大多数构建者仍然把 AI Agent 设计成一条直线
先研究
再写作
后审查
最后发布
每一步都要等待前一步完成,即使其中一半根本不需要前一步的结果
系统不会分支
不会并行
不知道如何恢复
它只会不停地往同一个上下文窗口里塞内容,直到 Agent 变得缓慢、混乱或成本高昂
问题不再出在提示词上
问题在于工作的形状
这正是图工程要解决的问题
我会在 Substack 上发布关于 AI Agent、工作流和生产系统的实用拆解
图工程到底是什么
图工程是一种把 Agent 工作流变成一张显式执行图的实践
与其把每个决策都藏在一个模型循环里,不如把系统定义为节点和边
1节点 = 一个有边界的工作单元2边 = 两个节点之间真实的依赖关系3状态 = 在节点之间存续的数据4路由 = 选择下一条边的规则5闸门 = 决定工作能否继续的检查
节点可以是 Agent、工具调用、确定性函数、验证器或人工审批步骤
边规定了下一步允许运行什么,以及哪些数据可以跨过边界
图决定哪些循环运行、按什么顺序运行、有哪些分支、合并和恢复路径
循环帮助一个 Agent 改进自己的工作;图把许多循环协调成一个系统
1. 别把每个"然后"都当成依赖
大多数 Agent 工作流是线性的,因为人们写指令时就是这样写的
做 A,然后 B,然后 C
但顺序不等于依赖
如果 B 不使用 A 的输出,B 就没有理由等待
1不好23收集市场数据 -> 检查仓库 -> 查看竞品定价45更好67 -> 收集市场数据 ---------8用户请求 -> 检查仓库 ----------> 综合汇总9 -> 查看竞品定价 ----
图工程要问的第一个问题很简单
下一步真的需要读取上一步的输出吗?
如果答案是否定的,就砍掉这条边
这一个小小的改变,通常就能把一条缓慢的链变成一张快速的并行图
2. 给每个节点一个契约
无法精确描述的节点,就是无法路由、测试或替换的节点
每个有用的节点都需要四样东西
- 一个职责
- 明确的输入
- 结构化的输出
- 清晰的失败状态
1{2 "node": "source_researcher",3 "input": {4 "topic": "string",5 "source_type": "primary"6 },7 "output": {8 "claim": "string",9 "source_url": "string",10 "confidence": "high | medium | low"11 },12 "failure": "no_primary_source_found"13}
自由文本会迫使下一个节点去猜测发生了什么
结构化输出能把模型响应变成图可以信任的东西
这也让节点变得可替换
只要契约不变,你就可以更换模型、提示词或工具,而无需重建整个系统
3. 把边当成数据契约,而不是箭头
边不应该意味着"B 在 A 之后"
它应该意味着"A 产生了 B 可以消费的数据"
这个区别很重要,因为大多数工作流的管道操作不需要再调用一次模型
展平数组、去重、过滤空值、检查状态和连接记录,这些都是确定性操作
1const usable = results2 .filter(Boolean)3 .flatMap(result => result.items)45const unique = [...new Map(6 usable.map(item => [item.source_url, item])7).values()]
这里不需要 Agent
把模型调用留给需要判断的地方
用代码处理管道操作
每条边都是一个 Agent 的图,等于在为它自己的连接线付 token
4. 掌握几乎所有 Agent 图背后的四种形状
你不需要五十种模式
大多数生产环境的图是四种形状的组合
链式
1A -> B -> C
当每一步都真正需要上一步的输出时使用
它简单、可预测,但往往比实际需要的更慢
菱形
1 -> B1 -2A -> -> B2 --> C3 -> B3 -
把一个任务拆分成独立的分支,并行运行,然后合并结果
这是研究、代码审查、尽职调查和市场扫描的主力结构
路由
1 -> 快速路径2分类 ---3 -> 全面审计
检查状态,只选择任务需要的路径
小任务保持低成本
高风险的活儿用更深的图
受控循环
1工作 -> 验证 -> 通过 -> 退出2 |3 -> 失败 -> 反馈 -> 工作
只有当证据表明结果不完整时才重复
每个循环都需要硬性停止条件、预算和收敛规则

