State and Reducers
How updates combine.
Here's a bug that catches everyone. You return a new message from a node, and your whole conversation disappears. That's because, by default, a new value replaces the old one. You've got to tell LangGraph when to combine things instead.

- Your conversation disappears
- New values replace old ones
- Tell it when to combine
Replace or add
This state has two fields. Latest is a plain string. Log has a reducer, which is operator dot add, meaning, add new items to the list. Both nodes write to both fields. Run it. Latest was overwritten, so only b survives. But the log kept both entries. That's all a reducer is. A rule for combining updates.
import operator
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
latest: str
log: Annotated[list, operator.add]
def a(state):
return {"latest": "from a", "log": ["a ran"]}
def b(state):
return {"latest": "from b", "log": ["b ran"]}
g = StateGraph(State)
g.add_node("a", a)
g.add_node("b", b)
g.add_edge(START, "a")
g.add_edge("a", "b")
g.add_edge("b", END)
print(g.compile().invoke({"latest": "", "log": []})){'latest': 'from b', 'log': ['a ran', 'b ran']}The recursion limit
Graphs protect you from endless loops. Here, a node keeps pointing to itself, forever. We set a recursion limit of ten. Run it. It stopped with a clear error. Think of this as a seat belt. It's not a substitute for the budgets and stop rules that you learned earlier, but it means that one bad edge can't run forever.
from typing import TypedDict
from langgraph.errors import GraphRecursionError
from langgraph.graph import StateGraph, START
class State(TypedDict):
n: int
g = StateGraph(State)
g.add_node("spin", lambda s: {"n": s["n"] + 1})
g.add_edge(START, "spin")
g.add_edge("spin", "spin")
app = g.compile()
try:
app.invoke({"n": 0}, {"recursion_limit": 10})
except GraphRecursionError:
print("Stopped by the recursion limit after ten steps")Stopped by the recursion limit after ten steps
Designing state
Good state design makes everything easier. Keep state small, and store big files elsewhere, with only a reference in the state. Use clear types. Separate messages from business data, such as the order number and the refund amount. Then your code can read real fields, instead of parsing chat text.
Summary
Replace by default, and combine with a reducer. Next, the feature that makes graphs worthwhile. Checkpoints.
Key takeaways- Default: replace
- Reducers combine
- Separate business data