Lesson 4 / 29
State Reducers: Replace or Accumulate
Control how node updates merge into the state.
Last-write-wins versus append
By default a node's returned value overwrites that state key. For keys that should accumulate (a message list, a log, collected results) you attach a reducer with Annotated[list, operator.add]: updates are combined with the reducer instead of replacing. LangGraph's own add_messages reducer does this for chat messages and also merges by message ID. Reducers matter most with parallel branches: several nodes writing the same key in one step need a reducer to define how to merge, otherwise you get an error. Decide per key whether it is "latest value" or "append".
Reducer versus overwrite, run
I ran this offline with langgraph 1.2.12 and langchain-core 1.6.6 in a Python virtual environment. No API key or model is needed because plain Python functions stand in for the model, so the output is repeatable. Both nodes return a log entry and a score. The log key has an operator.add reducer, so it accumulates both entries; score has none, so the last write (2) wins.
import operator
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
log: Annotated[list, operator.add] # reducer: updates are appended, not replaced
score: int # no reducer: last write wins
def a(state): return {"log": ["a ran"], "score": 1}
def b(state): return {"log": ["b ran"], "score": 2}
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({"log": [], "score": 0}))
Output:
{'log': ['a ran', 'b ran'], 'score': 2}Use add_messages for chat
For conversation history, Annotated[list, add_messages] appends new messages and updates existing ones by ID.
Quick check: What does a reducer on a state key do?
- Deletes the key
- Defines how new updates combine with the existing value
- Compiles the graph
- Speeds up the GPU
Answer
Defines how new updates combine with the existing value — Without a reducer the latest write replaces the old value.