本文由 辛梓煜@词元2号站(www.ciyuanerhao.com)撰写,转载请注明出处。
快速摘要
一句话说清楚:动态工作流是 Claude Code 在最新版里给出的一种"大任务编排"能力——你用大白话描述要做的事,Claude 自己写出一段 JavaScript 脚本,由后台运行时去调度几十到上百个子智能体并行干活,跑完之前还会让不同的智能体互相挑刺、反复收敛,最后只把一份"成品答案"递回到你的对话里。 它最颠覆的地方不是"agent 更多了",而是把"计划"从对话搬进了代码:分支、循环、中间结果全交给脚本的变量保管,主对话的上下文窗口只留最终结论,所以才敢一口气拉起几百个 agent 而不把 token 烧穿。 目前它处于研究预览阶段,需要 Claude Code v2.1.154 及以上版本,付费计划都能用;并发上限是同一时刻最多 16 个智能体、单次运行总量封顶 1000 个。开启方式很简单:在提示词里写上 workflow 这个词,或者把 effort 调到 ultracode 让 Claude 自己判断该不该编排工作流。
下面这篇我会把开关怎么打、界面怎么读、脚本长什么样、和子智能体/技能的本质区别、两种启动方式、两个实战例子、能力边界,以及它背后那套"harness 工程"的大趋势全部拆开讲清楚。想看完整拆解,往下翻。
一、先把结论讲透:动态工作流到底是什么
我先把最容易被绕晕的概念钉死,省得后面越看越糊涂。
一个动态工作流,本质上就是一段由 Claude 现写出来的 JavaScript 脚本,再交给一个独立的运行时(runtime)在后台执行。你不用自己写这段脚本,只要用自然语言把任务说清楚,Claude 会把任务拆成若干阶段,每个阶段再拆成一批子任务,扔给一群子智能体并行去跑。
这里有三个词第一次出现,我用白话各解释一句:
- 子智能体(subagent):可以理解成 Claude 临时雇来的"临时工",每个临时工领一小块活,干完把结果交回来。
- 运行时(runtime):负责真正去执行那段脚本、调度这些临时工的"工头",它独立于你的聊天对话运行。
- 编排(orchestration):就是"排活儿"——谁先干、谁后干、谁的结果要喂给谁,这套调度逻辑写死在脚本里。
为什么要搞这么一套?因为有些活儿,单个 agent 一遍是做不完的,单个对话也协调不了那么多 agent。比如整个服务从头到尾排查一类 bug、一次性改动几百个文件的迁移、要从好几个角度互相印证的研究、或者一个你想在动手前从多个方向先压测一遍的方案。这些场景的共同点是:规模大、需要并行、还需要交叉验证。动态工作流就是冲着这类"硬骨头"来的。
我自己折腾下来最直观的感受是:原来要规划好几个迭代周期才能动手的活儿,现在用一个工作流跑一两天就能拿到一份可以审阅的结果。它把"任务太大不敢一次性丢给模型"这件事,变成了"放心丢,它自己会拆、会并行、会自检"。
为了让你更快判断"我这个活到底该不该上工作流",我把适合它的典型场景列成一张清单,你照着对一下:
- 整个代码库级别的 bug 排查:不是改一个文件里的某个函数,而是要把一整个服务、一整个仓库都扫一遍,看哪里藏着同一类隐患。
- 大规模迁移:比如改动量在五百个文件以上的那种迁移,或者整体换框架、换语言、把一批废弃的 API 统一替换掉。
- 交叉核验型研究:一个结论不能只听一个来源,需要多个来源互相印证、互相反驳,最后留下扛得住质疑的部分。
- 要从多个角度先压测一遍的方案:在你真正动手之前,先让它从好几个独立角度各起一版草案,互相比一比,再挑出最稳的那一版。
- 错了代价很高、必须查两遍的关键活儿:安全审计、鉴权检查、输入校验这类"漏一个就出事"的场景。
反过来说,如果你的活儿一个对话来回几轮就能搞定,那完全没必要上工作流——那是杀鸡用牛刀,还白白多烧 token。判断标准其实就一句话:这个任务,是不是已经大到"一个对话协调不动那么多 agent"了? 是,再考虑工作流;不是,老老实实用普通会话或者子智能体就够了。
我个人的体会是,工作流最适合的就是那种"工作量很大、但每一小块都不算太难、而且彼此相对独立"的活儿——这种活恰好能被切碎、被并行、被各自验证。要是任务本身高度耦合、每一步都强依赖上一步的细节,那拆并行的收益反而会打折扣,这一点心里得有数。
二、五分钟上手:开启与你的第一条命令
这一节我尽量按"打开终端就能照着做"的顺序来写。
2.1 先确认版本和开关
动态工作流目前是研究预览形态,对版本有要求:需要 Claude Code 升级到 v2.1.154 或更高。所有付费计划都能用,同时也开放给 API,以及 Amazon Bedrock、Google Cloud Vertex AI、Microsoft Foundry 这几个平台。
开关在哪?在 Claude Code 里输入斜杠命令 /config,回车进入配置界面,用方向键找到 Dynamic workflows 这一行,确认它的值是 true 即可。
/config
# 在配置列表里找到 Dynamic workflows,确保它处于开启状态
这里要纠正一个很多人会踩的认知误区:在更早的预览阶段,确实要手动设环境变量才能把这个功能打开;但在现在的版本里,大多数付费计划是默认开着的,你打开 /config 多半只是去确认一下,而不是去手动启用。Max、Team 计划以及通过 API 用 Claude Code 的人,开关默认就是 on;Enterprise 计划在发布初期默认是关的,需要管理员在后台打开。
2.2 最简单的触发:提示词里写一个 workflow
确认开关没问题之后,最省事的触发方式只有一步——在你的提示词里任意位置写上 workflow 这个词。
写对了你会立刻看到反馈:输入框里的 workflow 这个词会高亮变色。一旦它变色,就说明 Claude Code 识别到了你要走工作流,它接下来不会像平时那样一来一回地慢慢做,而是直接给这个任务写一段编排脚本。
Run a workflow to 把这个开源仓库 src/routes/ 下的每个接口都查一遍,看有没有漏掉鉴权
补一句历史:在更早的版本里触发词不是 workflow,现在统一改成了 workflow,看到它变色就对了。如果你只是想在句子里正常用到这个英文单词、并不想触发工作流,可以在高亮时按 alt+w 忽略这一次,或者在光标紧跟在高亮词后面时按一下退格键。想彻底关掉这个触发,去 /config 里把 Workflow 关键词触发关掉就行。
2.3 用自然语言给模型派活:便宜的铺广度,强的来收口
这是我个人觉得最香的一个用法。你完全可以在任务描述里直接规定"哪一步用便宜模型、哪一步用旗舰模型",Claude 会把这套分工落进脚本。
举个我常用的例子。我想让它把一个开源仓库前十个 issue 分诊成三类,于是这样写:
用一个 workflow 来做:先用便宜的 Haiku 4.5 模型并行铺开把这十个 issue 都过一遍、做初步归类,
再用 Opus 4.8 这个强模型来做最终收口和定夺,把它们分成三类。
这里出现两个模型名,顺手解释一下:Haiku 4.5 是当前体系里轻量、便宜、跑得快的小模型,适合"铺广度"这种量大但每件不复杂的活;Opus 4.8 是旗舰强模型,思考更深,适合"收口"这种需要拍板的活。用便宜模型铺、用强模型收,本质上就是把成本花在刀刃上。
为什么这条用法值得单拎出来讲?因为工作流默认会让所有 agent 都跟着你当前会话挂着的那个模型走。也就是说,如果你会话里挂的是 Opus 4.8,又不在提示词里另作交代,那它一口气拉起来的几十上百个 agent 全是旗舰模型在并行跑——这账单会很难看。所以"在提示词里把模型分工写明白"不是锦上添花,而是控制成本的关键一招。
我自己摸出来的一个顺手句式是:先用一句话点明"铺广度用什么、收口用什么",再接具体任务。比如:
workflow 用便宜的小模型按文件并行铺一遍,强模型只在最后综合时用一次:
帮我把 src/ 下所有模块过一遍,找出没有被任何地方引用到的死代码,列成清单。
这样写,Claude 在生成脚本时就会把"按文件并行的那一批"路由到小模型,把"最后综合"那一步留给强模型。你也可以更激进一点,明确写出阶段:第一阶段做什么用什么模型、第二阶段做什么用什么模型,它都会照着落进脚本里。这一点在第七节的实战里你会看得更清楚。
这里再补一个心法:便宜模型负责"广度",强模型负责"判断"。 凡是"量大、机械、彼此独立"的活,交给便宜模型批量铺;凡是"需要权衡、需要拍板、错了代价大"的活,才请强模型出场。把这两类活分清楚,成本和质量基本就能同时拿捏住。
跑起来之后,Claude Code 真的会按你说的那样,用一批便宜模型并行处理、再用强模型综合。你也就不用担心 token 一下子爆掉——便宜模型干了大部分体力活,贵的只在关键环节出手。
2.4 给工作流设预算,别让 token 失控
动态工作流是真的能拉起几百个 agent 的,所以"花多少"必须心里有数。一个简单做法是在任务描述里直接圈定一个预算额度,比如:
workflow 100K 把这个仓库做一次依赖梳理,列出可以删掉的死代码
我这里写的 100K 就是给它划的 token 预算上限的意思,后面再跟上具体任务。Claude Code 会尽量在你设定的额度内把活干完,从而避免开销超出预期。
小提醒:动态工作流天生比普通的 Claude Code 会话消耗更多用量,因为它同时在养一群 agent。第一次用强烈建议拿一个范围很小的任务先试水,摸清在你自己的活儿里大概会吃掉多少,再上规模。—— 辛梓煜@词元二号站
三、看懂运行界面:/workflows 进度视图怎么读
任务一旦提交,工作流就会在后台跑起来,你的对话窗口不会被卡住,可以继续干别的。想看它跑到哪了,输入斜杠命令 /workflows,用方向键选中那次运行,回车就能打开进度视图。
/workflows
3.1 阶段、智能体、token、耗时一眼全在
新版的进度视图比早期版本直观多了,布局上甚至有点像 tmux(一个常见的终端分屏工具)那种分区感。打开之后你能看到这次运行被切成了几个阶段(phase),每个阶段后面跟着这一阶段用了多少个智能体、烧了多少 token、花了多少时间。用方向键就能在不同阶段之间切换。
3.2 钻进单个 agent 看它到底干了啥
想看得更细,选中某个阶段按回车钻进去,里面会列出这一阶段的所有 agent。再选一个 agent 钻进去,就能看到它的具体状态:调用了哪个模型、消耗了多少 token、调用了哪些工具、Claude Code 给它下的提示词是什么、它最后吐出来的结果是什么。
我举个真实的观感:进到某个 agent 里,界面会清清楚楚告诉我"这个 agent 调用了 Haiku 4.5,消耗约 50K token,调用了一个工具",再往下就是它产出的内容。这种透明度对排查"工作流为什么跑歪了"特别有用。
3.3 记住这几个快捷键:暂停、停止、重启、保存
进度视图底部会列出每个按键对应的操作,常用的我整理成下面这张表:
|
按键 |
作用 |
|
|
在阶段或 agent 之间移动选择 |
|
|
钻进选中的阶段,再钻进某个 agent 看它的提示词、近期工具调用和结果 |
|
|
往回退一层 |
|
|
当 agent 详情内容太长时在里面上下滚动 |
|
|
暂停或继续这次运行 |
|
|
停掉选中的 agent;当焦点在整次运行上时,按它就是停掉整个工作流 |
|
|
重启选中的、正在跑的 agent |
|
|
把这次运行的脚本保存成一个命令(后面第八节细讲) |
记住 x 是"叫停"、s 是"保存",这两个用得最多。停掉整个工作流时,已经跑完的部分不会白费,结果会留着。
3.4 第一次跑会让你"签字确认"
还有一个你一定会遇到的环节:工作流第一次触发时,Claude Code 会先把"准备要跑哪些阶段"摆给你看,让你确认要不要放行。 这是个很贴心的设计——它把动用重武器的决定权交还给你,免得稀里糊涂就拉起一大堆 agent 烧 token。
在命令行里,这个确认弹窗一般给你几个选项:直接跑、跑且"以后这个项目里这个工作流别再问我了"、先看一眼原始脚本再决定、以及取消。想在动手前读一遍脚本,按 Ctrl+G 能在编辑器里打开它;想在跑之前微调一下提示词,按 Tab 就能改。
要不要弹这个确认框,取决于你的权限模式:默认模式和"接受编辑"模式下,每次跑都会问,除非你之前对这个工作流选过"别再问我";自动模式下只在第一次启动时问,你点了同意它就记下来、以后不再打扰;而在"绕过权限"、claude -p 非交互模式、以及 Agent SDK 这几种场景下,根本没人可问,运行会直接开始。
桌面应用里则是弹一张审批卡片,上面写着工作流名字、阶段清单,还专门标了一句 token 用量的提醒,给你"只这一次""一直允许""拒绝"三个按钮。进度则显示在"后台任务"那个侧边面板里。
有一点要特别留神:你的权限模式只管"启动那一下要不要问你"。工作流真正派出去的那些子 agent,一律以"接受编辑"模式运行,文件改动是自动放行的,它们继承的是你的工具白名单。所以那些不在白名单里的 shell 命令、网页抓取、MCP 工具,仍然可能在跑到一半时弹窗问你——这也是我后面在实操建议里反复强调"长任务提前配好白名单"的原因。
四、原理拆解:为什么说它把"计划"搬进了代码
到这里你已经会用了,下面讲点更深的东西,搞懂了原理你才知道它的边界在哪。
4.1 一个动态工作流,本质就是一段 JS 脚本
再强调一遍这个核心:动态工作流不是"Claude 在脑子里默默多想了几步",而是 Claude 把整个计划写成了一段 JavaScript 脚本,再交给运行时去执行。这段脚本里写着:先跑哪个阶段、每个阶段拉几个 agent、谁的产物要传给下一阶段、什么条件下要循环重跑、什么条件下算收敛。
这一步是关键转变:传统玩法里,Claude 是那个"工头",它每走一步都要回到对话里想一下"下一步派谁去";而动态工作流把工头的活儿写进了脚本,循环和分支由脚本自己掌管,Claude 的对话只负责接收最终答案。
4.2 中间结果存在脚本变量里,而不是上下文窗口
这是它"敢拉几百个 agent"的真正底气,也是最容易被忽略的一点。
普通的子智能体或技能,跑出来的每一份中间结果都会回灌进 Claude 的上下文窗口(你可以理解成模型当下能"记住"的那块工作记忆)。agent 一多,中间结果就越堆越满,最后上下文被占爆,模型反而变笨。
动态工作流换了个思路:所有中间结果都先存在脚本的变量里,主对话的上下文只保留最终那份答案。打个不太严谨但好懂的比方——子智能体/技能是"所有人都挤在一个小会议室里汇报,人越多越吵";动态工作流是"大家各自在工位上把活干完、把结果存进共享文档,只有最终结论才拿到会议室念一遍"。
下面这张图把这个差别画了出来:
flowchart TD
U[你用自然语言描述任务] --> C[Claude 写出一段 JS 编排脚本]
C --> R{运行时在后台执行}
R --> P1[阶段一: 一批便宜模型并行铺广度]
R --> P2[阶段二: 对抗验证 互相挑刺]
R --> P3[阶段三: 强模型综合收口]
P1 -. 中间结果 .-> V[(脚本变量<br/>暂存所有中间产物)]
P2 -. 中间结果 .-> V
P3 --> F[只把最终答案<br/>交回主对话]
V -. 仅供脚本内部读取 .-> R
F --> U
看图就明白了:那条点线(中间结果)始终在脚本变量里打转,从不进主对话;只有最后那条实线(最终答案)才回到你这边。上下文窗口因此能一直保持轻盈。
4.3 多角度进攻 + 对抗验证 = 收敛出更靠谱的答案
动态工作流不只是"人多力量大",它还能套用一种可复用的质量套路:让一批 agent 从不同角度独立地解同一个问题,再让另一批 agent 专门去反驳、挑刺前面那批的结论,整个运行会不断迭代,直到答案收敛到一致为止。
这套"独立解题 + 对抗验证 + 反复收敛"的机制,是单趟跑(single pass)给不出来的——单趟跑只有一个声音,没人质疑它。所以遇到那种"错了代价很高、必须查两遍"的活儿,工作流的价值就特别突出。
我打个生活里的比方来体会这件事。单趟跑就像一个人闷头写完一份报告直接交上去,对不对全看他这一遍的状态;而工作流更像一个有审稿环节的编辑部:好几个作者各写一版,再有专门的审稿人逐条找茬,扛不住质疑的论点直接被毙掉,剩下的反复打磨到大家都挑不出毛病为止。同样是产出一份东西,后者天然更经得起推敲。
更妙的是,这套质量套路是**"可复用的模式",而不是一次性的灵光一现**。因为它写在脚本里,所以你今天用它审一个仓库,明天换一个仓库还能照着同样的"找—验—合"三段式跑。把质量标准固化进编排逻辑,而不是每次都指望模型临场发挥,这正是"计划搬进代码"带来的另一层红利。
顺带说一句"收敛"。这个词听起来玄,其实就是"反复迭代,直到答案不再剧烈摇摆、几路独立的尝试给出的结论趋于一致"。一旦各路 agent 从不同角度得到的结果开始彼此印证、不再互相打架,运行就认为这个问题已经收敛、可以给出最终答案了。理解了这一点,你就明白为什么工作流愿意"多花点 token 反复跑"——它买的是一份更可信的结果。
五、它和子智能体、技能到底差在哪(重点澄清)
我之前写过几篇关于子智能体和技能的东西,评论区总有人说"用技能不就能替代工作流吗"。这个理解不准确,也不够深入。这三者确实都能跑多步任务,但**"计划掌握在谁手里"完全不一样**。我把官方那张对照思路整理成下面这张表,并按自己的理解做了白话补充:
|
维度 |
子智能体(Subagents) |
技能(Skills) |
动态工作流(Workflows) |
|
它本质是什么 |
Claude 临时拉起的一个"工人" |
Claude 要遵循的一套"指令" |
运行时执行的一段"脚本" |
|
谁决定下一步 |
Claude,一轮一轮地决定 |
Claude,照着提示词决定 |
脚本自己决定 |
|
中间结果存哪 |
Claude 的上下文窗口 |
Claude 的上下文窗口 |
脚本变量里 |
|
可复用的是什么 |
工人的定义 |
那套指令 |
整套编排本身 |
|
规模量级 |
每轮几个委派任务 |
同子智能体 |
单次几十到上百个 agent |
|
被打断之后 |
这一轮重来 |
这一轮重来 |
同一会话内可恢复续跑 |
看懂这张表,争论就没了:子智能体和技能的中间结果都会进上下文窗口,所以越跑越占;只有工作流把中间结果隔离在脚本变量里,主对话只留最终答案。它们不是替代关系,而是"小活儿用子智能体/技能,大活儿上工作流"的分工关系。
我把这三者的"性格"再用一句话各自概括一下,帮你彻底记住:
- 子智能体是"工人"——Claude 临时拉一个人来干一小块活,干完结果回到 Claude 手里,下一步还得 Claude 来排。它的可复用单位是"这个工人怎么定义"。
- 技能是"指令"——一套写好的做事规范,Claude 照着它一步步做。它的可复用单位是"这套指令本身"。
- 工作流是"脚本"——把"先干啥后干啥、谁喂给谁、什么时候循环"整个调度逻辑写死成程序,由运行时去跑。它的可复用单位是"整套编排"。
为什么"中间结果存哪"这件事如此要命,我再多说两句,因为这是很多人没意识到的隐性成本。上下文窗口你可以理解成模型当下的"工作台面",面积是有限的。子智能体和技能每跑一步,产出的中间料都往这张台面上堆;agent 一多、步骤一长,台面很快就堆满了,模型反而开始"顾此失彼",质量不升反降。工作流把这些中间料统统搬到了"旁边的储物柜"(脚本变量)里,台面上永远只摆着最后要交付的那一份。这就是它为什么敢一次性拉起几百个 agent,而子智能体/技能拉不了的根本原因。 不是工作流"更厉害",而是它从架构上换了一个地方放中间结果。
所以下次再有人跟你说"用技能就能替代工作流",你可以反问一句:那几百个 agent 的中间结果,你打算往哪儿放?答案如果是"上下文窗口",那就注定撑不到那个规模。
六、两种启动方式详解:workflow 关键词 vs ultracode
前面第二节讲了最常用的关键词触发,这里把两种主要方式都讲全,外加一个开箱即用的内置命令。
6.1 方式一:提示词里写 workflow(单次、轻量)
如果你只想让"当前这一个任务"走工作流,又不想改动整个会话的努力等级,那就在提示词里写上 workflow,看到它高亮变色即可。它的特点是一次性——只影响这一条指令,干净利落。
6.2 方式二:ultracode(让 Claude 自己判断要不要编排)
第二种是把努力等级(effort)切到 ultracode。用斜杠命令就能切:
/effort ultracode
ultracode 是 Claude Code 专属的一档设置,它做了两件事:把推理努力拉到 xhigh(更高强度地思考),同时让 Claude 自动判断当前这个任务值不值得编排成工作流。开了它之后,会话里每一个有分量的任务,Claude 都会先做一次预评估,再决定是顺手处理掉,还是拉起一套工作流从多个角度同时进攻。
一个很有意思的细节:开了 ultracode 之后,一条请求可能连着触发好几个工作流——比如先来一个工作流摸清代码架构,再来一个负责动手改,最后再来一个负责验证。把"要不要动用重武器"的决定权,从你手里交给了模型。
要注意它的"脾气":ultracode 只在当前会话有效,开了新会话会重置;它也只在支持 xhigh 的模型上才出现在 /effort 菜单里。回到日常的轻活时,记得用 /effort high 切回去,免得每个小任务都被当成大工程来烧 token。
这里顺带说一句努力等级。Opus 4.8 默认就是 high,往上还有 extra、max,再往上配合 Claude Code 才是 ultracode 这一档。日常聊天用 high 足够,真要啃硬骨头再往上加档。
6.3 内置的 /deep-research:开箱即用的研究型工作流
Claude Code 自带了一个现成的工作流命令 /deep-research,专门用来"把一个问题在大量来源里查清楚"。它会从好几个角度并行撒网搜索、把找到的资料互相交叉核对、对每条结论投票表决,最后给你一份带引用的报告,那些没扛过交叉验证的结论会被直接过滤掉。
/deep-research Node.js 的权限模型从 v20 到 v22 之间到底改了哪些东西
我自己实测过用它研究一个偏架构的话题:运行起来会分成五个阶段。我用 /workflows 进去看,第一阶段在打底,第二阶段它一口气起了五个 agent 并行调研(没指定模型时默认用 Opus 4.8),第三阶段直接编排了二十多个 agent、跑得飞快,第四阶段是验证、拉了一大批 agent 排队跑、同一时刻并发十个左右。等了几分钟,一份相当详实的研究报告就出来了。这种"自己会撒网、会核对、会过滤"的体验,跟手动一条条搜完全不是一个量级。
把这个过程拆开看,你能清楚地看到工作流"分阶段收敛"的节奏:前面的阶段负责铺开——从多个角度撒网、把能找到的资料都抓回来;中间的阶段负责核对——把不同来源的说法摆在一起互相印证;后面的阶段负责过滤和综合——对每条结论投票,没扛过交叉验证的直接删掉,剩下的整理成一份带引用的报告。你拿到的不是"一堆搜索结果的堆砌",而是"一份已经替你筛过一遍的结论"。
操作上有个细节值得一提:进度视图里你可以用方向键左键往回退一步、回到上一层,也能钻进任意一个阶段去看它具体起了几个 agent、各自在忙什么。我研究那次,第三阶段那二十多个 agent 里,前几个很快就完成了任务,界面还会顺带显示它们各自消耗了多少 token——这种颗粒度的可见性,让"它到底在干嘛、花了多少钱"不再是个黑盒。
你自己保存下来的工作流,也会像 /deep-research 一样变成 / 开头的命令,出现在自动补全里。所以你完全可以把 /deep-research 当成一个"官方样板间":先跑几次,进去观察它是怎么切阶段、怎么做验证、怎么过滤的,再照着这个套路去描述你自己的任务,写出来的工作流质量会高不少。
七、实战一:用工作流做一次代码审计
讲了这么多,上个能直接抄的实战。代码审计是动态工作流的"主场"之一,因为它天然要"覆盖全仓库 + 每条发现都要复核"。
我的任务描述大概长这样:
用一个 workflow 给这个仓库做代码审计:
1) 便宜模型按文件并行去找 bug;
2) 每找到一条,再派三个便宜模型做对抗验证,互相质疑这条是不是真问题;
3) 最后用强模型把通过验证的发现综合成一份报告。
跑起来之后,它会清清楚楚地分成三个阶段:第一阶段找 bug、第二阶段验证、第三阶段合成最终报告。而且它严格遵守了我提示词里的要求——前两个量大的阶段都用了便宜的 Haiku 4.5 模型,最后综合那一步才换上强模型。
为了让你直观看到它写出来的脚本"长什么样",我用伪代码还原一下这套编排的骨架(真实脚本是 JS,这里只示意逻辑):
// —— 阶段一:并行找 bug(便宜模型铺广度)——
const files = listSourceFiles("src/");
const findings = await parallel(files, (file) =>
agent({ model: "haiku-4.5", task: `审查 ${file},列出可疑 bug` })
);
// —— 阶段二:对抗验证(每条发现派三个便宜模型互相挑刺)——
const verified = [];
for (const f of flatten(findings)) {
const votes = await parallel([1, 2, 3], () =>
agent({ model: "haiku-4.5", task: `质疑这条发现是否成立:${f}` })
);
if (majorityAgree(votes)) verified.push(f); // 多数认可才留下
}
// —— 阶段三:强模型综合收口 ——
const report = await agent({
model: "opus-4.8",
task: `把这些通过验证的发现整理成一份审计报告:${verified}`,
});
return report; // 只有这份最终报告会回到主对话
注意看最后那行注释:只有 report 会回到主对话,中间的 findings、votes、verified 全都待在脚本变量里。这就是第四节讲的原理在这个例子里的具体体现。
我特意把"对抗验证"那一段写成"每条发现派三个便宜模型投票、多数认可才留下",是有讲究的。代码审计最怕的就是误报——模型一惊一乍地报一堆"疑似 bug",结果你一条条看下去大半是虚惊,时间全耗在排查假阳性上。让三个独立的小模型互相质疑、多数同意才算数,相当于给每条发现加了一道廉价的"复核闸门",把大量噪音挡在最终报告之外。而且这道闸门用的还是便宜模型,三个一起跑也花不了多少钱,性价比很高。
跑完之后,最终报告里那些 bug 是带着"为什么这是问题、影响范围多大"一起呈现的,因为强模型在综合那一步会把零散的发现串成有条理的结论。我拿到报告后要做的,就是按它给的线索去逐条核实——但因为假阳性已经被前面那道验证闸门滤掉了大半,我的核实效率比"自己从头扫一遍仓库"高太多了。
整个过程里,我作为人要做的只有两件事:把任务说清楚、在结果出来后审一遍。重活、脏活