图工程解析:它是什么,何时使用,何时不用
AI 使用率仅 5–10%,瓶颈不在模型而在你画的线性流程;学会把链式工作流重画为菱形并行图,用假边测试删冗余、独立验证器把关,就能指挥一支代理舰队而非单打独斗

大多数人对AI的使用只发挥了其实际能力的5%到10%。有一种更快的方法,它的潜力远比表面看起来要大。掌握它,你就能优化庞大的流程,而不仅仅是个人任务。
这正是大公司中真正职位背后的技能。区别在于,是完成一份工作,还是设计一百份工作如何完成。
我很早就幸运地接触到了这一点。当我在丹麦一所顶尖大学学习时,我们有一整门课程只讲一件事:如何将流程绘制成图表,并使其尽可能高效。
当时这感觉很抽象。现在,这正是顶级AI工程师在你的时间线上争论的焦点。
读完这篇文章,你将比你所关注的几乎任何人都更懂图工程: 图到底是什么,一个能立刻让你的AI更快的测试,一个能自我回报的单一模式,这些东西在哪些地方悄然失效,何时图是错误工具,以及如何在几分钟内自己构建一个真正的图。
1 - 这究竟从何而来。
一个月前,整个领域都在热议循环。随后彼得·斯坦伯格贴出了上面那句话,而互联网上刚学完循环的一角,一夜之间就宣布它们过时了。
这个玩笑之所以奏效,是因为它半真半假。如果你读过我的《循环》一文,就已经有了基础。循环是一个智能体反复改进一件事:尝试、检查、调整、再来。那是上个月的技能。
大家转向的并非更好的循环,而是循环的图谱,一个网络,其中循环相互监视、相互纠正,而非一个智能体独自追逐一个数字。
工程师们在几小时内就反驳了这股热潮,指出这是一个披着新名字的几十年前的老想法。他们说得对,而这正是好消息。一个已运行关键系统三十年的模式,正是你愿意托付工作的东西。
2 - 图谱究竟是什么。
图谱只是你AI工作的规划图,画出来以便一目了然。它回答两个问题:哪些任务需要完成,以及哪个任务必须等待哪个。
只有两个部分,把它们理清就能解决大部分困惑。
方框称为节点。它代表一项工作:一个智能体执行一个任务,有输入也有输出。研究竞争对手。撰写草稿。核实声明。
箭头称为边。它仅表示一个任务需要另一个任务产生的结果,因此必须等待。而且只有当有实际内容沿箭头传递时,箭头才算数。

节点负责思考。边承载结果。这就是全部词汇。一旦掌握,就再也不需要定义。
让一个节点在图里真正可用的,是一份契约:一个明确的职责、一个确定的输入、一个确定的输出。一个输出是整块自由文本的节点,只有人类能读懂。一个输出形状固定的节点,下一个节点无需猜测就能直接消费——这正是关键所在。
▸ NODE CONTRACT
JOB: research one competitor's pricing (one job, nothing else)
IN: { competitor: "name", url: "https://..." } ← passed in, never assumed
OUT: { price: number, plan: string, source: url, date: "YYYY-MM-DD" }
SCHEMA: enforced. if the agent returns free text, it's rejected and retried
WHY: a defined output is what lets the next node read this one
without a human in the middle. that is what makes it wire-able.3 - 找出虚假连边的测试
看看你如今跑的 AI 工作流,一步步走一遍。每一步只问一件事:这一步真的需要上一步的结果吗?
如果需要,这条边就是真实的,保持顺序。如果不需要,那就没有边,等待就是白费。这两个任务可以同时跑。
举个简单的例子:“先审查文件 A 找 bug,再审查文件 B 找 bug。”这读起来像是一个序列,但对文件 B 的检查永远不会去看文件 A 返回了什么。它们之所以一个接一个地跑,只是因为你是按这个顺序输入的。让它们并行跑,整个流程完成的时间就是较慢那个文件的耗时,而不是两者相加。
在你画的几乎任何工作流里,你都会发现两三条这样的虚假连边。每一条都是你白白扔掉的时间。

