十万个why:多个 Agent 协同干活,为什么跑着跑着它们开始互相“踢皮球”甚至聊起天了?
大家好,我是小富~
前段时间,我们团队搭了一个基于 Multi-Agent 多智能体的自动化写代码系统。
设计初衷非常完美:设定三个 Agent 角色:PM(提需求)、Coder(写代码)、Reviewer(做代码审查)。
我们满心欢喜地以为,给它们拉个群,扔一个需求进去,Coder 写完 Reviewer 提意见,Coder 再改,最后就能直接输出完美的源码。
结果一跑起来,就失控了!
一开始画风还算正常,Coder 写了代码,Reviewer 指出了两处 Bug。但改到第三轮的时候,大模型就开始出幺蛾子了。
后台日志打出来的对话变成了这样:
Reviewer:代码修改得非常完美,不仅解决了 Bug,还考虑了边界情况,干得漂亮!
Coder:非常感谢你的认可!如果还有任何需要优化的细节,请随时告诉我,我很乐意效劳。
Reviewer:目前看已经无可挑剔了,祝你度过愉快的一天!
Coder:你也一样,有新需求我们再联系!
Reviewer:好的,再见!
Coder:再见!
…… 循环 50 次
这俩 Agent 就像两个大妈聊天了,还挺有礼貌~
最后的一行有效代码没存下来,系统陷入死循环,白白烧了我几十万个 Token,直到触发了 API 的并发限流才强行终止。
很多人在做 Agent 开发时都踩过这个坑:Agent 一旦多起来,它们极容易在上下文里迷失目标,开始互相踢皮球、无意义复读,甚至聊起家常。
加了 Prompt 为什么依然拉不回来?
遇到这种死循环,我的第一反应往往是:一定是提示词 Prompt 没写好!
于是我们在 Coder 和 Reviewer 的 System Prompt 里加了警告: 【警告】绝对不允许闲聊!代码 Review 通过后,立刻停止对话!绝不允许说谢谢!
结果前两轮确实有效,但只要对话轮次超过 5 轮,它们又双叒叕开始聊起来了。
甚至有时候把随机性 Temperature 设为 0 都没用,它们会机械性地重复:
“代码无误。”、“收到。”、“代码无误。”、“收到。”
这说明,这根本不是 Prompt 的问题,是由于大语言模型的底层物理特性决定的。
真相大白:大模型没有“下班”的概念
要理解这个诡异的现象,要理解三个反直觉的底层常识
RLHF 的礼貌病
现在的大模型比如 GPT-4, Claude, DeepSeek,在出厂前,都经过了极其严格的 RLHF(基于人类反馈的强化学习)对齐训练。
人类给模型打分的标准之一就是礼貌、有用、温和。这种训练把别人夸你,你要说不客气变成了模型的肌肉记忆。这是深深地刻在了它的权重里,普通的 Prompt 根本压不住这种底层的概率惯性。
上下文漂移(Context Drift)
为什么前两轮不闲聊,第五轮就开始聊了?
因为大模型的注意力机制是有偏好的,它更容易被距离最近的 Token 吸引。
也就是说对话越来越长,最顶部的 System Prompt(不许闲聊)的注意力权重会被稀释。
模型看着最近的 10 句话全是在互相讨论代码细节,它会觉得当前的任务语境就是聊天,彻底忘了最初的任务目标。
自由对话没有状态机
这也是最致命的一点。
我们的微服务调用,有 Request 就有 Response,处理完了立刻 return。
但在基于开源框架,像早期的 AutoGen 或 CrewAI 的群聊模式中,Agent 并没有结束进程的概念。
只要你不从代码层面把死循环给 Break 掉,大模型永远都能预测出下一个字。
如何终结 Agent 的踢皮球?
企业级 AI 工程落地,我们绝对不能把系统的控制权完全交给大模型的自由发散。肯定要把 软件工程的确定性 叠加到 大模型的随机性 之上。
有几种方案
放弃自由群聊,引入有限状态机
目前 AI 开发 LangGraph 这种基于图结构的状态机编排模式是主流做法!
在 LangGraph 中,Agent 不再是聊天窗口里的人,而是图上的节点 Node。Reviewer 审查完代码后,不是输出一段文本,是必须输出一个状态(如 "status": "approved" 或 "status": "needs_revision")。
然后由框架层面的条件边,通过硬代码 if-else 来决定是路由回 Coder 节点,还是路由到终点 END。这样从根本上杜绝了闲聊。
强制使用 Tool Calling 交出控制权
如果不使用复杂的图架构,也可以通过工具调用来强制终止。
我们可以给 Reviewer 提供一个名为 Submit_Final_Result 的工具(Tool/Function)。
在 Prompt 中严格规定,当你认为代码无误时,禁止回复任何文本,必须且只能调用 Submit_Final_Result 工具。
一旦大模型触发了这个工操作,我们的外层系统截获到工具调用请求,直接跳出 while 循环,强行中断。
加入熔断机制
AI 开发永远要假设大模型会发疯。
编写 Agent 循环逻辑,必须加上死循环兜底机制,比如设定 max_turns = 10。
如果对话轮次达到 10 轮依然没有输出结果,系统强制抛出 Timeout 异常,并将这 10 轮废话做一次Summarize 总结缩写,清理掉那些充满客套话的脏数据,然后重新拉起一个新的干净的会话环境。
总结
当你开始做 AI 业务时,你会深刻感受到传统架构与 AI 架构的撕裂感。
我的真实感受是:
不要指望只靠一句 Prompt 就能压住大模型底层的概率分布。
对于 Multi-Agent 系统,自由度越高,系统越脆弱。
把大模型当做纯粹的推理计算单元,把流程流转的控制权握在状态机手里才有安全感!
