Tutorial Image: LangGraph Tutorial: Working with LangChain Messages - Unit 1.1 Exercise 2

LangGraph Tutorial: Working with LangChain Messages - Unit 1.1 Exercise 2

Learn how to work with LangChain message types in LangGraph. This tutorial covers message hierarchy, type-safe storage, and state integration to build robust conversational agents.

๐ŸŽฏ What You'll Learn Today

This tutorial is also available in Google Colab here or for download here

Joint Initiative: This tutorial is part of a collaboration between AI Product Engineer and the Nebius Academy.

This tutorial explores message handling in LangGraph using LangChain's message types. We'll learn how to properly type and structure messages in our conversation state, which is essential for building robust conversational agents.

Key Concepts Covered

  1. Message Types and Hierarchy
  2. Type-Safe Message Storage
  3. Message Content Access
  4. State Integration with LangChain

Let's break it down step by step:

from typing import TypedDict
!pip install langchain-core
from langchain_core.messages import BaseMessage, HumanMessage

Step 1: Understanding LangChain Message Types

LangChain provides a robust message hierarchy starting with BaseMessage

BaseMessage
โ”œโ”€โ”€ HumanMessage     (User inputs)
โ”œโ”€โ”€ AIMessage        (Model responses)
โ”œโ”€โ”€ SystemMessage    (System instructions)
โ””โ”€โ”€ FunctionMessage  (Function calls/returns)

Using these typed messages ensures proper handling of different message sources and enables advanced features like role-based processing.

class State(TypedDict):
    """Enhanced state container using LangChain's message types.

    This version of State enforces that all messages must be instances
    of BaseMessage, providing several advantages:

    1. Role-based message handling (human vs AI vs system)
    2. Structured message content
    3. Metadata support
    4. Chain/agent compatibility

    Attributes:
        messages: A strongly-typed list that only accepts BaseMessage objects
                 or its subclasses (HumanMessage, AIMessage, etc.)

    Note:
        BaseMessage is abstract - you'll always use one of its concrete
        subclasses like HumanMessage or AIMessage in practice.
    """

    messages: list[BaseMessage]

Step 2: Working with Typed Messages

Let's explore how to create, store, and access properly typed messages in our LangGraph state.

Initialize state with typed message list

state: State = {"messages": []}

Create a new message using HumanMessage Note: HumanMessage is a concrete implementation of BaseMessage

hello_message = HumanMessage(content="Hello!")

Add message to state

state["messages"].append(hello_message)

Access message content Messages provide structured access to their content

print(state["messages"][0].content)  # Output: "Hello!"

Message Type Benefits

Using LangChain's message types provides several advantages:

  1. Type Safety:
  • Can't accidentally add non-message objects to state
  • IDE autocompletion for message properties
  • Runtime type checking
  1. Role-Based Processing:
  • Easy to filter messages by type
  • Clear distinction between message sources
  • Proper handling of different message roles
  1. Structured Data:
  • Consistent message format
  • Built-in metadata support
  • Serialization capabilities

Key Takeaways

  1. Message Typing: Using BaseMessage ensures type safety and proper message handling
  2. Message Hierarchy: Different message types for different roles (Human, AI, System)
  3. Content Access: Structured access to message content and metadata
  4. State Integration: Properly typed messages integrate seamlessly with LangGraph

Common Pitfalls to Avoid

  1. Using raw strings instead of message objects
  2. Mixing different message types inappropriately
  3. Forgetting to specify message type in state definition
  4. Not handling message metadata when needed

Next Steps

  • Implement AIMessage handling for responses
  • Add SystemMessage for conversation configuration
  • Explore message additional_kwargs for metadata
  • Implement message filtering by type

Example of filtering messages by type

Advanced usage example

human_messages = [
   msg for msg in state["messages"]
   if isinstance(msg, HumanMessage)
]

Rod Rivera

๐Ÿ‡ฌ๐Ÿ‡ง Chapter