如何构建一个 Graph Engineering 系统
上一篇文章聊了图工程为什么存在。这篇聊怎么建。

先给你一个反直觉的起点:构建图工程的第一步,是不要建图。
第一步:先把 Loop 跑通
在画任何节点和边之前,把整个任务塞进一个 agent loop:
discover → plan → execute → verify → repeat
一个 agent,一套工具,一个明确的验证条件。修 bug、写报告、做研究------大部分任务在这个阶段就应该交付了。
什么时候证明 Loop 不够?不是「感觉可以拆」,是有具体信号。五个:
- 任务天然拆分为多个专业角色------需要研究员、撰稿人、审稿人,各有各的指令和工具
- 需要真正并行------同时搜 5 个数据源再合并,Loop 只能串行
- 不同步骤需要不同模型------便宜模型分诊、前沿模型推理,Loop 全程绑一个模型
- 需要可审计的分支路径------合规场景,必须能说清为什么走了 A 不是 B
- 验证器过载------一个检查要同时判正确性、语气、安全、完整性,一直漏东西
信号 5 是最该盯的。当单一验证器过载,修复方式不是更长的 prompt------是拆一个独立 reviewer 节点。这就是最小的合法图:两个节点,一条边,一个只干审查的 agent。
没有信号 → 别建图。有一个信号 → 加一个节点。有一堆信号 → 才是一张真正的图。
第二步:定义六个要素
当你确定需要图了,按这个顺序来。
1. 节点:谁在干活
三种节点类型:
| 类型 | 干什么 | 举例 |
|---|---|---|
| Agent 节点 | 跑完整 agent loop | 研究员(搜→读→总结) |
| 确定性节点 | 纯代码/API,不调 LLM | 数据抓取、格式清洗 |
| 控制节点 | 路由决策、合并、人工审批 | 分类器、审批门 |
每个节点一句话能说清职责。说不清 = 拆得不够细。
2. 边:下一步走哪
| 类型 | 逻辑 | 代码中的样子 |
|---|---|---|
| 直连 | A 完 → B | add_edge("A", "B") |
| 条件 | 判断结果决定走向 | add_conditional_edges("reviewer", decide, {pass: "ship", fail: "writer"}) |
| fan-out | 一个触发多个并行 | Send() 动态路由 |
| fan-in | 多个合并回一个 | 等所有并行节点完成后聚合 |
| 回环 | 回到前面节点 | reviewer 不通过 → 退回 writer |
最经典的图结构:Researcher → Writer → Reviewer。审稿人通过 = 发布,不通过 = 退回撰稿人重写。三个节点,四条边,其中一条条件边、一条回环边。
3. 共享状态:节点之间传什么
沿边流动的数据对象。每个节点从 state 读输入、写输出。最小结构:
python
class AgentState(TypedDict):
task: str # 原始任务
notes: list # 研究员 → 产出
draft: str # 撰稿人 → 产出
verdict: str # 审稿人 → pass / fail
iteration: int # 退回次数计数器
状态漂移是图腐烂的第一原因。 写死规则:审稿人只读 draft,撰稿人只读 notes,研究员不碰 draft。谁写哪个字段,清清楚楚。
4. 运行时:谁来跑这张图
不要手写状态机。三个成熟框架:
| 框架 | 特点 |
|---|---|
| LangGraph | Python/JS,StateGraph + add_node + add_edge,最成熟 |
| Google ADK | Go/Python/TS,模板化 workflow(sequential/parallel/loop) |
| AutoGen GraphFlow | 多 agent 对话式编排 |
以 LangGraph 为例,最小可运行图:
python
from langgraph.graph import StateGraph, END
graph = StateGraph(AgentState)
# 定义节点
graph.add_node("researcher", research_node)
graph.add_node("writer", write_node)
graph.add_node("reviewer", review_node)
# 定义边
graph.add_edge("researcher", "writer")
graph.add_edge("writer", "reviewer")
# 条件边:审稿决定是发布还是退回
def decide(state):
return "ship" if state["verdict"] == "pass" else "writer"
graph.add_conditional_edges("reviewer", decide, {
"ship": END,
"writer": "writer"
})
graph.set_entry_point("researcher")
app = graph.compile()
5. 治理层:生产必需的
图上线后,节点和边之外必须加三样东西:
身份。 每个 agent 节点有独立可审计的身份。「图干的」不是审计答案。用虚拟账户 + RBAC 实现,每个节点用自己的 token 调模型和工具。
预算。 图通过 fan-out 和重试放大 token 消耗。传播 graph_id / run_id / node_id 做节点级成本归因。给每个节点设独立的预算上限。
审批检查点。 敏感操作(删除文件、发邮件、调生产 API)不靠模型自觉。在那些确切的边上硬编码暂停------这是图工程带来的全新能力:结构检查点。
6. 验证器:每个节点的出口条件
最重要的要素。每个节点必须有明确的「做完」标准:
研究员:收集到 ≥ N 个来源,每个来源有摘要
撰稿人:初稿覆盖了 notes 里的全部要点
审稿人:正确性/语气/安全/完整性 分别打分,全部 ≥ 阈值
验证器才是瓶颈,不是模型。 一半的「我需要图」实际上是弱验证器在伪装。先把验证器改到不能再改,再拆节点。
第三步:每加一个节点就验证一次
不要一次画出五节点的图。建图应该像加人手------每招一个人,确认他确实带来了增量。
Loop 跑通 → 验证器强化 → 加 reviewer 节点 → 跑通 → 加研究员节点 → 跑通 → ...
每次加节点前问自己:能不能指出是五个信号的哪一个迫使了这个节点?不能 → 不加。
删节点比加节点更需要勇气。 如果你删掉一个节点后输出质量不变,那就删。图的大小不是 KPI------用最少的节点交付结果才是。
完整的构建检查清单
建图前:
- Loop 已经跑通,验证器已经强化到改无可改
- 至少有一个五信号之一明确出现
- 每个计划的节点能用一句话说清唯一职责
建图中:
- 共享状态的读写权限已明确(谁写哪个字段)
- 每个节点有独立的验证条件
- 敏感操作边上有硬编码的审批检查点
- 传播了 graph_id / run_id / node_id 用于成本追踪
建图后:
- 删掉任意一个节点,确认输出会变差(否则删)
- 图里的每个节点都是运行中的 loop(不是单次 LLM 调用)
- 整个图能一口气讲清楚,不需要画图也能跟同事说明白
最后
图工程是一种组织设计。你建的节点 = 你招的人,边 = 你定的协作流程,共享状态 = 你放在公共盘里的文档。
不要给一个只需要回邮件的问题建一整个部门。但当你真的需要研究员、撰稿人和审稿人协同工作时------图工程让这场协作可编程、可审计、可重现。
参考文献
- Graph Engineering Guide (2026) --- AI Jason,图工程完整指南:五层 AI 工程栈、图 vs Loop 决策表、LangGraph/ADK 先验技术
- Graph vs Loop: Which Should Your Agent Use? --- AI Jason,图 vs Loop 决策指南:五信号、决策树、验证器瓶颈、过早用图的代价
- Graph Engineering for Multi-Agent Systems: Architecture, Governance, and Observability --- Boyu Wang / TrueFoundry,企业级图工程:治理三支柱、七问清单、身份/预算/可观测性
- 3 Years of Graph Engineering with LangGraph --- LangChain 官方博客,LangGraph 三年实践:Agent 图不是 DAG、动态转换、节点内跑完整 Agent
- LangGraph Documentation --- LangChain,低层级编排框架和运行时,StateGraph / 节点 / 边 / 条件边 / Send API