橙研所

为什么多 Agent 编排要写成脚本,而不是让模型自由发挥

多 agent 协作的质量不来自更聪明的模型,而来自一张写死的图纸——哪里并行、哪里设栅栏、验证几票、何时早退。以 Claude Code 的 Workflow 工具为例拆这张图纸怎么画。

Module C · 第 7 篇约 6 分钟

立靶: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):等这一阶段的全部条目完成,才放行下一阶段。总耗时等于每个阶段最慢者之和。

默认永远选流水线。栅栏只在下一阶段真的需要上一阶段的全部结果时才正当,正当理由只有三种:

  1. 跨条目去重或合并——不拿到全量没法判断谁和谁重复;
  2. 零结果早退——「一个 bug 都没找到,整个验证阶段直接跳过」;
  3. 下一阶段要引用「其他发现」做比较——评分、排序、挑代表。

而这些理由不成立:「我要先整理一下数据」(整理放进流水线的中间一站就行)、「两个阶段概念上是分开的」(流水线本来就建模阶段分离)、「代码更好看」。栅栏的代价是真实的墙钟:五个并行搜索里最慢的比最快的慢三倍,栅栏就白白浪费掉快者三分之二的空转时间。

质量模式库:结构如何换来可信

编排的第二重价值是质量——用结构性冗余买确信度。常用的形状:

模式做法治什么病
对抗验证每个发现派 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 存活。三条教训比数字更值钱:

  1. 确定性的活交给代码,不烧 token。 去重、排序、合并链接全是普通 JavaScript——agent 只干需要判断力的搜索与核验。
  2. 找的人和验的人必须是两拨。 搜索 agent 有凑数的动机(指令要求交 5 到 8 人),所以每个候选人交给独立 agent 重新打开链接核验。真跑的结果:核验阶段没有全灭任何人,但剔掉了多条打不开或张冠李戴的链接。
  3. 去重键会最先坏。 按名字归一挡不住同一个人被两个渠道用不同写法报送(一个渠道报中文名、另一个报拼音),重复条目漏进了终榜。生产版应改用「域名加账号名」当键。这类坑只有真跑一遍才暴露——所以先用十分之一规模跑通形状,再放大。

可操作做法:最小骨架与八条纪律

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) }

八条纪律,按踩坑概率排序:

  1. 先侦察后编排:主流程先摸清工作清单(哪些文件、渠道、条目),再喂给编排脚本。不必在任务前就知道形状,只需在编排那一步前知道。
  2. 默认流水线,栅栏给理由:见上文,这是墙钟的第一杠杆。
  3. 一切子 agent 输出走 schema:校验发生在工具层,不匹配自动重试;主流程永远拿结构化对象,不解析散文。
  4. 指令自包含:子 agent 冷启动、看不到对话历史,画像、规则、日期全部写死进指令。
  5. 找与验分离,验证者当怀疑者:宁可多花一轮验证,不让像真的假货进终稿。
  6. 确定性逻辑写代码:去重、排序、统计、过滤不派 agent。
  7. 截断必留痕:「取前 12,丢弃 14 人」要出现在日志里——让读结果的人知道覆盖边界。
  8. 先小后大:形状对不对用十分之一规模验证,坑都在小规模暴露,再复用缓存放大。

还有一条元纪律:大任务拆成多条 workflow、人留在环里。 理解、设计、实施、评审各跑一条,每条结束你读完结果再定下一条——而不是一条巨型脚本一口气跑到黑。编排解决的是单条流水线内的结构问题;流水线之间的方向盘,仍然在人手上。

一句话收口

多 agent 不是把一个不可靠的东西变成 N 个,而是用一张确定性的图纸,让 N 个不可靠的东西互相抵消掉彼此的不可靠——图纸画得好不好,才是编排的全部难度所在。