langgraph "MessageGraph" deprecated: migrate to StateGraph with messages key
Migrates a deprecated LangGraph MessageGraph to StateGraph with a messages key. Use when you see the MessageGraph deprecation warning, when upgrading LangGraph, and when you want the same message-list behavior on the supported API. Not for custom state schemas or brand-new graphs (build those on StateGraph directly).
TL;DR
MessageGraph is deprecated; the replacement is StateGraph with a messages key in the state. Swap the constructor, declare the state with an add_messages reducer, and keep your nodes and edges as they are.
Error
LangGraphDeprecationWarning: MessageGraph is deprecated. Please use StateGraph with a messages key instead.Steps
- Declare a state schema with a messages key using the add_messages reducer:
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages
class State(TypedDict):
messages: Annotated[list, add_messages]Expected output: a state type that appends messages instead of overwriting them, matching old MessageGraph behavior.
- Replace the MessageGraph constructor with StateGraph carrying that state:
# before
# graph = MessageGraph()
from langgraph.graph import StateGraph
builder = StateGraph(State)Expected output: no deprecation warning on construction.
- Port the nodes. MessageGraph nodes received a message list; StateGraph nodes receive the state dict and return a messages update:
def my_node(state: State):
reply = llm.invoke(state["messages"])
return {"messages": [reply]}Expected output: each node appends its reply to the running message list, exactly like before.
- Wire entry point and edges the same way, then compile and run a parity test:
builder.add_node("my_node", my_node)
builder.set_entry_point("my_node")
builder.set_finish_point("my_node")
graph = builder.compile()Expected output: identical conversation output to the old MessageGraph, with no deprecation warning.
When to use
- Your code constructs MessageGraph anywhere
- You are upgrading LangGraph and the warning appears in logs
- A tutorial or older codebase you inherited uses MessageGraph
When not to use
- You need custom state fields beyond messages (declare a fuller TypedDict on StateGraph, this migration is just the starting point)
- You are writing a new graph from scratch (start on StateGraph directly)
- You pinned an old LangGraph and cannot upgrade (the warning is harmless until you do)
Variant phrasings
"MessageGraph is deprecated, use StateGraph" import warning
Same migration. The warning fires at import or construction time depending on version.
migrating a message-only subgraph
Apply the same swap inside the subgraph builder, then compile it and add it to the parent as a single node.
Why it happens
MessageGraph was always a thin wrapper around StateGraph with a pre-filled messages state. The maintainers deprecated the wrapper to keep one code path, so the messages-key pattern is now the canonical way to get the same behavior.
Edge cases
- Nodes that returned a bare message must now return
{"messages": [...]}; a bare return silently drops the reply. add_messageslives inlanggraph.graph.message; importing it from elsewhere breaks on newer versions.set_entry_point/set_finish_pointstill exist on StateGraph, so simple linear chains port with no edge changes.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_QpWPsktAPfOu9ZRPTjhnsQ