Skip to main content
This guide explains the mechanics of using subgraphs. A subgraph is a graph that is used as a node in another graph. Subgraphs are useful for:
  • Building multi-agent systems
  • Reusing 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

Set up LangSmith for LangGraph development Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph—read more about how to get started with LangSmith.

Define subgraph communication

When adding subgraphs, you need to define how the parent graph and the subgraph communicate:

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.
  1. Transform the state to the subgraph state
  2. Transform response back to the parent state
This is an example with two levels of subgraphs: parent -> child -> grandchild.
  1. We’re transforming the state from the child state channels (myChildKey) to the grandchild state channels (myGrandchildKey)
  2. We’re transforming the state from the grandchild state channels (myGrandchildKey) back to the child state channels (myChildKey)
  3. We’re passing a function here instead of just compiled graph (grandchildGraph)
  4. We’re transforming the state from the parent state channels (myKey) to the child state channels (myChildKey)
  5. We’re transforming the state from the child state channels (myChildKey) back to the parent state channels (myKey)
  6. 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 to add_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. SQL agent graph If your subgraph shares state keys with the parent graph, you can follow these steps to add it to your graph:
  1. Define the subgraph workflow (subgraphBuilder in the example below) and compile it
  2. Pass compiled subgraph to the .addNode method when defining the parent graph workflow
  1. This key is shared with the parent graph state
  2. This key is private to the SubgraphState and is not visible to the parent graph

Subgraph persistence

When you use a subgraph, you need to decide what happens to its internal data between calls. Consider a customer support bot that delegates to specialist subagents: should the “billing expert” subagent remember the customer’s earlier questions, or start fresh each time it’s called? The checkpointer parameter on .compile() controls subgraph persistence: Per-invocation is the right choice for most applications, including multi-agent systems where subagents handle independent requests. Use per-thread when a subagent needs multi-turn conversation memory (for example, a research assistant that builds context over several exchanges).
The parent graph must be compiled with a checkpointer for subgraph persistence features (interrupts, state inspection, per-thread memory) to work. See persistence.
The examples below use LangChain’s create_agent, which is a common way to build agents. create_agent produces a LangGraph graph under the hood, so all subgraph persistence concepts apply directly. If you’re building with raw LangGraph StateGraph, the same patterns and configuration options apply—see the Graph API for details.

Stateful

Stateful subgraphs inherit the parent graph’s checkpointer, which enables interrupts, persistence, and state inspection. The two stateful modes differ in how long state is retained.

Per-invocation (default)

This is the recommended mode for most applications, including multi-agent systems where subagents are invoked as tools. It supports interrupts, persistence, and parallel calls while keeping each invocation isolated.
Use per-invocation persistence when each call to the subgraph is independent and the subagent doesn’t need to remember anything from previous calls. This is the most common pattern, especially for multi-agent systems where subagents handle one-off requests like “look up this customer’s order” or “summarize this document.” Omit checkpointer or set it to None. Each call starts fresh, but within a single call the subgraph inherits the parent’s checkpointer and can use interrupt() to pause and resume. The following examples use two subagents (fruit expert, veggie expert) wrapped as tools for an outer agent:
Each invocation can use interrupt() to pause and resume. Add interrupt() to a tool function to require user approval before proceeding:

Per-thread

Use per-thread persistence when a subagent needs to remember previous interactions. For example, a research assistant that builds up context over several exchanges, or a coding assistant that tracks what files it has already edited. The subagent’s conversation history and data accumulate across calls on the same thread. Each call picks up where the last one left off. Compile with checkpointer=True to enable this behavior.
Per-thread subgraphs do not support parallel tool calls. When an LLM has access to a per-thread subagent as a tool, it may try to call that tool multiple times in parallel (for example, asking the fruit expert about apples and bananas simultaneously). This causes checkpoint conflicts because both calls write to the same namespace.The examples below use LangChain’s ToolCallLimitMiddleware to prevent this. If you’re building with pure LangGraph StateGraph, you need to prevent parallel tool calls yourself—for example, by configuring your model to disable parallel tool calling or by adding logic to ensure the same subgraph is not invoked multiple times in parallel.
The following examples use a fruit expert subagent compiled with checkpointer=True:
Per-thread subagents support interrupt() just like per-invocation. Add interrupt() to a tool function to require user approval:

Stateless

Use this when you want to run a subagent like a plain function call with no checkpointing overhead. The subgraph cannot pause/resume and does not benefit from durable execution. Compile with checkpointer=False.
Without checkpointing, the subgraph has no durable execution. If the process crashes mid-run, the subgraph cannot recover and must be re-run from the beginning.

Checkpointer reference

Control subgraph persistence with the checkpointer parameter on .compile():
  • 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. With stateless checkpointing (checkpointer=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.
Returns subgraph state for the current invocation only. Each invocation starts fresh.

Stream subgraph outputs

To observe nested graph executions, we recommend event streaming: the stream.subgraphs projection discovers each nested run and exposes its path, messages, and values without parsing namespace strings.
  1. Set subgraphs: true to stream outputs from subgraphs.
  1. Set subgraphs: true to stream outputs from subgraphs.