5. 先扇出独立工作,再有意识地合并
并行是最容易理解的图优势,也是最容易被滥用的
如果五个节点相互独立,就一起运行
1const settled = await Promise.allSettled(2 sources.map(source => researchNode(source))3)45const findings = settled6 .filter(result => result.status === "fulfilled")7 .map(result => result.value)
一个分支失败不应该拖垮其他四个
但不要在每个阶段后面都放一道屏障
只有当下一个节点需要完整集合时,合并才值得等待
比如跨来源去重、给所有候选排名、比较备选方案,或判断覆盖是否完整
如果每个条目都可以独立继续,就让图保持流式处理
并行并不自动等于快。你的拓扑结构决定了系统在哪里等待
6. 让路由可检查
模型可以做判断
图应该限制这个判断可以触发什么
1const decision = await classifyRisk(change)23switch (decision.severity) {4 case "low":5 return quickReview(change)67 case "high":8 return fullParallelAudit(change)910 default:11 return humanReview(change)12}
分类器是概率性的
允许的路径是确定性的
这让你获得模型的灵活性,同时不会让它对系统拥有无限控制权
OpenAI 的可视化 Agent Builder 让这种转变变得显而易见:Agent 行为越来越被设计成可检查的工作流,而不是隐藏的提示词链
https://x.com/OpenAIDevs/status/1975269388195631492
7. 把验证放在边上
图里杠杆率最高的节点,往往是那个不产生任何新内容的节点
它的职责是阻止不合格的成果流向下一环节
验证器可以检查
- 每个论点是否有来源
- 引用的来源是否支持该论点
- 代码是否通过测试
- 结果是否符合要求的模式
- 是否有另一条独立路径得出相同结论
1生成器 -> 验证器 -> 通过 -> 综合器2 |3 -> 失败 -> 修复
不要要求同一个 Agent 在一个上下文里既生成、又审批、还发布自己的工作
把角色分开
把提示词分开
把失败边界分开
Anthropic 的生产研究系统在更大规模上遵循这个逻辑:一个主导 Agent 协调并行的子 Agent,综合各类发现,再由一个专门的引文阶段在结果到达用户之前附加证据
https://x.com/claudeai/status/2041927687460024721

8. 状态是大多数图隐藏的部分
盒子和箭头看起来很干净,直到系统需要从崩溃中恢复
生产环境的图需要持久化状态
1task_id2current_node3completed_nodes4artifacts5decisions6evidence7budgets8retry_counts9human_approvals
不要在节点之间传递巨大的对话记录
传递产物的引用
研究节点应该存储报告,然后返回路径、ID 或结构化摘要
审查者应该直接读取产物,而不是经由三个 Agent 收到一个压缩转述
这减少了上下文丢失,也让每次流转都可审计
图应该能在任何时刻回答三个问题
1已经发生了什么2系统为什么选择这条路线3执行可以从哪里安全恢复
如果它回答不了这些问题,那这个图还只是个演示
9. 只在收敛时加入循环
当工作量事先无法确定时,循环是有用的
发现 bug、深度研究和迭代修复都是很好的例子
但"重复直到满意"不是停止条件
要使用可衡量的收敛
1let dryRounds = 02let iteration = 03const seen = new Set()45while (dryRounds < 2 && iteration < 6) {6 const findings = await discover()7 const fresh = findings.filter(item => !seen.has(item.key))89 fresh.forEach(item => seen.add(item.key))10 dryRounds = fresh.length === 0 ? dryRounds + 1 : 011 iteration += 112}
注意系统记住了什么
它会和所有已经见过的结果去重,而不仅仅是那些通过验证的结果
否则被否决的想法会不断返回,图就要永远为重新发现同一个死胡同付费
每个受控循环都需要
- 一个完成测试
- 一个最大轮数
- 一个 token 或成本预算
- 一份先前尝试的记录
- 一条收敛失败时的升级路径
10. 把失败设计成局部事件
在链中,一个步骤出错可能会冻结整个工作流
在图中,失败应该被限制在尽可能小的边界内
每个节点都需要一个策略
1RETRY 工具或网络的瞬时故障2FALLBACK 首选模型或来源不可用3SKIP 可选分支失败4REPAIR 输出未通过验证5ESCALATE 风险或不确定性超过阈值6STOP 达到预算、安全或权限边界
在昂贵的节点之后设置检查点
让写入具备幂等性,这样重试不会产生重复的副作用
当并行工作进程修改文件时,给它们隔离的工作空间
记录每次路由决策以及产生该决策的状态
可靠性不是来自祈祷每个节点都成功
而是来自决定当某个节点失败时图该怎么做
11. 拓扑结构就是你的成本模型
图并不自动比单个 Agent 更便宜
如果每个任务都会生成一支舰队,它会烧掉多得多的 token
形状同时控制延迟和成本
用更便宜的模型做有边界的提取、分类和格式化
用更强的模型做拆解、综合和困难的验证
让简单任务走短路径
把完整的图留给值得的工作
1简单请求 -> 小模型 -> 快速检查 -> 完成23复杂请求 -> 规划器 -> 并行专家4 -> 验证器5 -> 强综合器6 -> 人工闸门
Anthropic 报告说,多 Agent 研究在广度优先的工作上能显著胜过单个 Agent,但也会消耗多得多的 token
这就是代价
图工程不是要最大化 Agent 的数量
而是只在并行、专业化或独立验证能创造足够价值的地方投入协调成本
12. 用于研究和发布的生产级图
这是一个把想法变成有引用的文章的实用图
1 -> 公司来源 -----2主题 -> 范围 -> 拆解 -> 论文 --------------> 去重3 -> 专家文章 ---------4 |5 v6 发布 <- 人工闸门 <- 最终检查 <- 草稿7 | ^8 -> 失败 -> 修复
这个系统的工作方式如下
- 范围节点定义问题、受众和完成标准
- 拆解节点创建独立的研究通道
- 研究节点在各自的独立上下文中并行运行
- 确定性代码去重并规范化来源
- 草稿节点基于结构化证据写作
- 检查器验证论点、引用、风格和缺失的章节
- 未通过的检查只将相关章节送回修复
- 发布前由人工批准最终产物
这不是一个假装成团队的巨型 Agent
这是一个拥有明确职责、状态和权限的系统

