引言
他是一位将军,帐下有三千精兵。每次出征,他都把最精锐的部队放在最前线,让他们冲锋、侦察、筑城、运粮、传令——所有事都交给最好的士兵。他以为这样最稳妥,直到某天发现:精锐部队疲于奔命,粮草总在不该断的时候断,而传令兵因为同时身兼数职,把"撤退"误传成了"进攻"。
他坐在帐中,看着沙盘上的混乱,终于明白:最强的兵不该做所有事。他们该站在高处,看清战场的全貌,在关键的分岔口做出判断。而那些重复的行军、筑城、运粮,交给普通士兵就够了——甚至,交给骡子也行。
多 Agent 架构的道理,和带兵打仗没什么两样。
TL;DR
多 Agent 架构有时只是把单 Agent 里的不稳定性拆散到更多组件里。真正有效的分工:强模型只处理规划、分叉和救场,便宜模型执行明确任务,脚本处理确定性动作。
多 Agent 的核心不是角色更多、能力更强。
一个 Agent 负责规划,一个 Agent 负责搜索,一个 Agent 负责写代码,一个 Agent 负责审查。每个角色都用强模型,职责看起来清楚,流程图也很好看。站在架构图前,系统被拆开了,它会更可控。
跑起来之后,事情没这么简单。角色变多,能力没有自动叠加,噪音先叠加了。消息要传递,状态要同步,失败要归因,多个 Agent 之间还会出现互相等待、重复判断和责任边界不清的问题。
单 Agent 的混乱是一个黑盒里的混乱。多 Agent 的混乱是多个接口之间的混乱。
"军师型 Multi-Agent"是一种更冷静的分工:强模型留在判断节点,便宜模型走执行路径,遇到越界问题再回头求助。
强模型不应该站在每一步上
一开始用单 Agent 做项目,所有工具都交给强模型。读文件、搜资料、写代码、跑测试、整理报告,全由它完成。
它能跑。每一步都贵,每一步都慢,很多简单任务并不需要强模型。
读一个文件并摘出关键信息,不需要复杂推理。按模板改一段代码,不需要架构判断。执行一条命令并收集输出,有时候连弱模型都不需要,脚本就够了。
强模型的价值在分叉点:
任务目标不清楚时,要判断该先问人还是先探索。
执行结果和预期冲突时,要判断是代码错、环境错,还是计划本身错。
连续失败之后,要判断继续重试、换路径,还是停下来。
多个实现方案都能走通时,要判断哪一个成本更低、边界更稳。
强模型的价值在这里。它不该像一个昂贵的循环体,被放进每一次工具调用里。
军师型分工的核心
把这种模式叫"军师型",这个名字能提醒我保持边界。
它只有三类角色。
军师负责规划和救场。它用强模型,但没有工具权限。它不能直接改文件,不能跑命令,不能自己完成任务。它只做三件事:理解目标、拆解任务、处理执行器求助。
武将负责执行。它可以用便宜模型,也可以是脚本包装后的自动化流程。它接收明确任务,调用工具,返回结果。它不重新设计系统,不擅自扩大范围。
斥候负责汇报。它不一定是独立 Agent,也可以只是一个格式化函数。它把执行过程压缩成军师需要看的事实:完成了什么、失败在哪里、产物是什么、下一步缺什么。
这个分工的关键在一个硬约束:军师不能执行。
如果强模型既规划又执行,它很容易滑回单 Agent。因为强模型总会觉得自己亲自下场更快、更稳。Prompt 里写"不要执行"当然有用,但不如工具权限为空来得彻底。
架构上的限制比语言上的劝说更可靠。
求助机制比角色命名更重要
很多多 Agent 系统的问题在反馈回路。
如果执行器遇到问题只能失败,系统就退化成一次性 Plan-and-Execute。计划一旦遇到现实里的异常,后面就开始硬跑。
如果执行器遇到一点不确定就求助,成本又会迅速涨回去。强模型被频繁唤醒,整个系统看起来是多 Agent,实际只是绕了一圈的强模型单 Agent。
军师型架构里,求助阈值必须设计清楚。
我更倾向于把问题分成三类。
路径、参数、格式这类小错误,执行器可以自己修一次。比如文件路径多了一层目录、命令参数少了一个 flag、JSON 输出多了一个逗号。这些问题不值得立刻叫军师。
连续失败两次,或者失败原因已经超出局部修复范围,就必须求助。比如任务理解偏了、依赖信息缺失、工具返回和计划不一致。
涉及目标、架构、取舍的问题,执行器不应该自己判断。它必须把上下文交回军师。
求助时,执行器不能只说"失败了"。它至少要提供四个字段:
{
"status": "blocked",
"reason": "具体失败原因",
"attempted": "已经尝试过的动作",
"context": "当前状态和相关产物"
}
这四个字段把情绪化的失败变成可判断的输入。军师不需要看完整噪音,只需要看到足够决策的信号。
系统能否稳定,取决于失败能不能被正确表达。
状态是任务事实
多 Agent 系统还有一个常见问题:上下文会散。
军师不知道执行器刚才改了什么,执行器不知道军师原计划为什么这么拆,审查者只看到最终产物,看不到中间的失败路径。每个角色都像站在不同房间里,通过门缝传递几句话。
我的做法是维护一份共享状态。它不需要一开始就复杂,可以只是一个 JSON 文件:
{
"goal": "用户的原始目标",
"plan": ["军师拆解出的任务"],
"current": "当前任务",
"completed": [],
"blocked": [],
"artifacts": []
}
这是任务事实。
每次军师重新规划时,它看这份状态。每次执行器完成任务时,它更新这份状态。每次出现阻塞时,失败原因也写进去。
系统不再依赖越来越长的对话历史来维持一致性。状态被压缩成少数几个字段,噪音少一点,判断就稳一点。
如果任务是串行的,一个文件就够。并行任务多起来之后,就需要文件锁、数据库或队列。但我不会一开始就上重型基础设施。工程里很多复杂度,应该在问题真实出现之后再支付。
一个最小闭环
这套模式的代码可以非常直接:
async def run_task(goal):
state = create_state(goal)
plan = await strategist.plan(goal)
state["plan"] = plan
for task in plan:
result = await executor.run(task, state)
if result.status == "done":
record_success(state, task, result)
continue
if result.status == "blocked":
record_block(state, task, result)
guidance = await strategist.handle_block(result, state)
retry = await executor.run(guidance.task, state)
update_state(state, retry)
return await strategist.summarize(state)
它先解决最小的问题:计划如何下发,执行如何返回,失败如何进入下一轮判断。
很多系统败在闭环不清楚。请求发出去了,结果回来了,但没人知道这个结果应该改变什么状态,触发什么判断,结束什么任务。
多 Agent 真正难的地方:让每一次说话都改变系统里某个明确的位置。
它适合什么,不适合什么
军师型 Multi-Agent 适合执行步骤多、判断节点少的任务。
比如资料整理、代码迁移、批量检查、报告生成、项目复盘、测试修复。这类任务里,大量步骤是确定性执行,少数节点才需要高级判断。
它也适合成本敏感的场景。强模型被放在分叉点,便宜模型和脚本承担主路径,整体成本会更可控。
但它不适合所有任务。
如果任务本身很简单,一个脚本或单 Agent 就能完成,多 Agent 只是增加包装。
如果每一步都需要深度推理,弱模型没有可用空间,军师型会退化成带有额外通信成本的单 Agent。
如果任务需要开放式讨论,比如研究辩论或创意共创,严格的军师-执行关系反而会压制探索。
架构选择先问:这个任务的难点到底在执行、判断、协调,还是状态一致性。
如果难点不在协调,强行引入协调层,只会制造新的失败面。
将军后来改了规矩。精锐部队不再冲锋陷阵,而是站在高处,用旗语指挥全局。普通士兵负责筑城运粮,骡子负责驮物资。传令兵只传令,不再兼做侦察。沙盘上的混乱慢慢消失了——不是因为兵变少了,而是因为每个人都知道自己该站在哪里、什么时候该动、什么时候该停。
多 Agent 架构的终点,不是让系统更复杂,而是让每个角色都回到它该在的位置。强模型看清分叉,弱模型走完路径,脚本负责重复,状态保存事实。系统不再是一个黑盒里的混战,而是一场有指挥、有分工、有回路的战役。
而将军坐在帐中,看着沙盘上的棋子各归其位,终于能睡个好觉了。
最后
多 Agent 是一种成本和边界的重新分配。强模型负责看清分叉,弱模型负责走完路径,脚本负责重复动作,状态对象负责保存事实。
系统能不能知道每个角色什么时候该出场,什么时候该停下,什么时候必须把控制权交回更高一层。
一个成功的 demo 只能证明主路径没有坍塌。系统真正的轮廓出现在异常、回退和边界里。
多 Agent 如果没有清楚的边界,只会把不稳定性分散到更多房间。房间多了,回声也会变多。