- Building multi-agent systems
- Re-using a set of nodes in multiple graphs
- Distributing development: when you want different teams to work on different parts of the graph independently, you can define each part as a subgraph, and as long as the subgraph interface (the input and output schemas) is respected, the parent graph can be built without knowing any details of the subgraph
Setup
Define subgraph communication
When adding subgraphs, you need to define how the parent graph and the subgraph communicate:| Pattern | When to use | State schemas |
|---|---|---|
| Call a subgraph inside a node | Parent and subgraph have different state schemas (no shared keys), or you need to transform state between them | You write a wrapper function that maps parent state to subgraph input and subgraph output back to parent state |
| Add a subgraph as a node | Parent and subgraph share state keys — the subgraph reads from and writes to the same channels as the parent | You pass the compiled subgraph directly to add_node — no wrapper function needed |
Call a subgraph inside a node
When the parent graph and subgraph have different state schemas (no shared keys), invoke the subgraph inside a node function. This is common when you want to keep a private message history for each agent in a multi-agent system. The node function transforms the parent state to the subgraph state before invoking the subgraph, and transforms the results back to the parent state before returning.Full example: different state schemas
Full example: different state schemas
- Transform the state to the subgraph state
- Transform response back to the parent state
Full example: different state schemas (two levels of subgraphs)
Full example: different state schemas (two levels of subgraphs)
This is an example with two levels of subgraphs: parent -> child -> grandchild.
- We’re transforming the state from the child state channels (
myChildKey) to the grandchild state channels (myGrandchildKey) - We’re transforming the state from the grandchild state channels (
myGrandchildKey) back to the child state channels (myChildKey) - We’re passing a function here instead of just compiled graph (
grandchildGraph) - We’re transforming the state from the parent state channels (
myKey) to the child state channels (myChildKey) - We’re transforming the state from the child state channels (
myChildKey) back to the parent state channels (myKey) - We’re passing a function here instead of just a compiled graph (
childGraph)
Add a subgraph as a node
When the parent graph and subgraph share state keys, you can pass a compiled subgraph directly toadd_node. No wrapper function is needed — the subgraph reads from and writes to the parent’s state channels automatically. For example, in multi-agent systems, the agents often communicate over a shared messages key.

- Define the subgraph workflow (
subgraphBuilderin the example below) and compile it - Pass compiled subgraph to the
.addNodemethod when defining the parent graph workflow
Full example: shared state schemas
Full example: shared state schemas
Subgraph persistence
By default, subgraphs start fresh on every invocation — they have no memory of previous calls. This is the right choice for most applications, including multi-agent systems where subagents are invoked as tools. If a subagent needs to remember previous conversations (multi-turn history), you can enable stateful persistence so state accumulates across invocations on the same thread.The parent graph must be compiled with a checkpointer for subgraph persistence features (interrupts, state inspection, stateful memory) to work. See persistence.
Stateless
Bothcheckpointer=False and checkpointer=None produce stateless behavior — each invocation starts fresh with no memory of previous calls. The difference is whether the subgraph supports interrupts within a single invocation.
Without interrupts
Compile withcheckpointer=False to opt out of checkpointing entirely. No checkpoints are written for the subgraph. The subgraph cannot use interrupt() and its state is not inspectable via get_state. This is the lightest-weight option.
With interrupts
The default behavior when you omitcheckpointer or set it to None. The subgraph inherits the parent’s checkpointer and each invocation gets a unique checkpoint namespace. Within a single invocation, the subgraph can use interrupt() to pause and resume.
The following examples use two subagents (fruit expert, veggie expert) wrapped as tools for an outer agent:
- Interrupts
- Multi-turn
- Multiple subgraph calls
Each invocation can use
interrupt() to pause and resume. Add interrupt() to a tool function to require user approval before proceeding:Stateful
Compile withcheckpointer=True to enable state that accumulates across invocations on the same thread. LangGraph strips task IDs from the checkpoint namespace (turning node:task_id|subnode:subtask_id into node|subnode), so the subgraph writes to the same namespace every time. The subgraph “remembers” previous calls — use this when a subagent needs multi-turn conversation history.
The following examples use a single fruit expert subagent compiled with checkpointer=True:
- Interrupts
- Multi-turn
- Multiple subgraph calls
Stateful subagents support
interrupt() just like per-invocation. Add interrupt() to a tool function to require user approval:Namespace isolation for parallel stateful subgraphs
Namespace isolation for parallel stateful subgraphs
When multiple subgraphs are called inside a node with
For stable, name-based namespaces, wrap each subgraph in its own
checkpointer=True, LangGraph assigns each invocation a position-based namespace suffix. The first invocation gets the base namespace (e.g., calling_node), the second gets calling_node|1, and so on. State persists per call position — if you reorder calls, each subgraph may load the wrong state.Subgraphs added as nodes do not have this limitation because each node has a unique name that becomes part of the namespace.| Subgraph pattern | Namespace with checkpointer=True | Isolation |
|---|---|---|
| Added as a node | node_name|internal_node | Name-based (stable) |
| Called inside a node | calling_node, calling_node|1, … | Position-based (order-dependent) |
StateGraph with a unique node name. Each wrapper must be a different compiled subgraph instance — you cannot invoke the same instance twice in a single node.Checkpointer reference
Control subgraph persistence with thecheckpointer parameter on .compile():
| Feature | Without interrupts | With interrupts (default) | Stateful |
|---|---|---|---|
checkpointer= | False | None | True |
| Interrupts (HITL) | ❌ | ✅ | ✅ |
| Multi-turn memory | ❌ | ❌ | ✅ |
| Multiple calls (different subgraphs) | ✅ | ✅ | |
| Multiple calls (same subgraph) | ✅ | ✅ | ❌ |
| State inspection | ❌ | ✅ |
- Interrupts (HITL): The subgraph can use interrupt() to pause execution and wait for user input, then resume where it left off.
- Multi-turn memory: The subgraph retains its state across multiple invocations within the same thread. Each call picks up where the last one left off rather than starting fresh.
- Multiple calls (different subgraphs): Multiple different subgraph instances can be invoked within a single node without checkpoint namespace conflicts.
- Multiple calls (same subgraph): The same subgraph instance can be invoked multiple times within a single node. With stateful persistence, these calls write to the same checkpoint namespace and conflict — use per-invocation persistence instead.
- State inspection: The subgraph’s state is available via
get_state(config, subgraphs=True)for debugging and monitoring.
View subgraph state
When you enable persistence, you can inspect the subgraph state using the subgraphs option. Withcheckpointer=False, no subgraph checkpoints are saved, so subgraph state is not available.
Viewing subgraph state requires that LangGraph can statically discover the subgraph — i.e., it is added as a node or called inside a node. It does not work when a subgraph is called inside a tool function or other indirection (e.g., the subagents pattern). Interrupts still propagate to the top-level graph regardless of nesting.
- Stateless
- Stateful
Returns subgraph state for the current invocation only. Each invocation starts fresh.
Stream subgraph outputs
To include outputs from subgraphs in the streamed outputs, you can set the subgraphs option in the stream method of the parent graph. This will stream outputs from both the parent graph and any subgraphs.- Set
subgraphs: trueto stream outputs from subgraphs.
Stream from subgraphs
Stream from subgraphs
- Set
subgraphs: trueto stream outputs from subgraphs.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.