当两个 Agent 共享一个工具:多 Agent 系统中的并发 Bug
当你输入“启动另一个智能体来并行处理”的那一刻,你就已经成为了一名分布式系统工程师。你可能没有注意到。框架让它变成了一行代码的改动,演示运行良好,延迟也降低了。但在底层,你刚刚引入了两个在没有协调的情况下读写共享状态的进程 —— 而困扰了数据库领域五十年的每一个竞态条件 (race condition)、更新丢失 (lost update) 和脏读 (dirty read),现在都潜伏在你的智能体堆栈中,伺机而动。
这种情况之所以棘手,是因为故障看起来不像并发 Bug,而像是某个智能体出错了。输出在语法上是有效的,流水线显示绿色,没有抛出异常 —— 然而,客户被收取了两次费用,或者文件丢失了一半预期的内容,又或者一个智能体自信地根据另一个智能体已经覆盖的数字采取了行动。你去调试那个“愚蠢的智能体”,发现它的提示词 (prompt) 没有任何问题,因为提示词根本就不是问题的症结所在。
多智能体系统的卖点在于智能体是独立的。它们运行自己的推理循环,拥有自己的上下文窗口,做出自己的决策。这种独立性恰恰是一种错觉。当 两个智能体接触到同一个文件系统、同一个数据库行、同一个草稿本或同一个 API 令牌的那一刻,它们就不再独立了 —— 它们是竞争共享资源的并发进程,而没有人针对这种竞争进行设计。
独立性的错觉
让我们来看看在典型的智能体部署中,“共享”到底意味着什么。两个研究智能体都将发现写入共享内存库。规划器和执行器都更新一个跟踪进度的任务对象。三个编码智能体都在同一个代码库检出中运行。一群工作智能体都使用同一个带有单一速率限制的 API 密钥进行身份验证。每一个都是竞争点,而且没有一个会主动声明自己是竞争点。
设计师的心理模型是一个整洁的组织架构图:管理者智能体负责分发任务,子智能体去完成孤立的工作,结果返回并合并。而运行时的现实更像是四个实习生在关闭了修订追踪的情况下编辑同一个 Google 文档。组织架构图说他们是独立的,但文档的内容却给出了相反的答案。
让这比经典分布式系统更糟糕的是时间差。传统服务的延迟在某种程度上是可预测的。大语言模型 (LLM) 智能体则不然 —— 一次调用在 200 毫秒内返回,下一次可能需要 9 秒,因为模型决定进行更深入的思考,或者某个工具超时并重试。你在生产环境中遇到的交错情况比你本地测试运行产生的任何情况都要多得多。在每次请求中只有万分之一发生概率的竞态,一旦你在不可预测的智能体时长内处理数百万个请求,就会变成每天都会发生的事故。