4 - 你当前的设置已经是一个图了。
当你把代理写成“先做A,然后B,然后C,然后D”时,你实际上已经画出了一个图。只是它是最可悲的那种:一条单一的直线链,每个节点只有一个箭头进、一个箭头出。
它运行正确。但它运行缓慢且容易出错,因为链没有冗余。如果C停滞,D永远不会发生,而A的工作被困在上游,无处可去。
图工程的第一项真正技能就是重新绘制这条链。拿你的线性工作流,对每个箭头,问那个“伪边”的问题。剪掉那些不携带数据的箭头,这条线就会塌缩成更宽的形状:几个可以同时运行的独立任务,它们共同喂给一个需要它们全部的任务。
这之所以重要,并非出于美观。一个有40步的线性工作流有40个顺序失败点,并且延迟是这40步的总和。同样的40个任务画成图,只有实际存在的依赖关系,通常只有三到五个,并且完成速度取决于最慢的那一层,而不是所有步骤的总和。这就是一个需要五分钟的任务和一个需要十五秒的任务之间的区别,而它们执行的是完全相同的工作。
模型从来不是瓶颈。你画的那条线才是。
5 - 唯一值得采用的模式:菱形。
你不需要上百种形状。观察任何严肃的智能体系统运作,同样的画面会反复出现。工作被拆分,多个工作者并行挖掘,有东西检查他们的发现,然后一切合并回一个答案。
这个画面被称为菱形,它几乎是今年你唯一需要的模式。它的正式名称值得记住:扇出、归约、综合。
扇出以获取广度,用普通代码归约以压缩,最后用智能体综合以撰写答案。

