多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

MCP与A2A在多智能体系统中的分层定位:工具连接与Agent协作的落地指南

MCP与A2A在多智能体系统中的分层定位:工具连接与Agent协作的落地指南 这个系列写到第八篇前几篇已经把多智能体的架构选型、任务编排、记忆与知识库、工具调用都过了一遍。这篇想专门聊协议层的问题也就是MCPModel Context Protocol和A2AAgent2Agent在设计多智能体系统时到底怎么用。这两个名字最近在各种技术社区里被放在一起讨论的频率非常高但真正动手落地的人很多一开始都会犯同一个错误把MCP和A2A当成了可以互相替换的同层方案。先直接说结论MCP管的是“智能体和工具之间的连接”A2A管的是“智能体和智能体之间的对话”它们在系统里是上下两层的关系不是二选一的关系。这篇会把两个协议的核心边界、编排粒度的选择、工具层实战细节以及多智能体系统里最常见的权限和调试问题一次讲透。无论你是刚接触多智能体的新手还是已经在系统里接了好几个Agent的开发者这篇都应该能帮你少踩几个坑。1. 先理清一个关键问题MCP和A2A各自解决哪一层的问题1.1 MCP管的是“触手”A2A管的是“协作”很多文章把MCP翻译成“模型上下文协议”这个翻译没问题但从工程视角看它真正做的事情是给AI应用一双可以操作真实世界的“手”。你的Agent要读数据库、查文档、调用内部API、操作浏览器全靠MCP来统一接入方式。MCP的三类原语——tools工具调用、resources资源读取、prompts提示模板——已经把AI应用与外部系统交互的常见形态都覆盖了。协议的传输结构也很简单基于JSON-RPC 2.0可以用stdio在本地启动子进程互通也可以走HTTPSSE做远程服务。也就是说MCP本质上是一个“连接器标准”它关心的始终是“AI应用如何安全地触达外部能力”。A2A则完全是另一层楼的问题。A2A的核心是Agent之间的身份发现、能力协商和任务协作。它定义了AgentCard机制每个Agent通过一个公开的卡片声明自己能做什么、用什么格式通信、有哪些能力还定义了完整的Task生命周期submitted、working、input-required、completed、failed、canceled让一个Agent可以安全地把任务委托给另一个Agent并持续跟踪任务状态。用一个生活化的类比MCP像USB-C接口把鼠标、键盘、显示器都统一成一种插口电脑不用为每个外设定制专属连接A2A更像是公司之间的商务合作流程你发一份询价单任务对方确认是否能做协商然后给你回报价和进度状态最后交付成果artifact。1.2 协议边界错位往往就是系统翻车的开始在实际项目里最容易出问题的不是协议本身而是用错了协议的层级。我见过不止一个团队把MCP Server当成Agent之间的通信总线让一个Agent把消息塞进MCP的resource里另一个Agent去那边轮询读取。这种做法不是完全跑不通但绕开了任务状态管理Agent之间无法表达“这件任务我需要你继续推进”这种语义最后消息全堆在资源池里没人消费、没人清理系统一跑就悬着一堆僵尸数据。反过来的误用也常见有人试图用A2A的消息结构去承载高频工具调用把每一次small tool调用都包装成一个A2A Task。结果就是Task状态机被频繁创建和销毁能力协商变成空转性能开销大语义还错位了。一个工具调用只是“一次性动作”而A2A Task是“一个有始有终的协作单元”两者粒度根本不在一个量级上。所以我在做设计时的红线很清晰智能体内部用MCP消费工具智能体之间用A2A传递任务。MCP的调用方是单个AgentA2A的调用方是另一个AgentMCP的返回值直接进入当前Agent的上下文A2A的返回值则要先经过任务状态机再决定要不要进入下一步编排。边界守住了系统架构才不会乱。2. 多智能体编排粒度怎么定从A2A直连到网关模式2.1 Agent一多直连就撑不住了两个Agent之间的通信很简单写个HTTP调用就行。但Agent数量一上来问题就变了。5个以内的Agent你可以用最简单的星型拓扑让编排Agent直接管理所有worker但到了20个Agent、每个Agent又有自己的MCP工具集再让所有节点互相直连服务和消息路径本身就成了一团乱麻。多智能体编排的粒度选择本质上是在回答三个问题谁来发现Agent的能力谁来路由任务谁来维护任务状态这三个问题的答案直接决定了系统是选择集中式、分布式还是混合式。集中的做法是有一个编排Agent它负责拆解用户请求通过A2A把子任务分发给不同的worker Agent。这种模式的好处是决策逻辑清晰坏处是编排Agent容易成为单点瓶颈。分布式的做法则是让Agent之间通过A2A互相发现、自行协商适合节点之间能力相近、没有明显上下级关系的场景。实际工程里最务实的往往都是混合式——核心决策走集中编排非关键路径允许Agent之间直接协商。电网领域最近有个“多智能体协同可靠运行”的方向就很典型。系统里通常会有调度Agent、负载预测Agent、检修计划Agent它们之间如果全部硬编码直连每次业务调整都要改代码。走了A2A之后调度Agent只需要向负载预测Agent发一个“未来6小时负荷走势”的任务预测Agent在AgentCard里声明自己有能力处理双方协商完成后交付结果调度Agent再统一决策。这就是能力发现和任务路由的实战价值。2.2 A2A在工程落地时的具体姿势A2A中有个很有用的设计是AgentCard。每个Agent对外暴露一个JSON-LD格式的卡片声明自己的标识、通信端点、能力列表、认证方式。有了这个机制新增Agent时不需要改动任何业务代码只要注册一张AgentCard其他Agent就能通过服务目录发现它。在工程落地时一般会加一层轻量的A2A Gateway而不是让所有Agent直接互相访问。Gateway负责三件事登记和维护AgentCard、做任务分发路由、做协议版本适配。它不承载业务逻辑只是像一个内网路由器让Agent之间不需要知道对方的真实地址就能对话。{ context: https://a2a-api.lge.com/, name: load-forecast-agent, description: 提供区域电网短期负荷预测服务, url: a2a://internal/load-forecast, version: 1.2.0, capabilities: { skills: [ { id: forecast.6h, name: SixHourLoadForecast, description: 基于历史负荷与气象数据输出未来6小时用电负荷曲线 } ] } }这里要特别提醒一点A2A的Task状态机必须和你的业务单据状态对齐。不要让A2A的TaskState只活在协议层业务侧完全不可见。最稳妥的做法是A2A Gateway收到任务状态变更时同步写一份内部事件到业务消息队列让上游系统能追踪“这个Agent协作任务走到哪一步了”。否则调完接口发现任务状态是completed但你并不知道业务结果有没有真正落库。3. 工具层实战Browser Use MCP和Playwright MCP到底怎么选3.1 工具选型决定了整个系统的能力天花板多智能体系统里有一句大实话编排决定系统的复杂度上限工具决定系统的能力上限。Agent再聪明MCP工具库里的工具质量不行它也做不成事。一个描述含糊的工具LLM要么不会调用要么传错参数最后回传的结果也未必能解析。我见过很多团队把工具封装成几十个“通用方法”Agent根本不知道哪个适合当前任务。所以在MCP Server的设计上有一个原则值得反复强调工具数量宁少勿多工具描述宁长勿短。每个工具的description要像给新同事写交接文档一样说清楚这个工具做什么、适合什么场景、不做什么、参数代表什么。比如一个查询订单状态的工具描述里写“查询订单状态”远远不够要写上“适合在用户询问物流配送进度时使用输入订单号为字符串类型返回结构包含配送公司、当前城市、配送状态码”。3.2 两个浏览器类MCP的真实区别热词里频繁出现的“Browser Use MCP和Playwright MCP有什么区别”这个问题非常典型。两者看起来都是让Agent操作浏览器但设计意图完全不同。Browser Use MCP的设计偏向“任务级代理”它会把浏览器操作封装得更抽象Agent只需要用自然语言说“帮我在搜索框输入关键词并提取前十条结果”它能自动处理元素定位和等待。Playwright MCP则更像“精确遥控器”它保留了选择器、截图、操作步骤的细粒度控制适合需要稳定复现、需要精确验证的场景。我用一个表格把两者的对比列出来方便你直接对照选型对比维度Browser Use MCPPlaywright MCP定位浏览器操作信息提取的任务封装浏览器自动化框架的协议封装Agent使用体验偏向自然语言意图LLM友好需要明确选择器和操作步骤上下文开销会返回结构化提取结果相对可控可能返回大量DOM和执行日志稳定性对页面结构变化容忍度较高需要维护选择器页面改版易失效典型场景信息收集、竞品分析、表单填写自动化测试、重复性巡检、精确交互如果Agent的任务是“调研型”的比如某个爬虫Agent要在多站点收集信息再汇总我倾向于用Browser Use MCP因为它对页面变化的适应性更好Agent不用关心每个站点的DOM结构。如果任务本质是“验证性”的比如上线前的回归巡检或定期打卡操作那就用Playwright MCP因为你可以把操作步骤固化成精确脚本测试稳定性要高得多。这里补充一个工具封装的经验无论选哪个MCP都要在Server侧做一层输出裁剪。浏览器自动化工具很容易返回超出预期的长内容如果不加限制模型上下文几分钟就被撑爆。我的做法是给所有MCP工具设置输出上限默认返回摘要和截断正文并在工具描述里说明“完整内容请用detail参数获取”。4. 可观测性、权限与调试多智能体系统最容易翻车的三个环节4.1 一次请求穿过四层协议怎么追踪多智能体系统的调试难度核心在于一次用户请求可能经过四层跳转用户请求进入编排Agent编排Agent通过A2A把任务发给worker Agentworker Agent调用MCP工具MCP Server再去访问外部服务。这四层之间的日志如果没有统一关联排查问题纯粹靠猜。我的建议是在协议层注入trace上下文。A2A的Request和MCP的Request都支持元信息扩展把traceId从入口一路带下去让每一次Agent协作和每一次工具调用都能串到同一个调用链上。# 伪代码跨协议传递trace上下文 def dispatch_task(agent_id, task_payload): trace_context get_current_trace_context() a2a_request { method: tasks/send, params: { task: { artifactId: ftask-{uuid4()}, message: { role: user, content: [{type: text, text: task_payload}] }, metadata: {trace_id: trace_context.trace_id} } } } response a2a_post(agent_id, a2a_request) return response同时在编排Agent这一层要把A2A的任务ID和MCP工具调用的requestId做一次映射。实际过程中你会发现很多“Agent回答得牛头不对马嘴”的问题根源不在模型而在工具调用返回了旧缓存。如果没有trace贯穿很难定位到是哪个环节拿到的脏数据。4.2 MCP接入的权限模型与常见配置失误MCP的接入权限是很多团队忽视的重灾区。默认情况下MCP Server并不区分请求来源谁拿到通道谁就能调用工具。在多智能体系统里这意味着一个权限敏感的Agent比如负责写数据库的Agent很可能被其他Agent借道调用导致越权。我的做法是给每个Agent分配独立的MCP通道和凭据工具级权限在Server侧做二次校验。不要让一个Service Account走遍全系统。尤其是外部MCP工具接入比如Figma、蓝湖这类设计工具授权流程更要谨慎。拿Figma MCP来说你需要在Figma账户里生成Personal Access Token再作为MCP Server的鉴权凭据但系统里有多个Agent时应该通过OAuth交换用户委托令牌而不是把个人Token硬编码到配置里。否则Agent异常调用你都不知道是哪个用户授权的操作。Codex接入MCP后“找不到MCP”的问题也属于配置层面的高发问题。Codex的MCP配置通常写在config.toml里常见失败原因有三个一是config.toml文件路径不对或格式错误Codex根本没读到配置二是启动命令的可执行文件不在PATH里特别是在macOS上GUI环境启动Codex时PATH被精简找不到npm或node三是MCP Server本身启动失败但日志被忽略了。所以排查这类问题的顺序应该是先用codex mcp list确认配置是否加载再手动在终端跑一次启动命令看是否有报错最后确认MCP Server返回的是合法JSON-RPC响应而不是一段纯文本。别一上来就怀疑模型能力十次有八次是配置问题。4.3 多智能体高频问题排查速查表把我在实际项目里遇到的典型问题整理成一个速查表遇到类似情况可以直接对号入座症状常见原因处理方式工具总是返回“解析失败”MCP Server返回了非JSON格式的错误信息在Server侧统一捕获异常强制输出JSON-RPC格式错误体Agent反复调用同一个工具不停止工具描述不明显Agent误判任务未完成检查工具description明确“该工具完成后的输出形态”两个Agent协作时任务状态一直卡在workingA2A Task状态未同步或子任务异步回调缺失检查A2A Gateway的回调机制增加任务超时重发逻辑Agent回答里带着不相干的上下文MCP工具返回内容过大污染了模型上下文在MCP Server侧做输出裁剪控制返回内容字段Codex提示找不到某个MCP工具config.toml未加载或命令路径错误用codex mcp list确认配置手动执行启动命令排错多Agent并发调用MCP时出现串数据多个Agent共用同一MCP会话上下文未隔离按Agent隔离MCP连接或在请求参数中注入session标识这张表不是理论推演是实打实从项目里踩出来的。多智能体系统的排查难度不在于单点技术多复杂而在于问题常常跨越协议边界。看到工具层报错原因可能在编排层看到任务状态异常原因可能在MCP的并发管理上。所以排查时一定要从trace链路统一视角去看不要盯着某一个节点死磕。写到这里再分享一个我个人在实践中的体会MCP和A2A的协议版本都还在快速演进阶段A2A的规范版本迭代尤其频繁。设计系统时不要和具体协议的某个版本绑死核心是要把“Agent到工具走MCP、Agent到Agent走A2A”这条边界稳定下来然后在边界处做适配层。这样协议再怎么升级系统内部只需要改一个适配模块而不是推倒重来。最后再给一个小技巧给每个Agent的工具调用都做一层“翻译层”把MCP返回的原始JSON统一翻译成系统内部的Schema对象。这层翻译看起来多余但它能把外部工具的数据结构变化隔离在核心业务之外。真实项目里你永远猜不到一个第三方MCP Server会在哪个版本偷偷改返回字段。有这层翻译兜底系统就不会被外部变化突然打断。
返回列表