# Sub-Graphs and Hierarchical Teams — LangGraph Agents & Multi-Agent Systems

Source: https://www.geekswithgeeks.com/en/langgraph-agents/x-subgraph

> Nest a graph inside another graph as a reusable component.

## A graph as a node

A compiled graph can be used as a **node** in a larger graph. This lets you build a team as its own graph (a research team with search and summarise nodes), test it alone, reuse it in several products, and compose **hierarchies** (a top-level supervisor routes to team supervisors, which route to workers). The parent and sub-graph can share state keys directly, or you wrap the sub-graph in a function that translates between the two state schemas, keeping each team's internal state **private**. Hierarchies keep each prompt small, but remember every layer adds latency, so keep them as shallow as the problem allows.

## A sub-graph used as a node, run

I ran this offline with langgraph 1.2.12 and langchain-core 1.6.6 in a Python virtual environment. No API key or model is needed because plain Python functions stand in for the model, so the output is repeatable. The inner graph upper-cases the text and adds "!". The outer graph prefixes "note:" and then runs the inner graph as a node, giving "NOTE: HELLO TEAM!". Both graphs here share the `text` key.

```python
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class Inner(TypedDict):
    text: str

def shout(s): return {"text": s["text"].upper()}
def punct(s): return {"text": s["text"] + "!"}

sub = StateGraph(Inner)
sub.add_node("shout", shout); sub.add_node("punct", punct)
sub.add_edge(START, "shout"); sub.add_edge("shout", "punct"); sub.add_edge("punct", END)
sub_app = sub.compile()

class Outer(TypedDict):
    text: str

def prefix(s): return {"text": "note: " + s["text"]}

g = StateGraph(Outer)
g.add_node("prefix", prefix)
g.add_node("polish", sub_app)           # a compiled graph used as a node
g.add_edge(START, "prefix"); g.add_edge("prefix", "polish"); g.add_edge("polish", END)
print(g.compile().invoke({"text": "hello team"}))

```

Output:

```
{'text': 'NOTE: HELLO TEAM!'}
```

## Keep team state private

Pass a sub-graph only the keys it needs and map its result back. This limits accidental coupling and context bloat.

**Quiz:** What is a benefit of sub-graphs?

- [ ] They are always faster
- [ ] They remove all state
- [x] Reusable, independently testable components
- [ ] They replace tools

*Answer:* Reusable, independently testable components. A compiled graph can be tested alone and plugged in as a node.
