
多agent系统这两年从论文里的概念快速变成了工程团队绕不开的落地课题。我所在的团队从去年开始把一个单agent的运维助手逐步演进成六个agent协作的系统中间踩过的坑、推翻过的架构、以及最后沉淀下来的治理规则远比任何一篇综述都来得具体。这篇文章不打算复述“什么是多agent”这种基础概念而是把我们从零到一、再从一到稳定的完整过程拆开讲——包括架构怎么分层、agent之间怎么通信、任务怎么分配、失败怎么兜底、以及最容易被忽略的治理体系怎么建。如果你正在做或者即将做多agent系统的工程落地不管你是架构师、后端工程师还是技术负责人这里面的选型逻辑、参数配置和踩坑记录都能直接拿去参考。1. 为什么单agent撑不住之后必须重新想架构1.1 单agent的能力天花板到底在哪里我们最初的系统是一个典型的单agent架构一个大模型加上一套工具调用负责处理运维场景下的告警分析、日志查询和简单修复建议。刚开始效果不错因为任务边界清晰上下文也不复杂。但业务方很快提出了新需求同一个告警需要同时做根因分析、影响面评估、修复方案生成和变更风险评估。这四个任务如果塞给一个agent会出现几个致命问题。第一是上下文污染。根因分析需要大量日志和调用链数据影响面评估需要服务依赖拓扑修复方案需要历史变更记录这些信息全部塞进一个上下文窗口后模型注意力被严重稀释输出质量断崖式下降。我们实测过当上下文超过六万token后根因定位的准确率从82%掉到54%。第二是工具冲突。不同任务需要的工具集差异很大一个agent挂载十几个工具后工具选择的错误率明显上升模型经常在错误的时机调用错误的工具。第三是无法并行。四个任务串行执行一次告警处理耗时接近三分钟而业务方要求三十秒内给出初步结论。这三个问题不是靠换更大的模型或者写更长的prompt能解决的它们本质上是架构问题。单agent的架构假设是“一个大脑处理所有事”但现实任务天然具有可分解性强行耦合只会让系统又慢又笨。1.2 多agent不是简单地把任务拆开很多人理解多agent就是“把任务分给几个agent分别做”这个理解只对了一半。我们第一版多agent系统就是这么做的四个agent各自独立处理自己的子任务最后把结果拼在一起。结果发现比单agent还差——因为四个agent之间没有任何协调根因分析agent不知道影响面评估agent发现了什么修复方案agent拿到的输入是残缺的。多agent系统的核心难点从来不是“拆”而是“合”。拆开之后agent之间如何共享中间结果、如何协商冲突结论、如何保证整体目标一致这些才是工程落地的真正挑战。我们后来引入了一个协调者agentCoordinator它不直接处理业务任务而是负责拆解任务、分配子任务、收集结果、处理冲突。这个角色的引入让系统准确率回升到88%但同时也带来了新的问题协调者本身成为瓶颈而且协调者的决策质量直接决定整个系统的上限。1.3 架构设计的第一原则按认知负荷分层经过几轮迭代我们总结出一条核心原则多agent系统的架构应该按照认知负荷来分层而不是按照业务功能来分层。什么意思认知负荷低的任务——比如数据查询、格式转换、简单规则判断——应该交给轻量agent用较小的模型和较少的工具就能完成。认知负荷高的任务——比如根因推理、方案权衡、风险评估——才需要重量级agent配备大模型和完整工具链。这个原则直接影响了我们的模型选型。轻量agent我们用7B级别的模型就够响应快、成本低重量级agent用70B以上的模型保证推理深度。如果反过来所有agent都用大模型成本会失控所有agent都用小模型关键任务的质量又无法保证。按认知负荷分层之后我们的整体推理成本下降了约60%而关键任务的准确率没有明显损失。2. 通信机制选型消息队列、共享内存还是直接调用2.1 三种通信模式的实测对比多agent系统里agent之间怎么通信是一个看似简单但影响深远的决策。我们实际尝试过三种模式每种都有自己的适用场景和坑。第一种是直接调用RPC风格。Agent A需要Agent B的结果时直接发起一个请求等待B返回。这种方式实现最简单调试也最直观。但问题是耦合太紧——A必须知道B的地址和接口B挂了A就阻塞而且无法做异步并行。我们早期用这种方式一旦某个agent响应慢整条链路就被拖死。第二种是共享内存或共享状态存储。所有agent读写同一个状态存储比如Redis或者一个共享的数据库。Agent之间不直接通信而是通过读写共享状态来间接协作。这种方式解耦彻底agent可以独立部署和扩缩容。但坑在于并发控制——两个agent同时写同一个key后写的会覆盖先写的。我们踩过一次严重的坑根因分析agent和影响面评估agent同时更新同一个告警的状态字段导致根因结果被覆盖系统给出了完全错误的修复建议。第三种是消息队列。Agent之间通过消息队列传递事件和结果生产者发消息消费者订阅。这种方式兼顾了解耦和可靠性消息可以持久化消费失败可以重试。我们最终选择了消息队列作为主要通信机制但也不是没有代价——消息的时序问题、重复消费问题、以及消息格式的版本兼容问题都需要额外处理。2.2 我们最终的消息队列配置方案具体来说我们用的是RabbitMQ核心配置如下。每个agent有自己独立的输入队列和输出交换机agent之间不直接绑定而是通过一个路由层来转发。路由层根据消息类型和目标agent的注册信息来决定消息投递到哪个队列。这样做的好处是agent的增减不影响其他agent只需要在路由层更新注册信息。消息格式我们定义了一套统一的信封结构包含消息ID、会话ID、发送者、接收者、消息类型、时间戳、优先级和负载。会话ID是关键它把同一个告警处理链路中的所有消息串联起来方便追踪和调试。优先级字段用于处理紧急告警高优先级的消息会被优先消费。重复消费是我们踩过的另一个坑。RabbitMQ在消费者确认超时后会重新投递消息如果agent的处理逻辑不是幂等的就会产生重复结果。我们的解决方案是在消息信封里加一个幂等键agent处理前先检查这个键是否已经处理过处理过就直接返回缓存结果。这个幂等键我们用的是会话ID加消息类型的组合简单有效。2.3 什么时候该用共享状态什么时候该用消息虽然我们最终以消息队列为主但共享状态并没有完全弃用。我们的经验是需要广播或者需要所有agent都能看到的最新全局状态用共享状态存储需要点对点传递、需要可靠投递和重试的用消息队列。举个例子告警的当前处理阶段比如“根因分析中”“影响面评估中”“方案生成中”放在共享状态里所有agent都可以读取用于判断自己是否应该启动。而具体的分析结果——比如根因分析agent输出的根因列表——通过消息队列点对点发给协调者agent。这样分工之后系统既有了全局可见性又保证了关键结果的可靠传递。3. 任务分配与协调协调者agent的设计细节3.1 协调者不是“管理者”而是“调度器”很多人把协调者agent设计成一个“管理者”让它去理解任务、做决策、指挥其他agent。我们第一版就是这么做的结果发现协调者变成了整个系统的单点瓶颈和故障源。它一旦判断失误整个链路全错它一旦响应慢所有agent都在等它。后来我们重新定位了协调者的角色它不是一个“大脑”而是一个“调度器”。它的核心职责只有三件事第一根据预定义的规则把任务拆解成子任务第二把子任务分配给对应的agent第三收集结果并检查完整性。它不做复杂的推理不做业务判断只做调度。这样设计之后协调者的逻辑变得非常简单用规则引擎就能实现甚至不需要大模型。响应速度从原来的秒级降到毫秒级可靠性也大幅提升。3.2 任务拆解用规则还是用模型这是一个很实际的选型问题。用模型做任务拆解灵活能处理没见过的任务类型但不可控可能拆出奇怪的子任务。用规则做任务拆解可控但只能处理预定义的任务类型遇到新任务就抓瞎。我们的方案是混合对于高频的、已知的任务类型用规则拆解保证速度和准确性对于低频的、未知的任务类型降级到模型拆解但拆解结果需要经过一个校验层检查子任务是否在已注册的agent能力范围内。如果校验不通过就拒绝该任务并告警而不是盲目执行。这个混合方案的关键在于规则库的维护。我们每周会review一次模型拆解的任务把其中合理的、高频的拆解模式沉淀成新规则。这样规则库逐渐覆盖大部分场景模型拆解的比例越来越低系统的整体可控性越来越好。3.3 子任务之间的依赖关系怎么处理多agent系统里子任务之间往往有依赖关系。比如影响面评估必须在根因分析之后因为影响面评估需要根因作为输入。这种依赖关系如果处理不好要么导致串行执行太慢要么导致并行执行时数据不一致。我们的做法是在任务拆解阶段就显式声明依赖关系用一个有向无环图DAG来表示。协调者根据DAG来决定哪些子任务可以并行哪些必须等待。DAG的节点是子任务边是依赖关系。协调者维护一个就绪队列只有所有前置依赖都完成的子任务才会进入就绪队列被分配给对应的agent。这个DAG不是静态的而是根据任务类型动态生成的。我们预定义了几种常见的DAG模板比如“根因分析→影响面评估→方案生成→风险评估”是一条链“日志查询”和“指标查询”可以并行。对于新任务类型协调者会根据模型拆解的结果动态构建DAG但同样需要经过校验。4. 失败处理多agent系统最容易被低估的部分4.1 失败模式比单agent复杂得多单agent系统的失败模式相对简单模型输出错误、工具调用失败、超时。多agent系统的失败模式要复杂一个数量级。我们实际遇到过的失败包括某个agent无响应导致整个DAG卡住、agent之间消息丢失导致结果不完整、两个agent给出矛盾结论导致协调者无法决策、agent陷入循环调用、以及最隐蔽的——agent输出了格式正确但语义错误的结果下游agent基于错误结果继续执行错误被逐级放大。这些失败模式里最危险的是最后一种因为它不会触发任何异常系统看起来在正常运行但输出结果是错的。我们曾经遇到过一次根因分析agent因为上下文里混入了无关日志给出了一个错误的根因影响面评估agent基于这个错误根因算出了一个看似合理的影响面修复方案agent又基于这个影响面生成了一个看似合理的修复方案。整个链路没有任何报错但最终建议是完全错误的。如果不是人工review时发现后果会很严重。4.2 我们的三层失败处理机制针对这些失败模式我们设计了三层处理机制。第一层是超时和重试。每个agent处理消息都有超时限制超时后消息重新入队由另一个agent实例重试。重试次数上限是三次超过三次则标记为失败进入第二层。这一层解决的是临时性故障比如网络抖动、agent实例短暂不可用。第二层是结果校验。每个agent的输出在发给下游之前会经过一个校验层。校验层检查输出的格式是否正确、必填字段是否完整、数值是否在合理范围内。对于关键agent校验层还会做语义校验比如根因分析的结果必须包含至少一个根因且根因必须来自已知的故障模式库。校验不通过的结果会被打回重做或者降级到人工处理。第三层是交叉验证。对于关键结论我们会让两个独立的agent分别计算然后比对结果。如果两个结果一致则采信如果不一致则触发人工介入。这一层成本较高我们只用在最关键的根因分析和修复方案生成上。交叉验证的agent使用不同的模型和不同的prompt以降低同源错误的概率。4.3 死循环和资源耗尽的预防Agent陷入循环调用是多agent系统里很隐蔽的问题。比如Agent A调用Agent BAgent B又调用Agent A形成一个环。或者一个agent反复调用同一个工具每次都得到相同的结果但就是不停止。我们的预防措施有两个。第一是在消息信封里加一个调用链字段记录这个消息经过的所有agent。Agent在处理消息前先检查调用链如果发现自己已经在调用链里出现过就拒绝处理并告警。第二是设置全局的调用深度上限和调用次数上限超过上限的任务强制终止。资源耗尽的问题主要出现在并行任务过多时。我们的协调者有一个并发控制器限制同时执行的子任务数量。这个上限是根据后端agent实例数量和每个实例的处理能力算出来的。超过上限的任务在就绪队列里等待而不是直接执行。这样避免了所有agent同时被占满导致系统整体无响应。5. 治理体系让多agent系统从能跑到可控5.1 可观测性不是加日志那么简单多agent系统的可观测性比单agent复杂得多因为一次任务处理涉及多个agent、多条消息、多个工具调用。如果只是每个agent各自打日志出了问题根本串不起来。我们的做法是引入一个全局的追踪ID就是前面提到的会话ID所有agent的日志、消息、工具调用都带上这个ID。然后我们建了一个追踪面板输入会话ID就能看到这次任务处理的完整链路经过了哪些agent、每个agent的输入输出是什么、每个工具调用的耗时和结果、以及最终输出是什么。这个面板在调试和排障时非常有用基本上看一眼就能定位问题出在哪个环节。除了追踪我们还做了指标监控。核心指标包括每个agent的吞吐量、平均处理时长、失败率、重试率消息队列的积压量、消费延迟以及端到端的任务成功率、平均完成时长。这些指标都有告警阈值超过阈值就触发告警。5.2 版本管理与灰度发布多agent系统里每个agent都是独立部署的这意味着版本管理变得复杂。如果Agent A升级了promptAgent B还在用旧版本两者之间的交互可能出问题。我们踩过一次坑根因分析agent升级了输出格式增加了一个字段但影响面评估agent没有同步升级导致解析失败整个链路中断。我们的解决方案是给每个agent的输出定义版本号消息信封里带上版本号。下游agent根据版本号来决定如何解析。同时我们建立了灰度发布机制新版本的agent先只处理10%的流量观察一段时间没有异常后再逐步扩大比例。灰度期间新旧版本并行运行如果新版本出问题可以快速回滚。5.3 成本控制与配额管理多agent系统的成本很容易失控因为agent数量多、调用链长、重试和交叉验证都会增加调用次数。我们做过统计一个告警处理链路平均涉及12次模型调用如果加上重试和交叉验证可能达到20次以上。我们的成本控制措施包括第一按认知负荷分层选模型轻量任务用小模型第二设置每个会话的token预算上限超过上限的任务降级处理或终止第三对交叉验证做采样不是所有任务都做交叉验证只对高风险任务做第四定期review agent的prompt和工具集移除冗余的工具和无效的prompt片段减少不必要的token消耗。配额管理方面我们给每个业务方分配了每日的调用配额超过配额的任务进入低优先级队列等配额恢复后再处理。这样避免了某个业务方的突发流量挤占其他业务方的资源。6. 从能跑到好用几个实战中总结的经验6.1 Prompt设计要面向agent协作而不是单agent单agent的prompt设计关注的是“如何让模型更好地完成这个任务”多agent的prompt设计还要额外关注“如何让模型更好地与其他agent协作”。具体来说每个agent的prompt里必须明确说明你的输入来自哪里、你的输出要发给谁、输出的格式要求是什么、以及遇到不确定的情况时应该怎么做。我们吃过一次亏根因分析agent的prompt里没有说明输出格式模型有时候输出自然语言有时候输出JSON导致下游agent解析失败。后来我们在prompt里强制要求输出JSON并给出了schema示例问题才解决。另一个经验是prompt里要明确告诉agent“如果你不确定就输出低置信度标记而不是编造一个答案”。这个简单的规则大幅降低了错误结论被下游采信的概率。6.2 Agent的能力边界要清晰且可验证每个agent应该只做一件事并且这件事的完成标准是可验证的。比如“查询日志”这个agent它的完成标准是“返回指定时间范围内的日志条目”这是可验证的。“分析根因”这个agent它的完成标准是“返回至少一个根因且根因来自已知故障模式库”这也是可验证的。但如果一个agent的职责是“给出好的建议”这就不可验证因为“好”没有客观标准。我们的原则是如果一个agent的职责无法用可验证的标准来描述就说明这个职责定义得太模糊需要继续拆分。这个原则倒逼我们把很多模糊的任务拆成了具体的、可验证的子任务系统的整体质量因此提升了不少。6.3 人工介入不是失败而是必要的兜底多agent系统再完善也不可能100%自动化。我们的系统里大约5%的任务会触发人工介入触发条件包括交叉验证结果不一致、agent输出低置信度、任务超时超过阈值、以及校验层发现异常。这5%的任务会进入一个人工处理队列由运维人员处理。关键是要让人工介入变得高效。我们做了一件事当任务触发人工介入时系统会自动生成一份“上下文摘要”包含这次任务的所有关键信息——告警内容、各agent的输出、冲突点在哪里、以及系统建议的处理方向。运维人员不需要自己去翻日志看一眼摘要就能快速决策。这个摘要功能把人工处理的平均时长从15分钟降到了4分钟。6.4 治理体系要随着系统演进持续迭代治理体系不是一次建成的而是随着系统演进持续迭代的。我们最开始只有基本的日志和监控后来加了追踪面板再后来加了版本管理和灰度发布最近又加了成本控制和配额管理。每一步都是因为遇到了实际问题才加的而不是一开始就设计好的。我的建议是不要试图一开始就建一套完美的治理体系而是先把系统跑起来遇到问题再补治理。但有一个前提——基础的可观测性必须一开始就有否则出了问题你连问题在哪都不知道根本谈不上治理。所以最小可用的治理体系是全局追踪ID加核心指标监控。这两样东西成本不高但价值极大。7. 关于多agent系统落地我个人的几点体会多agent系统的工程落地技术选型只占三成剩下七成是架构设计和治理体系。我见过太多团队把精力花在选模型、调prompt上结果系统跑起来之后发现agent之间配合得一塌糊涂出了问题也定位不到原因。架构设计和治理体系才是决定多agent系统能不能真正落地的关键。另一个体会是多agent系统不要追求一步到位。我们最开始只有两个agent后来逐步加到六个。每加一个agent都会暴露新的协调问题和治理问题但因为我们是一步步加的每次只需要解决一两个新问题难度可控。如果一开始就设计一个六个agent的完整系统很可能因为问题太多而无法推进。最后一点多agent系统的价值不在于“用了多agent”而在于它解决了单agent解决不了的问题。如果一个任务单agent就能做好就不要强行上多agent因为多agent带来的复杂度和成本是实实在在的。只有当任务确实需要分解、需要并行、需要多视角验证时多agent才是正确的选择。这个判断标准比任何架构原则都重要。