ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MCP与A2A协同:多智能体系统中工具与智能体的边界设计

MCP与A2A协同:多智能体系统中工具与智能体的边界设计 自从多智能体系统开始真正落地到生产环境我越来越觉得MCP 和 A2A 二选一是个伪命题。我做这个系列到现在已经是第六篇前五篇分别聊了基础概念、单 Agent 的工具调用、上下文工程、任务拆分以及安全边界这一篇我想把视角拉回工程现场当你的系统里同时存在 MCP 和 A2A 的时候它们各自的职责边界到底在哪工具接入和 Agent 协作应该怎么分层设计以及为什么浏览器自动化、IDE 集成这类场景会让 MCP 的价值暴露得最充分。如果你正在设计一个真正要跑业务的多智能体系统而不是停留在 Demo 阶段那么 MCP 负责的是智能体怎么拥有一双手A2A 负责的是智能体之间怎么说话。这两件事缺一不可但混在一起就会变成灾难。这篇文章我会围绕协议边界、浏览器类 MCP 选型、IDE 集成实战、A2A 任务流转、可观测性和架构模式这六个方面展开全程以我实际跑过的项目为例尽量少讲抽象概念多讲可以直接抄的工程决策。1. 从工具链到智能体链MCP 和 A2A 各自该管哪一层1.1 MCP 解决的是智能体与外界的连接问题Model Context Protocol 说白了就是给大模型一套标准化碰外部世界的接口。过去每个 AI 应用接一个数据源就要写一套私有适配器接了数据库、接了文件系统、接了浏览器、接了内部 API每套都是意大利面条式的代码。MCP 出现之后客户端、服务端和工具三者的边界变得很干净客户端向 MCP Server 发起请求MCP Server 返回工具列表和能力描述模型在对话过程中动态决定调用哪个工具。我在前面几篇反复强调过一个观点MCP 的工具调用本质上是函数式的。一个 MCP 工具就是一个函数入参出参都是结构化数据模型只需要按照 JSON Schema 生成参数剩下的执行逻辑全部在 Server 端完成。这种设计带来的最大好处是工具可以独立于大模型演进——你换了更强的模型工具不需要改你加了新的数据源模型也无需重新训练。但在真实的多智能体系统里MCP 的边界往往被过度扩展。比如有人会把整个业务流程塞进一个 MCP 工具里工具名是处理订单内部却包含了几十个步骤。这是典型的误用。MCP 工具应该保持原子性粒度应该控制在一个工具只干一件事的层面比如查询库存创建订单发送通知。粒度越细模型的选择空间越大组合能力越强。1.2 A2A 解决的是智能体之间的协作问题A2A也就是 Agent-to-Agent解决的是另一个层面的问题智能体之间如何发现彼此、如何传递任务、如何汇报结果。MCP 的调用关系是单向的客户端调服务端而 A2A 的关系是交互式的一个 Agent 可以发布任务另一个 Agent 可以接收任务并异步返回结果甚至可以主动请求补充信息。我经常用一个比喻MCP 像手A2A 像嘴。手用来执行嘴用来沟通。如果你的系统里只有一个智能体A2A 完全用不上MCP 就够了但当你拆出了规划 Agent、执行 Agent、质检 Agent、知识检索 Agent它们之间必然要围绕任务进行协商、分工和状态同步这个链路不是简单的工具调用能接住的。从协议设计上看A2A 更接近消息协议而非RPC 协议。它的核心元素包括任务Task、消息Message、工件Artifact和状态Status。任务是一次协作的完整单元消息是任务过程中的一次通信工件是任务产生或消耗的产物状态则是任务从提交到完成的演化记录。这四个概念组合起来足以表达我发起了一个任务我更新了任务状态我产出了一份文档你确认一下结果这类完整协作语义。1.3 什么时候说这一层不该用 MCP也不该用 A2A这是我被问得最多的问题之一。很多人在设计架构时恨不得所有交互都套上协议外衣结果是系统复杂到根本无法维护。我自己的判断标准很简单第一如果交互发生在进程内部也就是同一个智能体内部函数之间的调用不需要任何协议。你直接写普通函数调用即可引入 MCP 或 A2A 反而增加序列化和传输开销。第二如果交互是单向且短暂的比如从数据库取一条记录、调用一个搜索接口、执行一条 SQLMCP 是最合适的但如果这种调用发生在多个 Agent 之间而且结果需要回流到原始调用方那就不能简单用 MCP需要考虑 A2A 的任务回执机制。第三如果交互是双向且长周期的比如项目经理 Agent 派发给研发 Agent 一个任务研发 Agent 干到一半发现需求不明确需要反问这时候 MCP 表达不了这种状态流转必须落到 A2A 的任务生命周期里。所以我的结论是MCP 管工具层A2A 管智能体层两者之间是互补关系而不是竞争关系。架构设计的第一步就是先把哪些算工具和哪些算智能体划清楚。工具是确定性的、可预测的、执行粒度小的能力智能体是拥有上下文、能做决策、可能失败并需要重试的实体。这个边界一旦划错后续的所有代码都会拧巴。2. 浏览器操控类 MCP 的选型实录Playwright MCP 与 Chrome DevTools MCP浏览器自动化在 MCP 生态里是最典型的落地场景也是最适合解释工具粒度的样本。我同时试过 Playwright MCP 和 Chrome DevTools MCP两者解决的是同一个问题——让 AI 直接操控浏览器——但技术路径完全不同实际用起来差异巨大。2.1 两者的能力边界一个偏测试框架一个偏浏览器内核Playwright MCP 本质上是把 Playwright 测试框架的能力封装成 MCP 工具。你可以通过它启动浏览器、打开页面、点击元素、填充表单、截图、读取控制台日志甚至拦截网络请求。它的核心优势在于跨浏览器Chromium、Firefox、WebKit 全支持而且 Playwright 这么多年积累的自动化 API 相当成熟元素定位、等待策略、自动重试这些底层逻辑都不需要自己操心。Chrome DevTools MCP 走的则是另一条路子。它直接连接 Chrome DevTools Protocol也就是浏览器内核提供给调试工具的那套接口。你可以通过它读取 DOM 结构、监听网络事件、执行 JavaScript、分析性能、甚至直接操作调试器的断点。它的核心优势在于贴近浏览器原理能做的事情比 Playwright 更深比如直接在 Remote Debugging Port 层面交互观察真实用户会话或者接入已经在运行的浏览器实例。我做个表格方便对比维度Playwright MCPChrome DevTools MCP底层基础Playwright 测试框架CDP 调试协议浏览器范围Chromium / Firefox / WebKitChromium 系适合场景自动化测试、网页操作、表单填写性能分析、网络拦截、JS 注入启动方式框架管理浏览器实例可连接已有 Chrome 调试端口上手难度低API 封装度好高需要理解浏览器调试概念稳定性高等待策略完善依赖页面状态需要自行处理竞态2.2 实测场景把浏览器操作暴露成 MCP 工具给智能体调用我在一个多智能体系统里做了这样一个实验一个网页信息收集 Agent需要通过浏览器访问多个站点提取结构化数据再汇总给另一个分析 Agent 处理。初版设计里我让这个收集 Agent 直接用 Playwright MCP 操作浏览器效果很直接——模型读到工具描述后能自己规划先打开页面再等待元素出现然后提取文本每一步都很流畅。但后来我把场景换成 Chrome DevTools MCP发现了一个关键差异CDP 方式更擅长监听页面上发生的事件比如网络响应、DOM 变化你可以把等待某条件成立变成事件驱动而不是 Playwright 那种轮询式的等待。这在处理单页应用时特别有用尤其是页面内容通过异步请求动态加载的场景——用 Playwright 写等待要小心超时时间设置不对就会误判页面加载完成而 CDP 可以直接监听网络空闲事件精确得多。不过 CDP 也有很让人头疼的地方。它在连接现有浏览器实例时需要开启--remote-debugging-port如果目标 Chrome 版本更新部分协议字段可能调整你的 MCP Server 就得跟着适配。Playwright 的优势则在于它自己管理浏览器生命周期关掉会话浏览器跟着关不会留下僵尸进程。2.3 选型建议什么情况下用哪种跑了几个月的真实项目之后我的选型逻辑基本固化成了三条第一条如果目标网站是常见业务站点结构稳定交互以点击、填表、跳转为主优先选 Playwright MCP。它最稳容错性强模型调用出错率低。第二条如果你要处理的是重前端应用比如 React、Vue 单页应用而且对数据要等到某个网络请求完成后才能拿有强依赖可以考虑 Chrome DevTools MCP通过监听网络事件来获取精确的完成信号。第三条如果你需要在真实用户会话上做操作比如调试已经打开的页面、重现某个用户报障流程CDP 是唯一合理的选择因为 Playwright 是另起炉灶接管不了你手头已经在用的 Chrome 实例。2.4 我在浏览器 MCP 场景里踩过的坑这个坑值得单独拿出来说。用 Playwright MCP 操作页面时如果页面里嵌入了大量 iframe模型的工具调用会频繁失败。原因很简单MCP 工具暴露的是点击元素这类高层操作它内部默认定位的是主 frame而 iframe 内部元素需要切换上下文才能定位。模型并不知道当前目标元素藏在哪个 iframe 里它只会机械地传 CSS 选择器然后收到元素未找到的错误。我的解决方式是在 MCP Server 侧加了一层元素定位兜底。工具执行时如果主 frame 找不到目标元素就自动遍历所有子 frame 再找一遍。这个功能用框架自带的frame_locator可以很优雅地实现但需要你在写 Server 的时候多做一层封装。模型是无感的它以为自己调用的是点击元素实际上背后做了多 frame 定位。这个经验我认为非常值得分享——MCP Server 的职责不只是把 API 暴露出来还应该把工具使用下的复杂性封装掉让模型面对的是最友好的接口。3. 把 MCP 搬进开发环境IDE 集成带来的多智能体开发新常态热搜词里出现了一大串 IDE 和 MCP 结合的内容——通义灵码、Cursor、Trae、Codex、IDEA 插件。开发工具圈的注意力已经从AI 帮我补全代码转向AI 通过 MCP 直接操作我的开发环境。我自己把 Cursor 和 Trae 都实际接入过 MCP Server体验下来最大的感受是IDE 集成 MCP 的表面功夫是AI 能调用外部工具了真正的深层价值是AI 的开发上下文和信息处理边界被无限拓宽了。3.1 通义灵码、Cursor、Trae 里挂 MCP 的异同先说共通的部分。三者本质上都是AI 对话窗口 MCP 客户端的组合你只要提供一个 MCP Server 的地址本地进程地址或远程 HTTP/WebSocket 地址配置好工具列表AI 助手就能在对话过程中按需调用。配置方式也越来越统一基本都会读取一个类似mcp.json的文件。差异主要体现在三处第一工具可见性设计。Cursor 支持你为不同项目配置不同的 MCP Server而且可以在对话里用命令开关具体工具Trae 的配置更倾向于全局统一适合个人开发者通义灵码则是深度绑定阿里云生态在 Spring Boot、Java 项目中集成度更高如果你是这类技术栈MCP 能直接读懂项目上下文。第二对浏览器的控制能力。热搜词里出现了 Trae IDE 搭配 Burp Suite MCP Server 的完整指南这说明 Trae 用户群体对AI 操控安全测试工具有强烈需求。我自己实测过在 Trae 里挂 Burp MCPAI 确实能直接发起请求、查看响应、甚至调用 Burp 的扫描接口这种把专业安全工具纳入 AI 工作流的方式确实能节省大量重复性测试操作。第三远程 MCP 支持。存在通过wss://或 HTTP 地址接入远程 MCP 的场景热词中的远程 MCP 地址也印证了这一点。多智能体系统在 IDE 中接入远程 MCP Server 的价值在于你可以把统一配置管理放到服务端团队里所有人的 IDE 都连同一个 MCP 配置中心工具版本升级无需逐个更新本地。当然远程 MCP 也带来了认证和权限的额外负担下文会详细讲。3.2 直接抄走的 IDE 集成 MCP 模板假设你想在 Cursor 里接一个本地 MCP Server我给你一套可以无脑复制的基本框。在项目根目录创建.cursor/mcp.json{ mcpServers: { local-fileserver: { command: python, args: [run_server.py], env: { MCP_SERVER_PORT: 8866 } } } }这个配置声明了一个本地 MCP Server命令是启动run_server.pyCursor 会在启动工作区时自动拉起它并在对话中加载其工具列表。如果你是本地开发服务器用这种配置就够了MCP Server 的生命周期和 IDE 会话绑定退出 IDE 自动回收不会残留后台进程。如果是远程 MCP Server则变成这样{ mcpServers: { remote-tools: { url: https://mcp.example.com/mcp, headers: { Authorization: Bearer token } } } }有两点必须提醒。第一远程 MCP Server 的鉴权不能只靠 Header 里的静态 Token长期跑的话要考虑令牌轮换第二远程 MCP 的网络延迟会直接影响模型调用工具的体验工具响应超过 5 秒对话流畅度就会断崖式下跌。所以我的一般原则是轻量高频工具放本地重量低频工具放远程。3.3 我在 IDE 集成的 MCP 连接上踩到的两个坑第一个坑是 MCP Server 崩溃后 IDE 不会自动重启它。Cursor 在启动时拉起 MCP Server如果 Server 中途因异常退出IDE 不会感知到进程死亡后续对话继续尝试调用工具只会返回连接失败。我的处理方式是给 MCP Server 写一个简单的守护脚本用supervisor或裸 Python 的循环检测进程存活异常退出就自动拉起同时把崩溃日志写到独立文件里方便排查。第二个坑是工具描述过长会挤占上下文。IDE 自带的补全类 MCP Server 工具数量可能上百个每个工具的描述都是几百字的 JSON Schema模型每次对话都要重新加载这些描述Token 消耗直线上升。这直接导致对话上下文被工具描述挤占真正留给业务内容的窗口变小。解决方式是分层暴露工具。把工具按照使用频率分成活跃工具集和全量工具集默认只暴露使用频率最高的二三十个工具其余工具通过一个加载更多工具的特殊动作按需拉取。这种设计虽然技术上稍微复杂一点但对长会话的体验提升非常明显。3.4 IDE MCP 生态里的安全注意点因为热词里出现了 Burp Suite、Cheat Engine 这类安全工具桥接 MCP 的实践我必须展开说安全性。给 AI 挂上安全工具的 MCP 接口本质上是把高危操作的触发权交到了模型手里。模型的判断能力再强也架不住恶意提示注入——一个网页上的隐藏文本可能诱导模型去调用扫描内部网络的工具。我的建议是三条硬性约束第一所有 MCP Server 接入 IDE 之前必须经过最小权限评审只暴露当前项目确实需要的工具宁缺毋滥。第二高危操作必须加人工确认闸门。MCP Server 暴露给 IDE 的工具应该分成两档只读类和无害操作自动放行带有变更类、注入类、扫描类副作用的高危工具在执行前强制弹窗确认。第三远程 MCP 必须使用独立的服务账号切不可直接把个人 Token 配进 IDE。4. 多智能体协作中的任务流转A2A 消息设计的实战角度如果说 MCP 是把工具变成可被 AI 调用的函数那么 A2A 就是把任务变成可被传递、可被追踪、可被协商的状态机。设计多智能体系统时我见过最常见的错误是拿 HTTP 请求当 A2A 用Agent A 直接调 Agent B 的 HTTP 接口传一个 task 字符串Agent B 处理完同步返回结果。这套逻辑在智能体数量少、协作关系简单时勉强能用但一旦超过两个 Agent你就根本说不清楚某个任务现在到底处于什么状态它被谁处理到哪一步了下一步该由谁来接管。4.1 从调用一个工具到移交一项任务A2A 相比 RPC 式调用的核心差异在于任务是一次一等公民。RPC 是你调我我返回结果调用方全程持有控制权A2A 是我发一个任务给你任务自己会走到终点终点可能是完成、失败、取消或者需要补充信息。这个范式的转变决定了你的系统不能用同步 HTTP 请求来承载 A2A 消息。我的系统里维护了一个轻量的任务中心每个 Agent 都作为任务的生产者或消费者。任务对象包含任务标识、目标 Agent、任务 payload、优先级、截止时间、当前状态、父任务标识和子任务标识列表。A2A 的通信本质上是这些任务对象在图中的流转。4.2 A2A 消息字段的取舍设计不少人来问 A2A 消息里到底要放哪些字段。我给的答案很直接核心字段绝不能超过 10 个。字段越多Agent 之间越容易产生理解偏差。我自己设计的最小字段集如下字段作用必填task_id全局唯一任务标识是agent_id目标 Agent 标识是parent_task_id父任务标识用于任务拆分归并否action任务类型如process,review,summarize是payload任务具体内容是priority优先级否status任务状态pending/processing/completed/failed/blocked是created_at创建时间是updated_at最近更新时间是reply_to结果回传时的目标地址是这个设计的关键是职责单一每个 Agent 只需理解action和payload就能处理任务status只做状态同步reply_to保证了结果可以异步回传。消息体里不应携带上下文大段文本如果任务涉及大量上下文应该用 MCP 工具去查询而不是在 A2A 消息里满载荷传递。消息体到底有多大我见过一个反面案例Agent A 把一份 5 万字的分析文档直接塞进 A2A 消息的 payload 里发给 Agent B结果网络传输耗时三秒对方 Agent 还因为 Token 超限直接拒绝消费。解决方案很简单payload 里只放文档链接或文档 IDAgent B 需要内容时再通过 MCP 的文档读取工具自行拉取。这就是 MCP 和 A2A 协同的典型场景——A2A 负责通知流程MCP 负责按需取料。4.3 防循环、防重复执行多智能体系统跑久了最怕两件事任务环和重复执行。任务环是指任务 A 发给 BB 处理过程中需要 C 的信息于是给 C 发了个子任务结果 C 又回头调用 A 的一个能力最终形成环形依赖整个系统卡死。重复执行是 Agent 因为消息丢失或超时触发了重试机制结果同一个任务被执行了两遍下游数据被污染。我处理这两个问题的方式都是数据层兜底。任务中心在收到新任务时会检查task_id是否已存在如果存在相同task_id直接返回已执行状态不重复投递。这要求 Agent 之间传递任务时必须保持task_id的全局唯一性和幂等语义——同一task_id的任务无论送达多少次都只执行一次。环路检测上任务中心维护了一张简单的依赖图每次新增任务时检查图的拓扑排序是否存在环。在任务量不大的场景这个检测开销完全可以接受。我见过有团队把环路检测做到 Redis 缓存里代价是代码复杂度直线上升但实际上业务规模没到那个量级把时间花在过度设计上并不划算。5. 多智能体系统的可观测性日志、追踪与审计多智能体系统的排错难度和单 Agent 完全不是一个量级。单 Agent 出问题你看模型响应和工具调用即可多智能体出问题你面对的是多个 Agent 之间互相传递消息、修改任务状态、使用外部工具的网状行为。没有一套可观测性设计排查问题的过程就会变成大海捞针。5.1 双层日志工具调用日志与智能体协作日志我在系统设计里强制区分两层日志。第一层是工具调用日志记录每次 MCP 工具调用的入参、出参、耗时和错误。第二层是智能体协作日志记录每个 A2A 消息的收发、任务状态变化、Agent 之间的协商过程。这两层日志要分别存储不要混在一个文件里。分层的理由很朴素排查某个 Agent 没拿到正确的数据这类问题时我要快速定位是 MCP 工具调用阶段出了问题还是 A2A 消息传递阶段出了问题。混在一起会极大地降低检索效率。我现在的做法是工具日志存到本地文件并按天滚动协作日志单独存在专用目录并做结构化 JSON 存储每行一个对象支持用时间戳和 Agent ID 做索引。5.2 时间线重建法遇到复杂问题我不会浪费精力去看日志详情而是先看时间线。把某个任务从创建到完成之间的所有事件按时间顺序排列出来形成一个事件序列Task created - sent to Agent B - Agent B calls tool X - tool X returns error - Agent B retries tool X - ...。有了这条时间线绝大多数问题的发生点都能瞬间定位。比如你会发现某次任务卡住是因为 Agent B 在等待工具 X 的结果而工具 X 的 Server 因为内存泄漏已经挂了三小时——问题的答案不在模型行为里而在基础设施状态里。时间线重建完全可以通过结构化日志实现只要每行日志都带时间戳、自增序列号和链路 ID从任务的task_id延续下来我就可以用脚本一键生成某个任务的完整事件流。这条经验对我排查 AI Agent 类系统帮助极大因为它把黑盒拥抱型行为变成了可以逐帧回放的事件视频。5.3 让每个 Agent 自带审计页更进一步的设计是每个 Agent 都挂一个审计页。所谓审计页就是一个 HTTP 接口返回该 Agent 最近处理过的任务列表、每个任务的输入输出摘要、最近的错误信息以及当前的上下文状态快照。调试时我直接拉取各 Agent 的审计页就能快速判断哪个 Agent 的上下文里进了不该有的内容。这项设计的价值在引入外部信息源后格外明显。搜索引擎工具、浏览页面、读取文档等 MCP 工具都可能把来自外界的噪声内容带进 Agent 上下文进而影响其后续行为。有了审计页我能回溯这个 Agent 看到过哪些信息而不必猜测其行为动机。6. 多智能体架构的模式选择编排、协商与自主6.1 三种协作模式的适用场景多智能体系统的架构模式我大体归为三类编排、协商、自主。编排模式是指有一个中央控制器Orchestrator负责把大任务拆成子任务分配给各个执行 Agent汇总结果。这个模式适合流程固定、职责清晰的任务链。比如代码审查系统总控 Agent 负责拆解审查范围代码分析 Agent、安全扫描 Agent、性能评估 Agent 各自执行最后总控汇总报告。编排模式的优点是可控、可预测缺点是总控容易成为瓶颈而且扩展性有限——所有 Agent 都围着总控转。协商模式是指智能体之间直接对话围绕任务进行讨论、分工和确认没有绝对的上下级关系。这个模式适合需求不明确、需要多轮澄清的任务。比如市场调研规划 Agent和数据采集 Agent之间先协商清楚样本量、时间窗口和数据粒度再各自执行。协商模式的优点是灵活、适应性强缺点是系统复杂度和不可预测性都高必须有良好的任务状态管理托底。自主模式是指每个 Agent 独立启动按照自己的目标运行通过观察和交互来协同完成任务。这个模式最接近多智能体系统的学术理想但在生产环境里我持谨慎态度。自主模式在没有强约束的情况下很容易产生资源竞争、重复劳动和不可预见的连锁反应。如果你想在生产环境上跑自主模式至少要有完善的配额管理和环路检测作为前提。6.2 三种模式的混合设计经验在我自己的系统里通常不是纯用某一种模式而是混合编排。核心流程用编排模式保证稳定分支部分用协商模式保持灵活少数边缘任务尝试自主模式同时强加护栏。举个例子内容生产系统。主流程是编排式的——用户提交主题总控 Agent 分配给大纲 Agent、写作 Agent、配图 Agent、校对 Agent。但大纲 Agent 在生成过程中发现主题涉及专业领域需要咨询知识库 Agent这两个 Agent 之间的交流是协商式的——大纲 Agent 提问知识库 Agent 回答直到信息足够为止。全程不需要总控介入因为它俩的协作只在局部事务里发生。这个混合设计的核心原则是谁适合做什么就让它做什么。总控 Agent 适合做拆分和汇总因为它能看到全局执行 Agent 适合做专业操作因为它有工具和记忆知识 Agent 适合做查询和澄清因为它掌握领域语料。把 MCP 工具挂到最擅长使用它们的 Agent 上把 A2A 消息流通范围控制在局部整体架构会变得清晰得多。6.3 我现在怎么落地这套架构踩过几轮坑之后我现在落地多智能体系统遵循一套流程第一个环节是明确 Agent 角色边界。每个 Agent 只做一件事名字就是它的职责描述。不要在系统里放一个全能助手 Agent这样的 Agent 会让 A2A 消息路由失去意义。第二个环节是列出每个 Agent 需要的 MCP 工具清单。每个 Agent 只挂与其职责直接相关的工具工具挂载越精简模型调用的准确率越高。工具清单写进代码仓库的配置文件方便审计和复盘。第三个环节是画初始协作边界的 A2A 关系图并写死。在系统初始化阶段明确哪个 Agent 能向哪个 Agent 发消息导线关系写死在配置里避免运行时自由扩散。自由扩散看起来灵活但排查问题时会让你崩溃。第四个环节是建设审计体系。任何 Agent 的行为都能追溯到工具调用和消息记录。这不是可选项而是多智能体系统上生产环境的必要前提。7. 最后一篇的实践经验补遗这个系列已经走到第六篇我梳理一下最近一两个项目里沉淀下来的具体经验每个点都对应一次真实踩坑。第一MCP 工具描述必须经过真实调用测试。很多人写工具描述时写得天花乱坠结果模型实际生成的参数格式和 Server 期望的格式对不上。我的流程是写完 Server 后先用一个一次性脚本模拟模型生成请求用随机参数循环调用 20 次一旦出现 schema 校验失败立即修正工具描述或 Server 的解析逻辑。这个测试可以在本地跑几十次成本几乎为零但能省掉模型上线后把大量 Token 浪费在无效调用上的时间。第二MCP Server 的并发做好得很重要。如果你的多智能体系统里有两个 Agent 会同时调用同一个 MCP 工具你就要注意 Server 端的并发处理能力了。用 FastAPI 编写 MCP Server 的话默认异步接口可以撑住一批短请求但如果有个别工具执行时间超过 30 秒建议在工具内部使用任务队列异步化或者至少保证工具的执行逻辑有取消机制。第三A2A 消息的优先级语义在实际业务里几乎必用。每个 Agent 在消费任务时应该先从任务中心拉取高优先级任务再处理低优先级任务。这个机制简单的实现方式是把优先级作为排序字段在任务中心的消费队列里显式体现。我在代码里为每个 Agent 设计了一个每分钟一次的拉取循环每次拉取按优先级排序的子任务列表。这样天然形成了重要任务优先被处理的效果而不需要在消息传递层面做复杂调度。第四MCP 工具的错误信息要写得让模型看得懂。这一点很多资料不强调但实际影响极大。模型在发现工具调用报错时会直接读错误信息来决定下一步。如果你的错误信息是 Internal Server Error 或者一堆堆栈模型只会机械地重试如果你的错误信息是 用户名不存在请检查用户ID参数 或者 该接口需要 POST 方法模型就能据此调整参数。这是用极少成本换来极大工作流流畅度的做法。8. 写在最后的体会多智能体系统设计的核心不在于你用多新的协议框架不在于你编排了多少个容器而在于你有没有把工具层和智能体层的边界理清楚。MCP 把模型和工具之间的接口标准化了A2A 把模型和模型之间的对话标准化了但这只是地基上面盖什么楼、怎么盖依然取决于你对业务的理解和取舍。我这五篇写了这么多本质上都是在讲一件事保持简单、保持可观测、保持边界清晰。如果你在搭建自己的系统时能时刻记得每个 Agent 的职责单一、每个工具的粒度原子、每个任务的流转有迹可循你就已经跑赢了大多数团队。最后分享一个工程习惯给你永远给你的 MCP 工具和 A2A 消息打上schema_version字段。哪怕现在只有你自己在维护系统当版本升级、字段迭代时你会感激这个小小的版本号字段带来的好。
返回列表