什么时候图是错误答案
不要把所有提示词都变成架构图
在以下情况保持单个 Agent 的单循环
- 任务很短
- 一个上下文能装下所有相关信息
- 没有独立的分支
- 失败成本很低
- 人工可以快速审查最终结果
在以下情况转到图
- 工作可以并行
- 不同节点需要不同工具或权限
- 输出需要独立验证
- 任务必须能在中断后恢复
- 多个循环需要共享状态
- 成本和权限需要按路由控制
从一个循环开始
只有当依赖关系迫使你时,才去画图
图工程检查清单
发布之前,问自己
1[ ] 每条边是否都携带真实的数据或权限2[ ] 每个节点是否都只有一个有边界的任务3[ ] 输入和输出是否都是结构化的4[ ] 独立节点是否都可以并行运行5[ ] 合并是否只放在需要完整集合的地方6[ ] 重要结果是否在向下游传递前经过验证7[ ] 失败是否可以重试而不会产生重复的副作用8[ ] 图是否可以从检查点恢复9[ ] 每个循环是否有硬性停止条件和预算10[ ] 人工是否可以中断高风险路径11[ ] 你是否能解释每条路线被选中的原因12[ ] 图是否比它要解决的问题更简单
如果最后一个问题的答案是否定的,那就删掉节点
真正的转变
提示词工程改进指令
上下文工程控制模型看到什么
Harness 工程构建模型周围的环境
循环工程让一个工作单元通过反馈不断改进
图工程协调整个任务
1提示词 -> 上下文 -> Harness -> 循环 -> 图2消息 记忆 机器 运行 协调
模型只是一个节点
产品是围绕它的整个系统
只会写提示词的人要求 Agent 做更多;架构师重新设计图,让系统能更安全地做更多
继续阅读
- 可靠 AI Agent 背后的三个层次:Harness vs Loop vs Graph Engineering
- 我如何把 Obsidian + Claude 搭建成我的第二大脑
- 我如何设置 Claude 让它真正把活儿干完
- 我如何配置 Claude 项目让它们真正跑起来
- 我实际在用的 30 个 Claude 系统提示词
- 循环工程:2026 年每个构建者都需要的 AI 技能
- 大多数用户没发现的 30 个 Claude Code 设置、快捷键和工作流
- 我如何用 Claude Cowork 像一人公司一样运转
想看更短的笔记、新工具和我在测试的 AI 系统
想要更深入的拆解直接送到你面前
如果你读到了这里
收藏这篇文章,方便以后随时查阅这些模式
关注 @0xwhrrari,获取更多实用的 AI 系统
把这篇文章转发给那些还在把每个 Agent 都塞进一条长链里的构建者





