LangGraphLangGraph 1.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson →

Subgraphs: a graph inside a graph

A subgraph is a compiled graph used as a node inside another graph. It lets you build a piece once and reuse it, and keep a large flow readable.

Last updated: 27 Sep, 2026 · LangGraph 1.2

Once a flow grows past a handful of nodes, packing part of it into a subgraph keeps the parent graph small. If the subgraph shares state keys with its parent, you add it directly as a node.

Adding a compiled graph as a node

python
sub = sub_builder.compile()          # a compiled graph
parent.add_node("step", sub)          # use it as a node (shared state keys)

# different schema: wrap it and map the state in and out
def call_sub(state):
    out = sub.invoke({"bar": state["foo"]})
    return {"foo": out["bar"]}
parent.add_node("step", call_sub)

The shared state

Start with the imports and the shared state. Both the inner graph and the outer graph use this same State, so they share the text key.

python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):
    text: str            # the one key both graphs share

The inner graph

Build a small graph on its own. It has two nodes: clean strips the spaces off the text, and shout upper-cases it. Compiling turns this builder into prepare, a finished graph you can reuse.

python
sub = StateGraph(State)
sub.add_node("clean", lambda s: {"text": s["text"].strip()})   # remove the spaces
sub.add_node("shout", lambda s: {"text": s["text"].upper()})   # make it upper case
sub.add_edge(START, "clean")
sub.add_edge("clean", "shout")
sub.add_edge("shout", END)
prepare = sub.compile()          # a finished, reusable graph

The parent graph

Now the outer graph. It adds the compiled prepare as one node, then a tag node that puts [done] in front of the text. Because both graphs share the text key, the subgraph reads and writes it with no mapping.

python
parent = StateGraph(State)
parent.add_node("prepare", prepare)          # the compiled subgraph is one node
parent.add_node("tag", lambda s: {"text": "[done] " + s["text"]})
parent.add_edge(START, "prepare")
parent.add_edge("prepare", "tag")
parent.add_edge("tag", END)

Running the parent

Run the parent with text that has spaces around it. The subgraph trims and upper-cases first, then tag adds the label.

python
print(parent.compile().invoke({"text": "  hello  "}))

A subgraph inside a graph, end to end

The same pieces in one file, ready to run.

Example
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):
    text: str

# a small subgraph that trims and upper-cases
sub = StateGraph(State)
sub.add_node("clean", lambda s: {"text": s["text"].strip()})
sub.add_node("shout", lambda s: {"text": s["text"].upper()})
sub.add_edge(START, "clean")
sub.add_edge("clean", "shout")
sub.add_edge("shout", END)
prepare = sub.compile()

# the parent uses the subgraph as one node
parent = StateGraph(State)
parent.add_node("prepare", prepare)
parent.add_node("tag", lambda s: {"text": "[done] " + s["text"]})
parent.add_edge(START, "prepare")
parent.add_edge("prepare", "tag")
parent.add_edge("tag", END)

print(parent.compile().invoke({"text": "  hello  "}))

How the two graphs shared state

  • The subgraph prepare has its own nodes (clean, shout) but shares the text key with the parent.
  • The parent adds the compiled subgraph as a single node, so its whole flow runs in that one step.
  • Because the state key is shared, the subgraph reads and writes the parent's text with no mapping needed.

Two ways to add a subgraph

SituationHow
Subgraph shares the parent's state keysAdd the compiled graph directly: add_node("step", sub)
Subgraph has a different state shapeWrap it in a function that maps state in and out

Where subgraphs fit

  • A reusable piece, such as a retrieval-and-answer block used by several agents.
  • Breaking one large graph into named parts that are easier to read and test.
Watch out. If the shapes differ, do not add the subgraph directly; wrap it and map the keys, or a node will read a key that is not there.
Try it yourself
  • Add a third node to the subgraph that adds an exclamation mark, and rerun.
  • Give the subgraph a different key name and switch to the wrapper form.
  • Call prepare.invoke({"text": " hi "}) on its own. It runs as a normal graph.

Slow is fine. Stopping is the only problem.