第 8 章 · 子图与明确的输入输出边界
把可复用文本清理流程封装为子图。父图只关心输入文本与最终摘要,不应知道子图内部的临时字段。
工作机制与设计选择
当父子图状态键一致时,可把编译后的子图直接作为节点。键不一致时,用包装节点显式转换输入和输出。本例采取转换方式,防止子图内部词列表泄露到父状态。子图复用的是执行逻辑,并不自动提供不同用户的权限隔离。检查点继承、跨调用记忆与子图流式观察仍需按运行场景配置。
示例
python
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class ChildState(TypedDict):
raw: str
cleaned: str
def clean(state: ChildState):
return {"cleaned": " ".join(state["raw"].split())}
child_builder = StateGraph(ChildState)
child_builder.add_node("clean", clean)
child_builder.add_edge(START, "clean")
child_builder.add_edge("clean", END)
child = child_builder.compile()
class ParentState(TypedDict):
text: str
summary: str
def prepare(state: ParentState):
result = child.invoke({"raw": state["text"], "cleaned": ""})
return {"summary": result["cleaned"][:60]}
parent_builder = StateGraph(ParentState)
parent_builder.add_node("prepare", prepare)
parent_builder.add_edge(START, "prepare")
parent_builder.add_edge("prepare", END)
graph = parent_builder.compile()
result = graph.invoke({"text": " reusable graph ", "summary": ""})
assert result["summary"] == "reusable graph"
assert "raw" not in result
print(result)运行与验收
无需模型;运行后只应出现父图字段。单独调用 child.invoke,验证子图也能独立使用。这个例子不启用持久化,避免把状态映射与生命周期问题混在一起。
容易踩的坑
不要让父图直接依赖子图所有内部键,否则稍改子图就破坏调用方。对子任务上下文做裁剪,但保留它完成任务所需的明确验收标准。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 状态键不同怎么办?
2. 子图是权限隔离吗?
3. 父图应依赖什么?
4. 可独立测试子图吗?
动手实践
- 给子图添加内部计数,断言父图不暴露该键。
- 复用同一子图服务两个父流程,比较边界是否稳定。
- 写一个子图失败用例,明确父图应传播还是转换异常。
官方参考
核验日期:2026-09-17。