Skip to content

Chapter 2 · State, reducers, and concurrent updates ​

Who merges results when two nodes finish concurrently? Two deterministic reviewers write to one list so you can observe how a reducer defines update semantics.

Mechanics and design choices ​

Fields without a reducer use replacement semantics; concurrent writes to the same ordinary field may fail. Annotated[list[str], operator.add] concatenates lists. A reducer defines data semantics, not a lock, and concatenation does not deduplicate. Do not make business correctness depend on parallel display order; sort when testing. A list of upstream node names creates an explicit join.

Example ​

python
import operator
from typing import Annotated, TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):
    findings: Annotated[list[str], operator.add]
    summary: str

def style(state: State):
    return {"findings": ["style: pass"]}

def content(state: State):
    return {"findings": ["content: pass"]}

def summarize(state: State):
    return {"summary": "; ".join(sorted(state["findings"]))}

builder = StateGraph(State)
builder.add_node("style", style)
builder.add_node("content", content)
builder.add_node("summarize", summarize)
builder.add_edge(START, "style")
builder.add_edge(START, "content")
builder.add_edge(["style", "content"], "summarize")
builder.add_edge("summarize", END)
result = builder.compile().invoke({"findings": [], "summary": ""})
assert len(result["findings"]) == 2
assert result["summary"] == "content: pass; style: pass"
print(result)

Run and verify ​

Install langgraph, save, and run. Verify both the list length and the joined summary. Start with an empty list to avoid re-appending historical results as new input.

Pitfalls ​

Do not add operator.add to every field merely to silence errors. Summing amounts differs from replacing balances. Repeated updates may duplicate entries; idempotent designs need stable IDs and explicit merging.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. How is a default field updated?

2. Does operator.add deduplicate?

3. What must the join wait for?

4. What is a reducer?

Hands-on exercises ​

  1. Add a third reviewer and update the join; assert all three results arrive.
  2. Write an ID-based deduplicating reducer and test duplicate input.
  3. Explain why summary does not need a concatenating reducer.

Official references ​

Verified on: 2026-09-17.