Skip to main content

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 uses TypedDict to define your state structure:
TypeScript-style for those familiar:

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

Multiple nodes updating the same non-reducer key in one step raises InvalidUpdateError.

Built-in Reducers

List Operations

Message History

LangGraph provides specialized support for message lists:
The 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 state
  • output_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:
Benefits:
  • 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:
See Checkpointing for more details.

Best Practices

  • Use TypedDict for simple state, Pydantic for validation
  • Keep state flat when possible
  • Use meaningful, descriptive key names
  • Document reducer behavior clearly
  • Always use reducers for list/dict accumulation
  • Test reducer logic independently
  • Be cautious with non-deterministic reducers
  • Consider order-independence
  • 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