Overview
State is the backbone of LangGraph applications. Every node reads from and writes to a shared state object, enabling coordination and data flow across your graph.State Schema
TypedDict Schema
The most common approach usesTypedDict to define your state structure:
Pydantic Models
For validation and more complex types, use Pydantic:Annotated Types with Reducers
Reducers control how multiple updates to the same key are merged:Reducers receive
(current_value, new_value) and must return the merged result.How State Updates Work
Node Return Values
Nodes return partial state updates. Only specified keys are updated:Update Semantics
Built-in Reducers
List Operations
Message History
LangGraph provides specialized support for message lists:add_messages reducer:
- Appends new messages
- Updates messages by ID if they already exist
- Removes messages when passed
RemoveMessage(id=...)
Numeric Aggregation
Input and Output Schemas
Control what data enters and exits your graph:input_schema: Validates and maps input to internal stateoutput_schema: Filters internal state before returning- All three schemas must share overlapping keys
Channels: The State Backend
Under the hood, state is stored in channels. Each state key maps to a channel:Channel Types
LastValue
Stores the most recent value. Default for non-annotated keys.
BinaryOperatorAggregate
Applies a reducer function to accumulate updates.
Topic
PubSub channel for multi-value communication.
EphemeralValue
Temporary value that doesn’t persist across steps.
Direct Channel Usage (Advanced)
Node-Specific Input Schemas
Nodes can have their own input schemas, different from the graph state:- Clearer node signatures
- Reduced coupling
- Easier testing
Overwriting Reducers
Bypass a reducer to replace a value entirely:Context vs State
LangGraph separates mutable state from immutable context:State Persistence
With a checkpointer, state is automatically persisted:Best Practices
Schema Design
Schema Design
- Use TypedDict for simple state, Pydantic for validation
- Keep state flat when possible
- Use meaningful, descriptive key names
- Document reducer behavior clearly
Reducers
Reducers
- Always use reducers for list/dict accumulation
- Test reducer logic independently
- Be cautious with non-deterministic reducers
- Consider order-independence
Performance
Performance
- Minimize state size for faster checkpointing
- Use input/output schemas to limit data transfer
- Consider lazy loading for large objects
- Store references, not full objects when possible
Next Steps
Nodes & Edges
Learn how nodes consume and update state
Checkpointing
Persist state across invocations