「检索子流程」要在客服 Agent 和内部工具里复用——复制节点会双份维护。Subgraph 把子流程单独 compile,再作为单节点挂到主图,checkpoint 按 namespace 隔离。
1. 定位
| 维度 | 内容 |
|---|---|
| 角色 | 模块化图组合 |
| 输入 → 输出 | 子图 compile 产物 → add_node("sub", subgraph) |
| 核心 API | 嵌套 compile()、共享 State 字段 |
| 依赖 LangChain | 无 |
2. 图拓扑
子图 subgraph_research
| 节点 | 职责 | 写 |
|---|---|---|
fetch |
mock 检索 | research |
主图
| 节点 | 职责 | 读 | 写 |
|---|---|---|---|
sub_research |
嵌入子图 | — | research |
summarize |
汇总 | research |
summary |
边表(主图)
| 源 | 目标 | 类型 |
|---|---|---|
| START | sub_research | 固定 |
| sub_research | summarize | 固定 |
| summarize | END | 固定 |
3. invoke 生命周期
1 | 1. 主图调度 sub_research(子图入口) |
子图 superstep 计入主图调度;checkpoint ns 分子空间(见 checkpoint_ns 篇)。
4. 原理
4.1 共享 State schema
主图与子图 State 字段需兼容;子图只应写自己负责的字段。
4.2 编译顺序
先 sub = sub_builder.compile(),再 main_builder.add_node("sub_research", sub)。
4.3 主图 Saver、子图自动 ns
通常只在主图 compile(checkpointer=cp)。子图 compile() 不传 Saver 时继承同一实例:invoke 仍是 get_tuple / put,只是进子图节点时框架把 checkpoint_ns 改成 节点名:task_id,写入 storage[thread][该ns]。子图再传一个独立 Saver 会让恢复对不齐同一棵树。
5. 最小可运行示例
1 | from typing import TypedDict |
6. 执行追踪
| 步骤 | research |
summary |
|---|---|---|
| 初始 | “” | “” |
| sub fetch 后 | hits-for:langgraph | “” |
| summarize 后 | 同上 | TL;DR hits-for:langgraph |
重要配置参数
| 参数 | 类型 / 默认 | 作用与影响 | 参考起点 | 配置指导 |
|---|---|---|---|---|
add_node(name, compiled) |
CompiledGraph | 嵌子图 | 复用流程 | 先 compile 子图 |
| 共享 State | TypedDict | 字段对齐 | 公共字段 | 避免同名冲突 |
| 主图 checkpointer | 可选 | 含子图快照 | InMemorySaver | 子图一般不单独 cp |
stream(subgraphs=True) |
bool | 看子图事件 | 调试 | 06 专篇 |
| checkpoint_ns | 自动 | 子图隔离 | 04 ns 篇 | 勿手改 |
| 多 Subgraph | 多节点 | 多角色 | supervisor | 08+07 组合 |
7. 易踩坑
- 子图 State 字段与主图不一致:合并失败或丢字段。
- 子图单独 compile 又传独立 checkpointer:恢复顺序混乱。
- 子图过大:调试难,应拆清晰 IO 边界。
小结
- Subgraph = compile 后的图当节点;适合复用检索/审批子流程。
- State 字段在主子图间共享 schema。
- 主图绑一个 Saver;子图共用该实例,靠自动 checkpoint_ns 分抽屉。