StateGraph
Without a typed shared state, each node invents its own dict and the next node guesses keys. StateGraph makes the contract one schema.
A shared whiteboard the whole team writes on. Reducers are the rules: 'append to the message list, never erase history unless told'.
Visual Workflows
Start here — scroll inside each diagram frame to explore, then use + / − to zoom up to 200% if needed.
Overview
Scroll inside the frame to explore · use + / − to zoom up to 200%
Scroll inside the frame to explore · use + / − to zoom up to 200%
What lives in state
Scroll inside the frame to explore · use + / − to zoom up to 200%
Short-term working memory for this thread. Not your SQL database. Not a secret key.
Overwrite vs append
Scroll inside the frame to explore · use + / − to zoom up to 200%
Plain fields replace. messages with add_messages append. Pick the reducer on purpose.
Key Takeaways
- 1.StateGraph is the canvas: you declare the shape of state, then hang nodes and edges on it. State is a TypedDict or Pydantic model every node shares — messages, ticket_type, step count.
- 2.A reducer (Annotated + add_messages) says how to merge: append messages, do not overwrite the whole list. compile() freezes the drawing into a runnable. After compile you invoke, you do not add more nodes.
- 3.StateGraph(State) types every update. Channels are state keys.
- 4.Reducers define merge at each super-step. compile(checkpointer=...) is how persistence attaches — next modules. Until then, compile() with no checkpointer is a stateless run: every invoke starts blank.
Learn elsewhere
- →Checkpoints — persistence of this state
- →Nodes & Edges
Real Example
Scenario
State has messages and ticket_type. classify returns {ticket_type: 'billing'}. assistant returns {messages: [ai_reply]}. The reducer keeps both user and AI messages.
What you would do
List the keys on paper first: what must survive from node to node? Those keys are the schema. Extra junk in state is how prompts bloat.
Commands
Commands to Remember
StateGraph(State) # schema firstAnnotated[list, add_messages] # append, do not replacegraph.compile() # freeze before invokeKeep secrets out of state
Cheat Sheet
Quick recap
quick ref- •Schema first
- •Reducers merge
- •compile then invoke
- •State is not the DB
Common Mistakes
- ✕No reducer on messages, so each node wipes the chat history
- ✕Stuffing the database, the user object, and the API key into state
- ✕Adding nodes after compile — that object is already frozen
