反对默认采用 swarm 的理由
Agent 工程中一个常见的失败模式,是在想到函数之前先想到 swarm。任务被拆解成若干角色,加一个 supervisor,然后系统就被宣布为“agentic”。实际构建出来的,是一个把语言模型放进循环里的分布式系统,而代价既有分布式的那些熟悉代价,也有非确定性带来的陌生代价。
每增加一个 Agent,就引入一次交接。在每次交接中,生产方 Agent 把自身状态序列化成文本,消费方 Agent 再把它反序列化回上下文。这一来一回是有损的。一个带有置信度分数、来源引用和部分失败标记的结构化结果,在散文里会变成一句话,而这三样全被省略。这种损失不是随机的;它恰好与下游 Agent 判断该继续、重试还是升级所需的信息相关。
协调开销的增长也快于拆解带来的节省。如果一个任务需要 T 个单位的工作量,并拆成 n 个子任务,理想节省大约是 T/n。协调成本不是 T/n;它是所有交接之和,而每次交接都需要一个 prompt、一次模型调用、一次解析和一次验证。在实践中,当子任务并非真正独立时仍继续增加 Agent,得到的系统会比它所取代的单次调用更慢、更贵、更难调试。
最深的问题是可测试性。确定性代码可以做单元测试。一个接收类型化输入并返回类型化输出的函数,有一份你可以据以断言的契约。编排器的 prompt 没有。你可以在数据集上评估它的输出,而且你应该这么做,但你无法写出一个测试,在编排器于不同模型版本之间悄悄改变路由策略时失败。prompt 是用一门没有编译器的语言表达的规格说明。
这并不是在反对多 Agent 系统。这是在反对把它们当作默认选项。幕僚长模式,正如这篇关于编排 Claude Code 会话的文章所述,之所以有用,恰恰是因为它点明了协调层在哪些条件下才值得存在。
支持编排的信号
在实践中,有三个信号可以区分一个任务需要编排器还是需要一个脚本。
不相交的工具集或不相交的上下文
如果子任务 A 需要对代码库的读权限,而子任务 B 需要对部署目标的写权限,它们就需要不同的工具集。一个同时持有这两种工具的单一 Agent,必须被同时信任以使用两者,而且它的上下文必须承载两者的 schema、凭据和失败模式。把它们拆开,意味着每个 Agent 的上下文更小、权限更窄。同样的论证也适用于上下文窗口:如果一个子任务的原始材料会占用窗口的大部分,而另一个子任务的原始材料会占用剩下的部分,单一 Agent 就会截断或摘要,而信息损失恰恰就发生在摘要里。

真正的独立性
第二个 Agent 只有在真正独立时才值得其成本,而不是当它只是第一个 Agent 的换种说法时。独立意味着它不共享第一个 Agent 的上下文、假设或失败模式。一个读取相同上下文和相同推理的验证器,往往会同意生产方,因为它在相同的 token 上运行相同的分布。一个只读取产物、并拥有自己的检查工具的验证器,才可能不同意。这种不同意就是价值所在。
长周期任务
有些任务周期足够长,单一上下文无法容纳。一次触及数百个文件的迁移、一个持续数小时累积来源的研究任务、一次横跨多个系统的故障响应:这些都超出了单个窗口能保留的范围,而失败模式不是给出错误答案,而是遗忘。在这里,编排器的职责不是对任务进行推理,而是管理已完成事项和剩余事项的账本。
如果这三个信号一个都不存在,诚实的工程答案就是一个脚本。一个调用单个模型、按 schema 验证输出、失败时重试的脚本,是可测试、可观测且廉价的。在大多数情况下,它也更快。
实现该模式
当编排确有必要时,实现细节决定它能否奏效。有三个机制比框架的选择更重要。
单一权威任务账本
Agent 应当读写同一个共享账本,而不是互相传递散文式摘要。账本是事实来源,记录了什么已尝试、什么已成功、什么被阻塞。每条记录包含:任务标识符、状态、输入、输出以及任何错误。Agent 认领任务、更新状态、追加结果。编排器
这颠倒了通常的模式。状态不再由编排器保存在自己的上下文中并摘要给 worker,而是存在于每个上下文之外,按需读取。一个需要知道某个依赖是否成功的 worker,读取账本,而不是信任摘要。编排器的上下文保持很小,而这正是重点。

以类型化载荷作为交接契约
交接应当是一个类型化载荷,而不是散文式摘要。只定义一次 schema,在两端都进行验证,并在不匹配时大声失败。一个子 Agent 结果的最小契约可能如下所示:
{
"task_id": "string",
"status": "succeeded | failed | blocked",
"artefacts": [{"path": "string", "hash": "string"}],
"claims": [{"text": "string", "evidence": "string"}],
"open_questions": ["string"]
}
这个 schema 做两件事。它迫使生产方 Agent 区分它做了什么和它相信什么,而这是两件不同的事。它还给消费方 Agent 一个稳定的接口,这样生产方推理的变化不会悄悄改变消费方的输入。当某个字段无法填写时,Agent 必须说明,而 blocked 是一个有效状态。散文式摘要恰恰隐藏了这种情况。
对交接延迟和信息损失进行埋点
交接延迟是可测量的:从生产方完成到消费方开始的时间,以及在验证和重试中花费的时间。信息损失更难测量,但并非不可能。通过比较生产方发出的内容与消费方据以行动的内容来埋点。如果生产方的载荷包含三个未决问题,而消费方的下一步行动一个都没处理,那就是一次损失,值得记录。在多次运行中,这些损失的分布会告诉你契约在哪些地方过于单薄。
把两者都当作一等指标,与任务成功率和每任务成本并列。一个正确、但交接耗时超过其所协调工作的编排系统,是一个应当被收拢回脚本的系统。
诚实的权衡
幕僚长模式不是免费的,也不总是正确的。它的成本是真实的:更多活动部件、更多需要维护的 prompt、更多需要观测的失败模式,以及一种横跨多个上下文而非单一上下文的调试体验。它的收益也是真实的,但都是有条件的。当子任务需要不同上下文、不同工具或独立验证时,收益才会出现;当这些条件不成立时,收益基本消失。
实践中的纪律是从脚本开始。写出单次调用,验证其输出,测量它在何处失败。当它因为上下文太大、工具冲突或验证不够独立而失败时,再加入编排器。不要提前。该模式是对一组特定约束的回应,而在没有这些约束的情况下套用它,只会以牺牲实质为代价换来表面的精致。
