DS DevShelfHub Projects · AI tools
Tutorials / LangChain / Reference / Methods / .add_messages()
Method Message reducers

.add_messages(): Reference Guide

By DevShelfHub

Append messages to conversation history.

What is .add_messages()?

add_messages is a LangGraph reducer function — not a method on an object, but a callable you annotate in a state TypedDict to tell LangGraph how to merge state updates for the messages field. When a node returns {"messages": [new_message]}, LangGraph uses the registered reducer to combine the returned value with the existing state. With add_messages as the reducer, incoming messages are appended to the existing list rather than replacing it.

The function signature is add_messages(left: list, right: list | BaseMessage) -> list. The first argument is the current state, the second is the new value from the node's return dict. LangGraph calls this automatically — you do not invoke add_messages() directly in your node functions. Registration happens in the Annotated type hint on the state TypedDict: messages: Annotated[list[BaseMessage], add_messages].

Starting in LangGraph 0.2, add_messages also handles message deduplication via message IDs. If a returned message has the same id as an existing message in state, add_messages updates the existing message in place rather than appending a duplicate. This is how streaming partial message chunks get reassembled: each chunk arrives with the same id, and the reducer progressively replaces the partial message with the latest chunk.

Use Cases

  • Conversation management
  • Message history
  • State updates
  • History composition
  • Message ordering
  • Duplicate handling

Key Features

  • Append messages
  • Ordering
  • Duplicate prevention
  • Simple API
  • State integration
  • History building

When NOT to Use

Direct list append is fine for simple cases.

Notes

Register as reducer, do not call directly in nodes

Register add_messages in the TypedDict annotation: messages: Annotated[list[BaseMessage], add_messages]. In your node function, just return {"messages": [new_msg]} and LangGraph calls the reducer automatically. Calling add_messages(state['messages'], ...) directly inside a node function is redundant and confusing.

Message ID upsert for streaming

LangGraph 0.2+ uses message IDs for upsert behavior. If you return a message with the same id as an existing message, add_messages updates it in place rather than appending. Set the same id on streamed chunks to reassemble partial messages without duplicates.

Clearing history requires RemoveMessage

To clear messages (e.g., reset a conversation), return a RemoveMessage for each message you want to delete, or use the delete_messages helper. Simply returning {"messages": []} is a no-op — add_messages appends an empty list, leaving existing messages intact.

All message types must be JSON-serializable

For LangGraph persistence (checkpointing), all message subclasses must serialize to JSON. Custom BaseMessage subclasses need the type attribute set correctly. Use LangChain's built-in types (HumanMessage, AIMessage, ToolMessage) whenever possible.

Method Signature

python
state['messages'] = add_messages(state['messages'], new_message)

Parameters

Parameter Type Required Purpose
messages List[BaseMessage] Yes Existing messages

Return Value

Type:

List[BaseMessage]

Description:

Updated messages

Example Output:

[message1, message2, ...]

Code Examples

Direct call (non-graph context)

python
from langgraph.graph import add_messages

state['messages'] = add_messages(
    state['messages'],
    HumanMessage(content='Hello')
)

Annotated state definition with add_messages reducer

python
from typing import Annotated
from typing_extensions import TypedDict
from langchain_core.messages import BaseMessage
from langgraph.graph import add_messages, StateGraph, END

class State(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]

def chatbot(state: State):
    response = llm.invoke(state["messages"])
    return {"messages": [response]}

graph = StateGraph(State)
graph.add_node('chatbot', chatbot)
# add_messages reducer appends response automatically

ID-based upsert for streaming chunk reassembly

python
from langchain_core.messages import AIMessage

# Streaming: update a partial message by ID
chunk1 = AIMessage(content="Hello", id="msg-1")
chunk2 = AIMessage(content="Hello world", id="msg-1")

state = {"messages": []}
state["messages"] = add_messages(state["messages"], chunk1)
state["messages"] = add_messages(state["messages"], chunk2)
print(len(state["messages"]))  # 1 — updated in place, not duplicated
print(state["messages"][0].content)  # Hello world

Common Mistakes

❌ Direct append to messages list

✅ Use add_messages() for proper handling

Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with .add_messages() and the wider framework.

.add_messages() FAQ

What does .add_messages() do in LangChain?

Append messages to conversation history. add_messages is a LangGraph reducer function — not a method on an object, but a callable you annotate in a state TypedDict to tell LangGraph how to merge state updates for the messages field. When a node returns {"messages": [new_message]}, LangGraph uses the registered reducer to combine the returned value with the existing state. With add_messages as the reducer, incoming messages are appended to the existing list rather than replacing it. The function signature is add_mes…

Which LangChain classes support .add_messages()?

.add_messages() is available on Message reducers. Pin your installed LangChain version and verify the method exists in that release before deploying.

When should I use .add_messages()?

Use .add_messages() when your LangChain chains, agents, or pipelines need the behavior described in this guide.

What does .add_messages() return?

.add_messages() returns a List[BaseMessage]. Updated messages

Does .add_messages() have an async equivalent?

.add_messages() does not have a documented async variant. Avoid .add_messages() Direct list append is fine for simple cases.

Where can I explore more LangChain API reference pages?

Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.