Claude 内部的研究功能在生产环境中正是如此运作。一个主导者规划角度,工作者并行收集,发现被检查,只有那时一份报告才会送到你手中。一旦你能看清菱形,你就不再问“如何让我的智能体做更多步骤”,而是开始问“拆分在哪里,合并在哪里”。第二个问题才是能扩展的关键。
以下是菱形在底层实际的样子。当你说“工作流”时,Claude 会自己编写一个像这样的简短脚本,并将协调作为代码运行,这就是为什么在智能体之间传递结果不会消耗额外上下文的原因。
// a market-scan graph — the diamond, written by Claude when you say "workflow"
const angles = [
"pricing vs the top 3 competitors",
"what buyers complain about in reviews",
"the feature gaps in the category",
"where the market moves in the next 12 months",
];
// FAN OUT — one researcher per angle, all at the same time
const raw = await parallel(
angles.map(a => () => agent({
task: `research: ${a}. every claim needs a source url + date.`,
schema: Finding, // validated output, not free text
model: "cheap", // boring node → cheap model
}))
);
// REDUCE — plain code, no model, no tokens
const findings = dedupeBySource(raw.flat().filter(Boolean));
// VERIFY — a FRESH skeptic per finding, tries to kill it
const survivors = await parallel(
findings.map(f => () => agent({
task: "try to disprove this. return keep | drop + why.",
input: f,
freshContext: true, // never reuse the researcher's chat
model: "strong", // judgment node → strong model
}))
).then(v => findings.filter((_, i) => v[i].verdict === "keep"));
// SYNTHESIZE — one agent writes the answer from what survived
return agent({ task: "one report, ranked by confidence, sources attached.",
input: survivors, model: "strong" });读一遍,整个架构便一目了然:工作独立时的扇出、在自由代码中完成的归约、在新上下文中进行的验证、在枯燥节点上使用廉价模型,而在需要判断力的地方使用强大模型,最后进行一次综合。无论是市场扫描、代码审查还是研究报告,背后都是同样的骨架。只需调整视角与提示词。
6 - 检查器才是关键所在。
现在,我们来谈谈几乎所有人都跳过的那部分,而这正是区分真正图表与昂贵玩具的分水岭。
每一次对AI自我审查的严肃测试都指向同一结论:模型会漏掉自身大部分的错误。让模型给自己的作业打分,它对自己总是太过宽容。
因此,你绝不能让执行任务的代理来检查自己的工作。
你要在边缘放置一个独立的节点。它的唯一职责,就是在发现结果继续前进之前,设法将其扼杀。如果它能存活下来,就通过;否则,就在那里终结。
这里有个没人点破的陷阱:那个检查器需要一个干净的上下文。
如果给它和工作者相同的聊天记录,它不是在检查任何东西,而是换了个字体在随声附和。共享一个上下文的代理图,不过是穿着戏服的单循环,它也会以同样的方式崩溃,只是更晚、更昂贵。
所以,要让验证器保持全新状态,拥有自己的上下文。它检查的是真实信号,不是“代理是否说完成了”,而是“测试是否真正通过”。
然后,将检查分为三个维度。它正确吗?它是最新的吗?来源是否真实?三个不同的视角能捕捉到十个相同视角所遗漏的问题。
▸ VERIFIER NODE
INPUT: one finding from a worker (the finding only, never the worker's chat)
CONTEXT: fresh and empty. it has not seen the work it is judging
CHECKS: three skeptics run in parallel, each with a different question
1. is it correct? → does the claim actually hold up
2. is it current? → is the source recent, not something stale
3. is the source real? → does the link resolve to the claim it's cited for
PASS: keep the finding only if a majority of skeptics let it live
FAIL: drop it before it ever reaches the final answer要记住的规则是:工作者与其验证器绝不能共享上下文。一旦共享,你就又回到了那个给自己的作业打分的单循环,只是账单更大了。
7 - 图结构真正失效的场景。
1. 上下文坍缩。
展开一千个节点,然后试图将所有一千个输出一次性喂入最终步骤,在综合开始之前,你便已超出上下文窗口的限制。
解决方案:分层进行扇入操作。分批处理结果,对每批进行摘要,然后合并摘要,而非直接处理原始堆积数据。
// layered fan-in — never pour 1,000 raw outputs into one step
const batches = chunk(results, 40); // groups of 40
const summaries = await parallel(
batches.map(b => () => agent({ task: "summarize this batch", input: b }))
);
return agent({ task: "write the answer from the summaries", input: summaries });
// the final step reads ~25 summaries, not 1,000 raw outputs2. 虚假独立性。
两个节点看似独立,因为它们的提示词从未提及彼此,但它们都写入同一文件或访问同一限流API。这就是一条隐藏的边。
当Bun团队首次将大型任务分发到多个代理时,他们共享同一工作区,结果互相覆盖了对方的成果。
解决方案:为每个工作单元提供独立的隔离空间,并审计共享资源,而不仅仅是共享数据。
// isolate the workers — no shared file, no shared workspace
await parallel(files.map(f => () => agent({
task: `refactor ${f}`,
worktree: true, // each agent works in its own git worktree
})));
// they can't overwrite each other, then the results merge cleanly
// rule: any two nodes writing the same file need an edge, not parallelism3. 静默节点故障。
在链式结构中,一个节点失败会中断一切,虽令人烦恼但显而易见。而在图结构中,两百个节点中一个失效,可能悄然混入看似完整的报告中。
解决方案:每个合并步骤都应将其输入数量与预期数量进行核对,并标记差异,而不是在数据缺失一半的情况下静默运行。
// fan-in guard — catch the node that quietly died
const results = (await parallel(jobs)).filter(Boolean); // dropped nodes = null
if (results.length < jobs.length) {
flag(`WARNING: ${jobs.length - results.length} of ${jobs.length} nodes returned nothing`);
}
// never synthesize on a partial set and call the report complete8 - 你真的需要它吗?
按照我文章的一贯传统,让我们诚实地分析一下,这到底对谁有用。
图(Graph)带来的是广度,它并不能带来更好的判断力。
它是一种用于并行处理的工具,适合同时开展多项独立工作。当工作本身并不宽泛时,线性流程从来就不是问题所在。
以下情况可以跳过图:
- 任务规模小或相对独立。比如添加一个函数、修复一个 Bug。此时协调工作纯粹是额外开销,单个代理(Agent)更快也更经济。
- 你希望审批每一个步骤。图的核心价值在于无需你干预即可并行运行,因此严格的控制反而会适得其反。
- 你还不清楚自己要找什么。探索性工作更适合使用一个你可以随时引导的代理,而不是一群被计划束缚的代理。
- 步骤之间确实存在依赖关系。强行将图应用于真正的顺序任务,只会增加成本,却无法带来任何加速。
- 判断的关键在于“伪边测试”。如果你找不到两个之间没有边(Edge)的任务,那就没有图可以构建。这只是一个循环,而循环本身没有问题。
9 - 无人愿听的部分:锚点。
这里有一个更深的陷阱,也是整个转变的真正教训。
设想你构建了完整的图谱。配对的检查器、审计节点、调整其他节点的元节点。每个节点监视另一个节点,而每一个节点都读取一份报告。
审计将数字与财务数字核对,而这些财务数字最初就来自同一个系统。
一切看似一致,实则无一得到验证。
这个图谱的失败方式与单一循环完全相同,只是更晚、更昂贵,并且在坠落途中亮起更多绿灯。

仅凭拓扑结构并不能换来真相。图谱需要锚点:那些不容争辩的节点。
实际运行过的测试,而非“应通过”的测试,确实通过了。真正到账的收入。确实留存的客户。
某些规则必须被冻结,那些优化器会试图削弱的规则,之所以被设为禁区,正是因为它们正是优化器为了取胜而会扭曲的规则。
图谱的诚实程度,取决于其中那些拒绝变动的部分。
以无法反驳的数字来评判它,它便能保持脚踏实地。让它自行评估自己的报告,它便会自信地犯错。
10 - 在 Claude Code 中亲手构建一个。
理论已经足够。如果你已决定这适合你,或者只是想尝试一下,那就动手构建一个吧。你可以在几分钟内构建一个真正的图,因为 Claude Code 已经提供了直接实现这一点的工具,称为动态工作流。
关键在于一个词:“工作流”。
把它放入你的提示中,Claude 就不再按单一步骤链工作。相反,它会编写一个简短的编排脚本,然后生成一支协调的子代理舰队来执行它。
重要的是,协调是代码,而非对话。在代理之间传递结果不会像聊天交接那样重新消耗你的上下文,这正是让一次运行能够扩展到整个舰队而不淹没会话的原因。
打开一个你熟悉的真实仓库,粘贴以下内容:
▸ GRAPH SPEC
GOAL: audit every route file under src/routes/ for missing auth checks
FAN OUT: one agent per file, all running in parallel
VERIFY: an independent checker on each finding, with fresh context
CAP: 20 files on this first run
ON FAIL: flag any file that doesn't return, never skip it silently
REPORT: one merged list of the routes missing auth
(start the prompt with the word "workflow" so Claude builds the graph)运行它,接下来会发生以下情况。
首先,Claude 会发出信号,表明它正在构建工作流,而不是以正常聊天方式回答,并在做任何事之前向你展示计划。你阅读并批准。
然后舰队运行。每个文件一个代理,同时进行,而你的会话全程保持空闲。
最终得到的不是二十个需要翻找的独立聊天,而是一份报告。中间结果存在于脚本内部,从未进入你的上下文,因此你实际看到的只有最终答案。
这就是一个图。一句话衍生出十几个代理。当一次运行结果良好时,保存它,它就会变成一个命令,你可以按名称永久重跑。

注意那个提示中的“20 文件”上限。它让你的首次运行成本低廉,同时也暗示了每个演示都避而不谈的事情:账单。
11 - 可直接粘贴的现成图表
以下每一个都是针对不同任务的同一颗钻石。在真实文件夹中打开 Claude Code,将方括号内的部分替换为你自己的内容,然后粘贴。“workflow”一词是告诉 Claude 构建一个协调的舰队,而不是一串单一步骤。在一切发布之前,保持你自己作为最后的批准者。
一个决策级的研究台。 取代一周的谷歌搜索或昂贵的分析师账单。你的问题被拆分成多个角度,研究人员同时深入挖掘,一个怀疑者攻击每项发现,只有幸存者才能进入报告。
▸ GRAPH SPEC
GOAL: decision-grade research on [your question]
FAN OUT: split into 5 distinct angles, one researcher per angle, in parallel
RULE: every finding needs a source link and a date
VERIFY: a skeptic attacks each finding and tries to disprove it, drop what fails
MERGE: survivors into one report ranked by confidence
SAVE: research-report.md, then show me the top findings
HUMAN GATE: change nothing after that without asking me
(start the prompt with the word "workflow" so Claude builds the graph)一个 SEO 内容机器。 每次运行生成一篇可排名的草稿,未经你的批准绝不发布。
▸ GRAPH SPEC
GOAL: one ranking-ready draft for [topic]
PARALLEL JOBS (run at once):
1. what the current top-ranking pages cover
2. the real questions people ask about this topic
3. what those top pages skip
MERGE: the three into an outline, then write a full draft
VERIFY: a fact-checker that flags every claim without a source
SAVE: drafts/ with the flagged claims listed at the top
HUMAN GATE: never publish anything
(start the prompt with the word "workflow" so Claude builds the graph)一个上市工具包。 一次运行完成全套发布包,每件作品都需你批准。
▸ GRAPH SPEC
GOAL: full launch kit for [product], aimed at [audience]
PARALLEL JOBS (research, run at once):
1. profile the buyer and the exact words they use
2. map where these buyers spend time online
3. collect how competitors pitch them
MERGE: a one-page positioning doc
HUMAN GATE: pause and show me the positioning doc before writing
PARALLEL JOBS (writing, from that doc):
1. landing page copy
2. a week of launch posts
3. a set of outreach messages
VERIFY: a checker compares every asset to the positioning doc, flags anything off
SAVE: launch-kit/, change nothing after that without asking me
(start the prompt with the word "workflow" so Claude builds the graph)一次覆盖整个代码库的重构清理。 其广度非单一上下文所能容纳。
▸ GRAPH SPEC
GOAL: find every function over 100 lines and propose a refactor for each
FAN OUT: one agent per file, in parallel
VERIFY: an independent checker on each proposed refactor, fresh context
DEDUPE: proposals against everything already seen
CAP: 50 files on this first run
REPORT: how many files came back, so nothing fails silently
(start the prompt with the word "workflow" so Claude builds the graph)一个规模未知的探索循环。 适用于那些在着手前无法预知工作量大小的任务,例如排查缺陷时,发现一个bug往往牵出另外三个。
▸ GRAPH SPEC
GOAL: hunt this repo for [security issues / broken error handling / dead code]
FAN OUT: run finders in parallel
DEDUPE: check each new find against everything already seen
VERIFY: an independent checker on the survivors
LOOP: keep going until two rounds in a row find nothing new, then stop
CAP: a hard limit on total agents so it can't run away
REPORT: final list ranked by severity
(start the prompt with the word "workflow" so Claude builds the graph)
Run one scoped, watch what it costs, then widen. When a run is good, save it, and every one of these becomes a single command you launch by name.12 - 成本与监督
图的开销比普通聊天高得多,高出一大截。真正变便宜的是协调,而不是工作本身。代理依然在消耗令牌,一群代理更是烧钱如流水。
最明显的例子是公开的。一位工程师用这套配置重写了Bun运行时,大约十一天内将约53.5万行的一种语言翻译成超过一百万行的另一种语言。靠人工来做,这接近一年的工作量。
它运行了约50个工作流,最多时有64个代理同时运行。
成本也大约花了16.5万美元的使用费,需要一个人来设计和全程监控,并且因为如此大量的AI编写代码是否能被安全审查而受到了真正的批评。
这就是它的真实面貌。一个图可以扩展到一千个代理,处理任何单一上下文都无法容纳的任务。但如果指向错误的任务或跳过锚点,它也可能在后台悄悄烧掉你的钱。
所以,重负载版本适合有预算、有上限、有监控能力的团队。如果你还没到那一步,你并没有错过什么。从小处开始,观察一次运行的成本,只有当一个运行证明了自己的价值后,再扩大规模。
13 - 这对你实际意味着什么。
这就是全貌。你现在知道了什么是图,它的优势所在,它的局限之处,以及它真正适合谁。
你了解了它的强项:广度,即同时进行的独立工作。而它的弱点在于:它买来的是宽度,而非判断力,如果你把它用错地方,它会花光你的钱。
因此,关键不在于将所有事物都图形化。而在于识别何时工作范围足够广,需要图来处理,何时一个简单的循环本就是答案。
我的看法:今晚就学习“假边测试”。画出你当前的工作流程,找出那些不承载数据的边,并将它们删除。这一举动,在你触碰任何新工具之前,就能让你比大多数人更快。
大多数人会继续按顺序排队步骤。而那些学会绘制图的人,将指挥一支舰队。