跳转到主要内容

幕僚长模式:何时该编排 Agent,何时只需写个脚本

多 Agent 编排只有在子任务需要不同上下文、不同工具或独立验证时才有价值。否则,它只是一次更慢的函数调用。

白色背景上一只机械手伸出的极简图像。

反对默认采用 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 就会截断或摘要,而信息损失恰恰就发生在摘要里。

Detail view of an aircraft's sophisticated control panel with instruments and switches.

真正的独立性

第二个 Agent 只有在真正独立时才值得其成本,而不是当它只是第一个 Agent 的换种说法时。独立意味着它不共享第一个 Agent 的上下文、假设或失败模式。一个读取相同上下文和相同推理的验证器,往往会同意生产方,因为它在相同的 token 上运行相同的分布。一个只读取产物、并拥有自己的检查工具的验证器,才可能不同意。这种不同意就是价值所在。

长周期任务

有些任务周期足够长,单一上下文无法容纳。一次触及数百个文件的迁移、一个持续数小时累积来源的研究任务、一次横跨多个系统的故障响应:这些都超出了单个窗口能保留的范围,而失败模式不是给出错误答案,而是遗忘。在这里,编排器的职责不是对任务进行推理,而是管理已完成事项和剩余事项的账本。

如果这三个信号一个都不存在,诚实的工程答案就是一个脚本。一个调用单个模型、按 schema 验证输出、失败时重试的脚本,是可测试、可观测且廉价的。在大多数情况下,它也更快。

实现该模式

当编排确有必要时,实现细节决定它能否奏效。有三个机制比框架的选择更重要。

单一权威任务账本

Agent 应当读写同一个共享账本,而不是互相传递散文式摘要。账本是事实来源,记录了什么已尝试、什么已成功、什么被阻塞。每条记录包含:任务标识符、状态、输入、输出以及任何错误。Agent 认领任务、更新状态、追加结果。编排器

这颠倒了通常的模式。状态不再由编排器保存在自己的上下文中并摘要给 worker,而是存在于每个上下文之外,按需读取。一个需要知道某个依赖是否成功的 worker,读取账本,而不是信任摘要。编排器的上下文保持很小,而这正是重点。

Close-up of automated canning equipment in a brewery, highlighting the manufacturing process.

以类型化载荷作为交接契约

交接应当是一个类型化载荷,而不是散文式摘要。只定义一次 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、更多需要观测的失败模式,以及一种横跨多个上下文而非单一上下文的调试体验。它的收益也是真实的,但都是有条件的。当子任务需要不同上下文、不同工具或独立验证时,收益才会出现;当这些条件不成立时,收益基本消失。

实践中的纪律是从脚本开始。写出单次调用,验证其输出,测量它在何处失败。当它因为上下文太大、工具冲突或验证不够独立而失败时,再加入编排器。不要提前。该模式是对一组特定约束的回应,而在没有这些约束的情况下套用它,只会以牺牲实质为代价换来表面的精致。

分享XLinkedIn永久链接6 分钟阅读

相关阅读

这能回答的问题

When should a task be handled by a single script instead of multiple agents?

When subtasks share the same context and tool set, when verification is not genuinely independent, and when the task fits in one context window. In those cases a single validated model call is testable, observable, and faster than a coordinated set of agents.

What is a handoff contract in a multi-agent system?

A handoff contract is a typed payload passed between agents, with a defined schema validated on both sides. It replaces prose summaries, which tend to omit confidence, evidence, and partial-failure information that downstream agents need.

How is information loss measured across agent handoffs?

By comparing what a producing agent emitted against what the consuming agent acted on. If open questions or artefacts in the payload are not addressed by the next action, that is a measurable loss, and its distribution over many runs shows where contracts are too thin.

Why can an orchestrator prompt be harder to maintain than code?

Deterministic code can be unit tested against a typed contract. An orchestrator prompt is a specification in a language with no compiler, so its routing policy can change silently between model versions without any test failing.