先说结论:多智能体协作翻车,十次里有八次不是模型不够聪明,而是「通信协议、上下文污染、责任边界」这三件事没做好。模型能力只是地板,工程编排才是天花板。下面我把踩过的坑掰开揉碎讲一遍。
一、先从那个经典的翻车现场说起
很多团队上多 Agent 的路径是一样的:先用单个 Agent 跑通了一个任务,效果惊艳,老板一看「这玩意儿能干活」,立刻拍板「那我们多上几个,一个负责查资料、一个负责写代码、一个负责测试、一个负责汇报,流水线走起来!」
然后事情就开始不对劲了。
单 Agent 的时候,它查完资料直接写,上下文里什么都有,写出来的东西有头有尾。拆成三个 Agent 之后,查资料的 Agent 给了一段摘要,写代码的 Agent 根据摘要写,测试的 Agent 根据写出来的代码测。结果第一轮跑下来,代码里的函数签名对不上,测试直接崩了。
你以为是模型退化了吗?不是。是中间那个「摘要」把关键信息过滤掉了------任务拆太细,中间信息层层丢失,最后拼不回来。
这就是多 Agent 协作的第一个大坑,也是最隐蔽的一个。
二、坑一:任务拆解过度,信息在传递中蒸发
2.1 「信息蒸发」是怎么发生的
单 Agent 干一个任务时,它脑子里的上下文是全的。比如「帮我写一个爬虫,抓取某网站的文章,存成 JSON,处理一下时间格式」。它写代码的时候,知道 URL 长什么样、字段名是什么、时间格式具体是「2026-08-26 10:18:44」还是「1724643524」这种时间戳。
拆成三个 Agent 后:
- Agent A(采集) :负责抓网页,它看到了完整的 HTML,知道时间字段是
"publish_time": "2026-08-26T02:18:44Z"(UTC 格式,带时区)。 - 它给 Agent B 的摘要里写:「文章时间字段为 publish_time,需处理时间格式」。
- Agent B(解析) :拿到摘要,看到「需处理时间格式」,它自作主张把时间转成了北京时间
+8时区。 - Agent C(存储):拿到 B 的结果,直接存了。
最后用户查数据发现时间全错了------因为 A 原文里写的是「已带时区,直接存即可」,但这句话在 A → B 的摘要里被简化成了「需处理时间格式」。
信息每经过一次「摘要」,就丢失一部分细节。经过两次、三次,关键细节就蒸发了。 而每个 Agent 都会基于自己拿到的不完整信息「合理推断」,推断多了,就成了幻觉。
2.2 为什么「拆细」会适得其反
拆任务的初衷是「降低单个 Agent 的认知负担,让每个 Agent 专注做一件事」。这个思路本身没错,错在两点:
-
拆分的粒度超过了任务内在的耦合度。 一个任务如果内部信息强耦合(比如解析和存储必须知道确切的字段语义),强行拆开,就要人为定义「接口」,而接口一旦定义不清,就成了丢信息的口子。
-
每层拆分都引入了「接口契约」,而契约本身就可能是错的。 Agent A 输出「需处理时间格式」,这本身就是一个不精确的契约。B 按自己的理解执行,A 和 B 对「处理时间格式」的理解不一致,错就埋下了。
2.3 怎么破
- 别拆,先想清楚依赖关系。 信息强耦合的步骤,宁可用一个 Agent 串行做,也不要用三个 Agent 接力。减少交接次数,就是减少蒸发次数。
- 交接用「结构化、机器可读」的格式,而不是自然语言摘要。 让 A 输出一个 JSON schema,字段、类型、时区、样例值都写死,B 按 schema 解析,而不是读一段自由文本。结构化接口是防信息蒸发的第一道防线。
- 关键信息显式传递,禁止「隐含假设」。 如果 A 知道「时间已带时区」,必须写进字段里(如
time_zone_aware: true),而不是指望 B 从上下文猜。
三、坑二:Agent 之间消息格式不统一,接口越接越乱
3.1 每个 Agent 都「说自己的方言」
多 Agent 系统里,最容易出现的问题就是:A 输出 Markdown,B 期望 JSON;B 输出 JSON,C 又期望纯文本;C 的输出带了一堆注释,D 解析不了。
一开始可能只是「小问题」,你写个正则、加个解析层糊弄过去。但 Agent 越多、链路越长,这些「方言」就越多,解析层越叠越厚,最后你发现系统里一半的代码是在做「格式翻译」,而不是在干活。
更糟的是,模型对「格式」的遵守是概率性的 。你告诉 A「输出 JSON」,它 95% 的时候输出规范 JSON,剩下 5% 的时候在 JSON 外面包了一层 ```````json```` 代码块,或者多加了一个尾逗号。这个 5% 在多级传递里会被放大:A 有 5% 概率输出错格式,B 解析失败后可能自己也输出错格式,链路越长,最终成功率呈指数下降。
3.2 为什么会「越接越乱」
核心原因是没有在系统层面定义统一的通信协议。每个 Agent 是独立开发的,甚至可能是不同团队、不同时间做的,接口格式各管各的。当你要把三个 Agent 串起来时,只能打补丁,而不是重新设计协议。
打补丁的思路是「谁错改谁」,但模型输出本身就有随机性,你「改」的其实是 prompt,而 prompt 只能降低概率,不能消灭概率。于是你陷入「修了 A 的格式,B 又出问题;修了 B,C 又出问题」的循环。
3.3 怎么破
- 在系统层面定义一套统一的通信协议。 所有 Agent 之间的消息都用同一种信封格式,比如:
json
{
"from": "collector",
"to": "parser",
"task_id": "xxx",
"payload": { },
"schema_version": "1.0",
"status": "success"
}
信封统一了,每个 Agent 只关心 payload 里的业务字段,格式解析的问题就收敛到了一处。
-
用「约束解码」或「结构化输出」把格式变成硬约束,而不是软请求。 如果底层框架支持 JSON mode / function calling / structured output,一定要用。把「请输出 JSON」变成「输出必须符合这个 JSON Schema,否则直接报错重试」,成功率会从 95% 拉到 99.9%。
-
加一层「格式校验 + 重试」的网关。 每个 Agent 的输出先过校验器,格式不对就带着错误信息重试一次。这一层把概率性错误拦在了链路中间,不让它往下游传染。
四、坑三:共享状态/上下文互相污染,越跑越「幻觉」
4.1 共享上下文是「公共厕所」
很多多 Agent 框架图省事,让所有 Agent 共享一个大的上下文窗口(或者共享一个全局 memory)。这看起来高效------「大家都能看到所有信息,多好」。但实际上,共享上下文是所有 Agent 互相污染的温床。
举个真实场景:你有一个「客服 Agent」和一个「技术诊断 Agent」,共享一个会话上下文。用户先跟客服聊了「我的订单号是 123456,商品是蓝色衬衫」,客服 Agent 把这段写进了共享上下文。然后用户转人工技术诊断,问「我的软件装不上」,技术诊断 Agent 看到了共享上下文里的「蓝色衬衫」「订单号 123456」,它可能真的会把「蓝色衬衫」当成某种变量名去查,产生一堆莫名其妙的联想。
这就是典型的上下文污染:一个 Agent 产生的中间信息,被另一个不相关的 Agent 当成了自己的输入。Agent 越「尽职」地利用上下文,污染越严重------因为它会尝试「理解」并「使用」所有它看到的信息,哪怕这些信息跟它没关系。
4.2 共享记忆的「越跑越幻觉」
全局 memory 的问题更隐蔽。假设多个 Agent 往同一个 memory 里写东西,A 写了「用户喜欢蓝色」,B 写错了「用户喜欢红色」(B 在一次对话里理解错了),C 之后每次都读 memory,看到「用户喜欢红色」,于是所有后续推荐都基于「红色」。
错误被写进了「长期记忆」,然后被所有 Agent 反复读取、强化,一个小错误就被固化成系统性的偏见。而且你很难追溯是哪个 Agent、哪次对话写错了,因为 memory 是共享的、无主的。
4.3 怎么破
- 默认「隔离」,不要默认「共享」。 每个 Agent 只拿到它完成任务所需的最小上下文,而不是整个会话的所有历史。需要共享的信息,通过显式传参传递,而不是「大家都看同一个大池子」。
- 上下文要「标注来源和归属」。 如果必须共享,给每条信息打上「谁写的、什么时间、属于哪个任务」,让下游 Agent 能区分「这是我要用的」和「这是别人任务里的垃圾」。
- 写入 memory 要「带所有者和置信度」。 别让 Agent 随便往全局 memory 里写,写入要经过校验,标注来源和置信度,冲突时要能仲裁,而不是谁后写谁赢。
五、坑四:责任边界模糊------谁兜底、谁验收,才是真坑
5.1 三个 Agent,出了问题找谁
这是最容易被忽视、但最要命的一个坑。单 Agent 的时候,出了问题,责任就是「这个 Agent 没做好」,你调它就行。三个 Agent 的时候,问题来了:
- A 说「我输出的没问题,是 B 没用对」。
- B 说「我按 A 给的输入做的,A 的输入就是错的」。
- C 说「我按 B 的输出存的,B 没说要校验」。
责任被分散了,没有人对最终结果负责。 你花三天查日志,最后发现是 A 的输出少了一个字段,但这个字段在 A 的「认知」里是「可选的」,在 B 的「认知」里是「必需的」。两个 Agent 各自都「没做错」,但合在一起就是错的。
5.2 「每个 Agent 都负责,等于没人负责」
多 Agent 系统里最常见的组织病,就是没有定义「验收者」。谁来判断「这个阶段的输出是合格的」?谁来「兜底」------当中间结果明显不对时,谁有权力叫停、重试、或者上报?
如果没有验收者,每个 Agent 都「尽力输出」,然后把结果甩给下一个,下一个「尽力处理」,再甩给下一个。链路的最终输出看起来是「完成了」,但中间任何一个环节的偏差,都会像滚雪球一样累积到最后,而没有人中途拦下来。
更糟的是「甩锅链条」:因为没有人对最终结果负责,出了 bug,大家互相推,最后只能靠「人肉兜底」------找一个工程师把整条链路的日志从头到尾看一遍,人工定位问题。这跟「不用多 Agent,直接人肉干」有什么区别?
5.3 怎么破
- 明确定义每个 Agent 的「输入契约」和「输出契约」。 输入契约 = 它期望拿到什么、什么格式、什么字段必须存在;输出契约 = 它保证输出什么、什么格式、什么字段一定给全。契约写清楚了,「谁错了」就一目了然。
- 给每个环节加「验收 Agent」或「验收逻辑」。 不一定要单独搞一个 Agent,可以是硬编码的校验规则。每个阶段的输出必须通过验收才能进入下一阶段,验收不过就带着错误信息退回重试。验收是防「错误累积」的关键闸门。
- 设置一个「兜底者」(orchestrator)。 有一个总调度器,它不干具体的活,但负责:拆任务、发任务、收集结果、判断结果是否达标、决定重试还是叫停。出了问题,先问 orchestrator,它能告诉你「卡在第几步、那个环节的输出是什么、是否符合契约」。没有 orchestrator 的多 Agent,就是一群没有班长的临时工。
六、给「要不要上多 Agent」的人几句实话
聊了这么多坑,最后说点实在的。
什么时候别上多 Agent:
- 单个 Agent 就能稳定做好的任务,别拆。拆了只会引入通信成本和信息蒸发,得不偿失。
- 任务内部信息强耦合、步骤之间高度依赖的,别拆。这种任务拆了接口反而难定义。
- 你还没有「验收」和「兜底」机制的,先别拆。没有闸门的流水线,是灾难放大器。
什么时候该上多 Agent:
- 任务天然可以并行、彼此独立(比如同时查多个数据源、同时跑多个独立的测试)。
- 不同子任务需要不同的能力或工具权限(比如一个 Agent 有数据库权限,一个有外部 API 权限),单 Agent 不好统一。
- 任务太长,单 Agent 的上下文窗口装不下,需要「分段 + 接力」来突破上下文限制。
上多 Agent 之前,先把这三件事做了:
- 统一通信协议(结构化信封 + schema)。
- 隔离上下文(最小上下文原则,别共享大池子)。
- 定义契约 + 验收 + 兜底(每个环节有输入/输出契约,有验收闸门,有 orchestrator 兜底)。
这三件事没做好,模型再强也是「三个臭皮匠,赛过......三个互相甩锅的臭皮匠」。
七、一句话总结
多 Agent 协作的核心矛盾从来不是「模型会不会」,而是「信息在传递中如何不丢、不污染、不被误解 」,以及「出了问题,谁负责」。
模型能力决定了你的多 Agent 系统「上限能有多高」,而通信协议、上下文隔离、责任边界这三件事,决定了它「下限有多低」。
下限太低的话,单个 Agent 才是最优解。🐟