MCP与A2A实战:多智能体AI系统架构设计与工程优化
1. 从单兵作战到团队协作多智能体系统的架构演进逻辑如果你已经跟着这个系列一路看下来应该对 MCP 和 A2A 这两个协议各自的能力边界有了比较清楚的认识。MCP 解决的是智能体怎么调用外部工具和数据源的问题A2A 解决的是智能体之间怎么互相通信和协作的问题。但把这两个协议放在一起用去搭建一个真正能跑起来的多智能体系统中间还有大量工程层面的决策要做。这一篇我们不再单独讲某个协议怎么用而是把视角拉高聊一聊怎么用 MCP 和 A2A 组合出一套多智能体 AI 系统的完整架构。我会从实际项目出发把架构设计的思路、踩过的坑、以及一些在文档里找不到的经验都摊开来讲。先说一个我自己的判断多智能体系统最大的价值不在于多而在于分工后的协作效率。很多人一上来就搞五六个 Agent结果每个 Agent 的职责边界模糊互相之间通信开销巨大最后效果还不如一个单体 Agent 加几个工具调用。所以这一篇的核心主线是怎么用 MCP 和 A2A 把分工和协作这两件事做扎实。1.1 为什么单体 Agent 迟早会碰到天花板先聊聊为什么需要多智能体。我刚开始做 AI 系统的时候也是能用一个 Agent 解决就绝不用两个。但项目复杂度上去之后单体 Agent 会遇到几个绕不过去的问题。第一个是上下文窗口的物理限制。一个 Agent 要同时处理用户意图理解、工具选择、结果校验、格式输出系统提示词会膨胀得非常快。当你给它挂上十几个 MCP 工具之后光是工具描述就占掉大量 token模型的实际推理能力会被严重稀释。第二个是职责耦合带来的调试困难。单体 Agent 出错了你很难判断到底是意图理解错了、工具选错了、还是参数填错了。所有逻辑搅在一起排查成本极高。第三个是不同任务对模型能力的要求差异很大。有些任务需要强推理能力有些任务只需要快速的信息抽取和格式化。用一个模型打天下要么浪费算力要么能力不够。多智能体架构本质上就是软件工程里关注点分离原则在 AI 系统上的投影。每个 Agent 只负责一个明确的子领域通过 A2A 协议互相调用通过 MCP 协议各自连接自己需要的工具。这样每个 Agent 的提示词可以做得非常精简职责边界清晰调试的时候也能快速定位问题出在哪个环节。1.2 MCP 和 A2A 在多智能体系统里各自扮演什么角色这里我用一个类比来说明。把多智能体系统想象成一家公司MCP相当于每个员工手里的工具箱和操作手册。员工通过 MCP 去使用各种外部系统——查数据库、调 API、读文件、发邮件。MCP 定义的是人和工具之间的接口。A2A相当于公司内部的协作流程和沟通规范。员工之间怎么派活、怎么汇报进度、怎么传递中间结果这些由 A2A 来定义。A2A 定义的是人和人之间的接口。这两个协议解决的是完全不同层面的问题但它们是互补的。一个 Agent 可以同时是 MCP 的客户端调用工具和 A2A 的服务端接受其他 Agent 的任务委派。在实际架构里通常会有这么几种角色分工角色类型核心职责主要使用的协议编排 Agent理解用户意图拆解任务分派给下游 AgentA2A作为客户端领域 Agent处理特定领域的子任务调用专业工具MCP作为客户端 A2A作为服务端工具服务封装具体的外部能力供 Agent 调用MCP作为服务端校验 Agent对结果进行质量检查、格式规范化A2A MCP这个分工不是固定的你可以根据项目需要灵活调整。但核心原则是每个 Agent 的职责要能用一句话说清楚。如果一句话说不清楚说明这个 Agent 承担了太多职责应该继续拆分。1.3 一个真实项目的架构决策过程我拿之前做过的一个智能运维巡检系统来举例。需求是这样的系统需要定期检查一批服务器的健康状态发现异常后自动生成报告并根据异常级别决定是否触发告警。最开始我尝试用单体 Agent 来做把所有巡检逻辑、报告生成逻辑、告警判断逻辑都塞进一个 Agent 里。结果发现几个问题巡检任务需要调用大量 MCP 工具各种监控接口这些工具描述占用了大量上下文报告生成需要很强的文本组织能力但巡检判断需要的是精确的规则匹配能力两种能力放在一个 Agent 里互相干扰。后来我把它拆成了三个 Agent巡检 Agent负责调用各种监控 MCP 工具收集原始数据输出结构化的巡检结果。它的提示词非常精简核心就是按规则检查输出 JSON。分析 Agent接收巡检 Agent 的结构化结果做异常判断和根因分析。它通过 A2A 接收任务不需要直接调用监控工具。报告 Agent接收分析结果生成人类可读的报告并决定是否触发告警。它通过 MCP 连接告警系统和文档系统。拆分之后每个 Agent 的提示词都控制在合理长度内调试的时候也能快速定位问题。巡检数据不对就查巡检 Agent分析逻辑不对就查分析 Agent报告格式不对就查报告 Agent。这个拆分过程让我总结出一条经验Agent 的拆分粒度应该以可独立测试为标准。如果你没法单独测试某个 Agent 的输入输出说明它的职责边界还不够清晰。2. 用 MCP 构建 Agent 的工具层从工具注册到权限隔离MCP 在这个架构里承担的是工具层的角色。每个 Agent 通过 MCP 协议连接自己需要的工具服务。这一章我详细讲讲工具层的设计要点。2.1 MCP Server 的粒度怎么定这是我在实际项目里被问得最多的问题之一一个 MCP Server 应该包含多少个工具我的经验是按业务域来划分 MCP Server而不是按工具数量来划分。比如监控相关的工具查 CPU、查内存、查磁盘、查网络放在一个 MCP Server 里告警相关的工具发邮件、发短信、发 webhook放在另一个 MCP Server 里。这样划分的好处是权限控制更清晰。巡检 Agent 只需要连接监控 MCP Server不需要连接告警 MCP Server天然做到了权限隔离。部署和升级更灵活。监控工具升级不影响告警功能。工具发现更高效。Agent 连接某个 MCP Server 后拿到的工具列表都是同一业务域的语义相关性强模型选择工具的准确率更高。反过来如果你把所有工具都塞进一个 MCP Server会有两个问题一是工具列表太长模型选择困难二是权限没法细分所有 Agent 都能调用所有工具安全风险大。2.2 工具描述怎么写才能让模型选对MCP 工具的描述文本直接决定了模型能不能选对工具。我见过太多项目工具功能没问题但描述写得太随意导致模型频繁选错。写工具描述的几个要点第一描述里要包含什么时候用而不只是能做什么。比如一个查询服务器状态的工具不要只写查询服务器状态而要写当需要获取服务器的实时 CPU、内存、磁盘使用率时使用此工具。适用于巡检和故障排查场景。不适用于查询历史趋势数据。第二参数描述要给出明确的格式示例。模型对格式的敏感度很高如果你在参数描述里给一个具体的示例值模型填错的概率会大幅降低。第三工具名称要有语义区分度。不要出现get_data_1、get_data_2这种命名。用get_server_metrics、get_historical_trends这种一看就知道区别的名字。下面是一个我实际在用的工具定义示例{ name: get_server_metrics, description: 获取指定服务器的实时性能指标包括 CPU 使用率、内存使用率、磁盘使用率、网络流量。适用于巡检和实时故障排查。不适用于查询历史趋势数据历史数据请使用 get_historical_trends 工具。, inputSchema: { type: object, properties: { server_id: { type: string, description: 服务器唯一标识格式如 srv-001、srv-002 }, metrics: { type: array, items: {type: string}, description: 需要获取的指标列表可选值cpu、memory、disk、network。不传则返回全部指标。 } }, required: [server_id] } }这个描述里包含了使用场景、排除场景、参数格式示例模型选错和填错的概率会低很多。2.3 工具调用的错误处理与重试策略MCP 工具调用失败是常态网络抖动、服务超时、参数错误都会导致失败。如果不在 Agent 层面做好错误处理整个系统会非常脆弱。我的做法是在 Agent 的系统提示词里明确错误处理规则工具返回超时错误时最多重试 2 次每次间隔递增。工具返回参数错误时不重试直接把错误信息返回给上游让上游决定怎么处理。工具返回业务逻辑错误比如服务器不存在时记录错误并继续处理其他任务不要因为一个子任务失败就中断整个流程。这些规则写在提示词里模型会在调用工具时自动遵循。当然更可靠的做法是在 MCP 客户端层面做拦截但提示词层面的规则对于大多数场景已经够用了。注意重试策略一定要设置上限。我见过有项目因为没设重试上限工具一直失败一直重试最后把 token 额度耗光了。2.4 用 MCP 做权限隔离的实际方案在多智能体系统里不同 Agent 应该有不同的工具权限。比如巡检 Agent 只能读监控数据不能触发告警告警 Agent 只能发告警不能修改监控配置。用 MCP 做权限隔离有两种方案方案一物理隔离。不同 Agent 连接不同的 MCP Server每个 MCP Server 只暴露该 Agent 需要的工具。这是最简单也最可靠的方案推荐优先使用。方案二逻辑隔离。所有 Agent 连接同一个 MCP Server但在 MCP Server 层面根据调用方身份做权限校验。这个方案实现复杂需要 MCP Server 支持身份识别一般不建议。在实际项目里我基本都用方案一。每个 Agent 的配置文件里只声明它需要的 MCP Server 地址天然就做到了权限隔离。3. 用 A2A 打通 Agent 间的协作链路任务委派与结果回传MCP 解决了工具层的问题A2A 解决的是 Agent 之间的协作问题。这一章我详细讲讲 A2A 在实际项目里的用法。3.1 A2A 的核心交互模式A2A 协议的核心是任务Task这个概念。一个 Agent 可以向另一个 Agent 发送任务接收方处理完后返回结果。这个交互模式看起来简单但实际用起来有几个关键决策点。第一个决策点同步还是异步。如果任务处理时间短比如几秒内可以用同步模式发送方等待接收方返回结果。如果任务处理时间长比如几分钟必须用异步模式发送方发送任务后继续做其他事接收方处理完后通过回调通知。在我的运维巡检项目里巡检 Agent 收集数据可能需要几十秒所以用的是异步模式。编排 Agent 发送巡检任务后继续处理其他事情等巡检 Agent 回调后再进行下一步。第二个决策点任务粒度。一个任务应该包含多少工作我的经验是一个任务应该是一个原子操作要么全部成功要么全部失败。不要把多个不相关的操作打包成一个任务否则部分失败时很难处理。第三个决策点结果格式。A2A 任务的结果格式应该提前约定好。我通常用 JSON Schema 来定义结果格式这样接收方和发送方都有明确的预期减少解析错误。3.2 Agent Card 的设计与能力声明A2A 协议里有一个很重要的概念叫 Agent Card相当于 Agent 的名片声明了这个 Agent 能做什么、接受什么格式的输入、返回什么格式的输出。Agent Card 设计得好不好直接决定了其他 Agent 能不能正确地调用它。我踩过的坑是一开始 Agent Card 写得太简单只写了能做巡检结果编排 Agent 不知道该传什么参数经常传错。后来我把 Agent Card 写得很详细包含能力描述这个 Agent 具体能做什么不能做什么。输入格式需要哪些参数每个参数的类型、格式、是否必填。输出格式返回什么结构的数据包含哪些字段。调用示例给一个完整的输入输出示例。这样编排 Agent 在调用时就有明确的参考出错率大幅降低。3.3 任务编排的几种常见模式在多智能体系统里任务编排模式主要有这么几种串行编排。Agent A 处理完传给 Agent BB 处理完传给 Agent C。适合有明确先后顺序的流程。比如巡检 → 分析 → 报告。并行编排。编排 Agent 同时向多个 Agent 发送任务等所有结果返回后汇总。适合可以并行处理的子任务。比如同时巡检多台服务器。条件编排。根据前一个 Agent 的结果决定下一步调用哪个 Agent。比如分析 Agent 发现异常级别高就调用告警 Agent级别低就只调用报告 Agent。循环编排。某个 Agent 的结果不满足条件时重新调用前一个 Agent。比如报告 Agent 发现数据不完整要求巡检 Agent 重新收集。在实际项目里这几种模式通常是混合使用的。我的运维巡检系统用的是并行 条件的混合模式并行巡检多台服务器然后根据分析结果条件触发告警。3.4 处理 Agent 间的通信失败Agent 间通信失败是必然会发生的。网络问题、接收方 Agent 过载、任务格式不匹配都会导致通信失败。我的处理策略是超时重试。发送任务后设置超时时间超时后重试。重试次数不超过 3 次。降级处理。如果重试仍然失败走降级逻辑。比如巡检 Agent 调用失败就用上一次的巡检数据并在报告里标注数据可能不是最新的。失败通知。如果降级也无法处理通知人工介入。这些策略需要在编排 Agent 的提示词里明确定义让模型知道在什么情况下该做什么。4. 多智能体系统的状态管理与上下文传递这一章聊一个容易被忽视但非常关键的问题状态管理和上下文传递。4.1 为什么状态管理是多智能体系统的难点单体 Agent 的状态管理很简单所有上下文都在一个对话历史里。但多智能体系统里每个 Agent 有自己的上下文Agent 之间传递的是任务和结果不是完整的对话历史。这就带来一个问题下游 Agent 怎么知道上游 Agent 已经做了什么如果不知道可能会重复劳动或者做出与上游矛盾的决策。我的解决方案是在任务里携带上下文摘要。上游 Agent 在发送任务时不只发送任务参数还发送一个简短的上下文摘要说明已经做了什么、发现了什么、期望下游做什么。这个摘要不需要很长几句话就够。但有了它下游 Agent 的决策质量会明显提升。4.2 上下文摘要的生成策略上下文摘要怎么生成有两种方式方式一让上游 Agent 自己生成。在上游 Agent 的提示词里要求它在发送任务时附带上下文摘要。这种方式灵活但依赖模型的总结能力。方式二系统自动生成。在 A2A 客户端层面自动从上游 Agent 的执行记录里提取关键信息生成摘要。这种方式可控但实现复杂。我通常用方式一因为实现简单而且模型现在的总结能力已经足够好了。提示词里加一句在发送任务时用不超过 100 字总结你已经完成的工作和关键发现效果就不错。4.3 共享状态 vs 传递状态多智能体系统里状态可以共享也可以传递。两种方式各有优劣。共享状态是指所有 Agent 访问同一个状态存储比如 Redis、数据库。优点是状态一致性好缺点是引入了外部依赖而且并发访问需要加锁。传递状态是指状态通过任务消息在 Agent 之间传递。优点是没有外部依赖缺点是状态可能不一致而且消息会越来越大。我的经验是小规模系统用传递状态大规模系统用共享状态。Agent 数量少于 5 个时传递状态完全够用。Agent 数量多了之后状态传递的复杂度会急剧上升这时候引入共享状态存储更合适。4.4 实际项目中的状态管理方案在运维巡检项目里我用的是传递状态 轻量共享的混合方案。巡检 Agent 和分析 Agent 之间用传递状态巡检结果直接放在 A2A 任务消息里传给分析 Agent。分析 Agent 和报告 Agent 之间也是传递状态。但有一个共享状态巡检任务的全局状态进行中、已完成、失败。这个状态存在 Redis 里所有 Agent 都可以查询。这样编排 Agent 可以随时知道整体进度不需要等所有 Agent 都返回。这个混合方案的好处是大部分状态通过消息传递避免了共享状态的并发问题关键状态通过 Redis 共享保证了全局可见性。5. 实战中的性能优化与踩坑记录前面几章讲的是架构设计这一章讲讲实际跑起来之后遇到的性能问题和踩过的坑。5.1 Agent 响应慢的排查思路多智能体系统跑起来之后最常见的抱怨就是慢。一个任务从发起到完成可能要几十秒甚至几分钟。排查慢的问题我通常按这个顺序来第一步看是哪个 Agent 慢。在每个 Agent 的入口和出口打日志记录时间戳。这样能快速定位是哪个环节拖慢了整体流程。第二步看是模型推理慢还是工具调用慢。如果 Agent 大部分时间花在等模型返回那是模型推理慢如果花在等工具返回那是工具调用慢。两种情况优化方向完全不同。第三步看是不是串行导致的。如果多个子任务本来可以并行但被写成了串行那优化空间很大。把串行改成并行整体耗时可能直接减半。我遇到过一个案例巡检 10 台服务器原本是串行巡检每台 3 秒总共 30 秒。改成并行后总共只要 4 秒。这个优化效果非常明显。5.2 Token 消耗过大的优化手段多智能体系统的 token 消耗通常比单体 Agent 大因为 Agent 之间的通信也要消耗 token。优化 token 消耗有几个手段精简系统提示词。每个 Agent 的系统提示词只保留必要信息不要把所有规则都塞进去。能放到工具描述里的就放到工具描述里。控制上下文长度。Agent 之间的任务消息不要携带完整的历史记录只携带必要的上下文摘要。选择合适的模型。不是所有 Agent 都需要用最强的模型。巡检 Agent 只需要按规则调用工具用轻量模型就够了。分析 Agent 需要推理能力可以用强一点的模型。缓存重复的工具调用结果。如果多个 Agent 在短时间内调用同一个工具结果可以缓存。比如多个 Agent 都要查同一台服务器的状态第一次查完后缓存起来后续直接读缓存。5.3 我踩过的三个典型坑坑一Agent 之间循环调用。有一次我设计的流程里Agent A 调用 Agent BAgent B 在某些情况下又调用 Agent A结果陷入了无限循环。后来加了调用深度限制超过 3 层就强制中断。坑二任务消息格式不兼容。上游 Agent 发送的任务消息格式和下游 Agent 期望的格式不一致导致下游 Agent 解析失败。后来我强制要求所有 Agent 的任务消息都用 JSON Schema 定义并且在 A2A 客户端层面做格式校验。坑三工具调用结果过大。有个工具返回的数据量非常大几 MB 的 JSON直接塞进 Agent 的上下文导致 token 爆掉。后来在 MCP 客户端层面加了结果截断和摘要逻辑超过一定大小的结果先摘要再返回。5.4 监控与可观测性建设多智能体系统比单体系统更难调试所以监控和可观测性建设非常重要。我通常会做这几件事全链路追踪。每个任务分配一个 trace ID从编排 Agent 到最下游 Agent所有日志都带上这个 ID。这样排查问题时可以快速串起整个链路。关键指标采集。每个 Agent 的调用次数、成功率、平均耗时、token 消耗都要采集。这些指标能帮你快速发现异常。任务状态看板。实时展示当前进行中的任务、已完成的任务、失败的任务。运维人员一眼就能看到系统状态。这些监控设施在项目初期可能觉得是负担但一旦系统复杂起来没有它们根本没法运维。6. 从能跑到好用多智能体系统的迭代方向最后聊聊系统跑通之后怎么继续优化。6.1 提示词的持续迭代多智能体系统的效果很大程度上取决于提示词质量。提示词不是写一次就完事的需要根据实际运行情况持续迭代。我的做法是每次发现 Agent 决策错误就记录下当时的输入和错误输出分析是提示词哪里没说清楚然后针对性修改。积累一段时间后提示词会越来越精准。6.2 Agent 能力的动态扩展系统跑起来之后经常会有新需求比如新增一种巡检项、新增一种告警方式。这时候不需要改所有 Agent只需要在对应的 MCP Server 里新增工具然后更新相关 Agent 的工具列表就行。这种动态扩展能力是多智能体架构的一大优势。单体 Agent 加新功能往往要改提示词、重新测试影响面大。多智能体架构下改动被隔离在单个 Agent 或单个 MCP Server 里影响面小。6.3 从规则驱动到学习驱动我现在的系统主要还是规则驱动Agent 的行为由提示词和工具定义决定。未来可以探索的方向是让系统从历史数据中学习自动优化任务编排策略和工具选择策略。比如系统可以记录每次任务编排的效果分析哪种编排方式在什么场景下效果最好然后自动调整。这需要一套反馈机制和学习算法目前还在探索阶段。我个人在实际操作中的体会是多智能体系统的建设是一个渐进的过程不要一开始就追求完美架构。先把核心流程跑通然后根据实际遇到的问题逐步优化。每次优化都解决一个具体问题积累下来系统就会越来越健壮。另外分享一个小技巧在项目初期可以先用单体 Agent 快速验证业务逻辑等业务逻辑稳定后再拆分成多智能体。这样避免了一开始就陷入架构设计的细节里能更快看到效果。拆分的时候按照可独立测试的原则来划分 Agent 边界基本不会出大问题。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →