为什么多 Agent 编排要写成脚本,而不是让模型自由发挥
多 agent 协作的质量不来自更聪明的模型,而来自一张写死的图纸——哪里并行、哪里设栅栏、验证几票、何时早退。以 Claude Code 的 Workflow 工具为例拆这张图纸怎么画。
立靶:2026 年「multi-agent」是最热的词之一,也是翻车率最高的做法之一。把一个任务丢给一群 agent「自由协作」,常见结局是:两个 agent 重复干同一件事、第三个 agent 把前两个的结论各信一半、没有任何人负责验证、最后汇总的 agent 把「我看过了」当成「我核实了」。模型每强一代,这些病一个都不少——因为它们不是智能问题,是结构问题。
本讲的核心主张一句话:
多 agent 协作的质量,来自一张写死的图纸,不来自格子里 agent 的聪明程度。 图纸规定:任务怎么分、哪里并行、哪里必须等齐、谁验证谁、验证几票算数、什么条件早退。这张图纸应该是确定性代码,不是模型的临场发挥。
Claude Code 在 2026 年把这张图纸做成了产品化的 Workflow 工具:编排逻辑用 JavaScript 写死,循环、分支、fan-out 全部确定性执行;只有每个格子里的具体工作(搜索、判断、改写)交给子 agent。本讲用它做例子,但图纸思维适用于任何多 agent 框架。
什么任务值得编排:三类动机
先泼冷水:大多数任务不值得编排。单点事实查询、一两个独立子任务、对话式问答、琐碎改动——一个 agent 从头跑到尾就能做对的事,编排是纯开销。判据是「结构是否创造价值」。
值得上编排的任务,动机只有三类:
| 动机 | 缺的是什么 | 典型任务 | 编排形状 |
|---|---|---|---|
| 求全 | 一个视角扫不完 | 全库审计、多渠道调研、竞品横扫 | 分解,并行覆盖,汇总 |
| 求信 | 单次判断不敢信 | bug 复核、方案评审、事实核查 | 独立视角乘 N,对抗验证,只留幸存者 |
| 求量 | 单个上下文装不下 | 大规模迁移、逐文件改写、上百条目逐一处理 | 发现工作清单,逐条流水线 |
和「派一个子 agent」的分界线:子 agent 是「派一个人去办一件事」;编排是「搭一条流水线让 N 个人按图纸协作」。只有当你需要图纸本身——去重在哪一步、验证要几票、什么时候早退——才值得写编排脚本。
图纸上最重要的一笔:流水线还是栅栏
九成的编排失误发生在同一处:该用流水线的地方用了栅栏。
两个原语的区别:
- 流水线(pipeline):每个条目独立走完所有阶段,阶段之间不互相等。条目 A 在第三步时,条目 B 可以还在第一步。总耗时等于最慢的单条链。
- 栅栏(barrier):等这一阶段的全部条目完成,才放行下一阶段。总耗时等于每个阶段最慢者之和。
默认永远选流水线。栅栏只在下一阶段真的需要上一阶段的全部结果时才正当,正当理由只有三种:
- 跨条目去重或合并——不拿到全量没法判断谁和谁重复;
- 零结果早退——「一个 bug 都没找到,整个验证阶段直接跳过」;
- 下一阶段要引用「其他发现」做比较——评分、排序、挑代表。
而这些理由不成立:「我要先整理一下数据」(整理放进流水线的中间一站就行)、「两个阶段概念上是分开的」(流水线本来就建模阶段分离)、「代码更好看」。栅栏的代价是真实的墙钟:五个并行搜索里最慢的比最快的慢三倍,栅栏就白白浪费掉快者三分之二的空转时间。
质量模式库:结构如何换来可信
编排的第二重价值是质量——用结构性冗余买确信度。常用的形状:
| 模式 | 做法 | 治什么病 |
|---|---|---|
| 对抗验证 | 每个发现派 N 个独立怀疑者,指令就写「尝试反驳它」,多数反驳即杀 | 像真的假发现 |
| 多视角验证 | N 个验证者各持不同镜头(正确性、安全、能否复现),而非 N 个同款 | 冗余抓不到的多样失效 |
| 评委团 | N 个不同角度的独立方案,并行评分,从冠军合成、嫁接亚军亮点 | 解空间宽时「一稿反复改」的局部最优 |
| 干涸循环 | 连续 K 轮无新发现才停,而不是数够 N 个就停 | 未知规模任务漏长尾 |
| 多模态横扫 | 并行 agent 各用一种搜法(按容器、按内容、按实体、按时间) | 单一搜索角度的盲区 |
| 完整性批评家 | 收尾专派一个 agent 问「还缺什么」,其产出变成下一轮工作 | 过早收工 |
| 不留无声上限 | 凡截断(取前 N、抽样)必在日志里报丢弃量 | 「都覆盖了」的假象 |
熟悉本模块前几讲的读者会认出来:对抗验证就是 verify 独立于实现的多 agent 版;干涸循环对应 fixture 跑到不再冒新错;不留无声上限就是完成声明前先回读。同一套 harness 纪律,换到了多 agent 运行层。
一个真实 case:候选人 sourcing 流水线
起因是 Anthropic 的 Claude Code 产品经理公开分享她的日常用法:给 agent 一份岗位画像,让它跑动态 workflow 找 100 个候选人,每人附公开足迹链接和一句话推介,做成页面发邮件给她,然后合上电脑下班。我们按同样的形状复刻了一条缩小版流水线:
岗位画像(常量,注入每个 agent 的指令)
|
Source 阶段 4 个渠道 agent 并行搜索(社交平台 / GitHub / 中文社区 / 播客演讲)
| 此处栅栏正当:跨渠道去重需要全量到齐
纯代码去重与排序(零 token):29 人 -> 26 人,取前 12(日志报丢弃 14 人)
|
Verify 阶段 12 个「怀疑者」agent 并行逐链接核验,证伪即剔
|
返回结构化 JSON -> 主流程渲染成交付页面
实测:16 个 agent,6 分半跑完,漏斗 29 找到、26 去重、12 进核验、11 存活。三条教训比数字更值钱:
- 确定性的活交给代码,不烧 token。 去重、排序、合并链接全是普通 JavaScript——agent 只干需要判断力的搜索与核验。
- 找的人和验的人必须是两拨。 搜索 agent 有凑数的动机(指令要求交 5 到 8 人),所以每个候选人交给独立 agent 重新打开链接核验。真跑的结果:核验阶段没有全灭任何人,但剔掉了多条打不开或张冠李戴的链接。
- 去重键会最先坏。 按名字归一挡不住同一个人被两个渠道用不同写法报送(一个渠道报中文名、另一个报拼音),重复条目漏进了终榜。生产版应改用「域名加账号名」当键。这类坑只有真跑一遍才暴露——所以先用十分之一规模跑通形状,再放大。
可操作做法:最小骨架与八条纪律
Workflow 脚本的最小可跑骨架(纯 JavaScript,开头一个纯字面量的 meta 块):
export const meta = {
name: 'review-changes',
description: '按维度评审改动,逐条对抗验证',
phases: [{ title: 'Review' }, { title: 'Verify' }],
}
phase('Review')
// schema 强制子 agent 返回可校验的 JSON,不用再解析散文
const r = await agent('审查 src/ 的正确性问题…', { schema: FINDINGS })
phase('Verify')
const v = await parallel(r.findings.map(f => () =>
agent(`对抗验证:尝试反驳 ${f.title}`, { schema: VERDICT })))
return { confirmed: v.filter(Boolean).filter(x => x.isReal) }
八条纪律,按踩坑概率排序:
- 先侦察后编排:主流程先摸清工作清单(哪些文件、渠道、条目),再喂给编排脚本。不必在任务前就知道形状,只需在编排那一步前知道。
- 默认流水线,栅栏给理由:见上文,这是墙钟的第一杠杆。
- 一切子 agent 输出走 schema:校验发生在工具层,不匹配自动重试;主流程永远拿结构化对象,不解析散文。
- 指令自包含:子 agent 冷启动、看不到对话历史,画像、规则、日期全部写死进指令。
- 找与验分离,验证者当怀疑者:宁可多花一轮验证,不让像真的假货进终稿。
- 确定性逻辑写代码:去重、排序、统计、过滤不派 agent。
- 截断必留痕:「取前 12,丢弃 14 人」要出现在日志里——让读结果的人知道覆盖边界。
- 先小后大:形状对不对用十分之一规模验证,坑都在小规模暴露,再复用缓存放大。
还有一条元纪律:大任务拆成多条 workflow、人留在环里。 理解、设计、实施、评审各跑一条,每条结束你读完结果再定下一条——而不是一条巨型脚本一口气跑到黑。编排解决的是单条流水线内的结构问题;流水线之间的方向盘,仍然在人手上。
一句话收口
多 agent 不是把一个不可靠的东西变成 N 个,而是用一张确定性的图纸,让 N 个不可靠的东西互相抵消掉彼此的不可靠——图纸画得好不好,才是编排的全部难度所在。