news 2026/10/2 5:50:43

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 反而增加序列化和传输开销。

第二,如果交互是"单向且短暂"的,比如从数据库取一条记录、调用一个搜索接口、执行一条 SQL,MCP 是最合适的;但如果这种调用发生在多个 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 MCP,AI 确实能直接发起请求、查看响应、甚至调用 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.py,Cursor 会在启动工作区时自动拉起它,并在对话中加载其工具列表。如果你是本地开发服务器,用这种配置就够了,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 里只放文档链接或文档 ID,Agent B 需要内容时再通过 MCP 的文档读取工具自行拉取。这就是 MCP 和 A2A 协同的典型场景——A2A 负责通知流程,MCP 负责按需取料。

4.3 防循环、防重复执行

多智能体系统跑久了,最怕两件事:任务环和重复执行。任务环是指任务 A 发给 B,B 处理过程中需要 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字段。哪怕现在只有你自己在维护系统,当版本升级、字段迭代时,你会感激这个小小的版本号字段带来的好。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 5:50:42

Android MutableLiveData 核心原理与最佳实践指南

1. 为什么 MutableLiveData 是 Android 开发里最常被低估的“安全开关”MutableLiveData 这个词在 Android 开发者日常交流中出现频率极高&#xff0c;但真正理解它“为什么非用不可”、又“为什么不能乱用”的人&#xff0c;远比你以为的少。我带过十几支移动端团队&#xff0…

作者头像 李华
网站建设 2026/10/2 5:50:39

openrig 配置指南:Claude Code 与 Codex 的 YAML 集成实践

1. 从 openrig 这个名字说起&#xff1a;它到底想解决什么问题第一次看到 openrig 这个标题&#xff0c;我脑子里冒出来的第一个念头是“又一个把 CLI 工具包装成图形界面的壳子”。但把热词列表扫了一遍之后&#xff0c;我意识到它踩中的其实是一个很具体的痛点&#xff1a;Cl…

作者头像 李华
网站建设 2026/10/2 5:50:17

YOLOv11狗狗部位检测实战:从数据集标注到PyQt5界面全流程

1. 从"狗在哪"到"狗身上哪个部位"&#xff1a;这个项目到底在解决什么问题大多数人做目标检测&#xff0c;第一步都是"把狗框出来"。框出来之后呢&#xff1f;没了。但对于很多实际场景来说&#xff0c;知道"这是一只狗"远远不够——宠…

作者头像 李华
网站建设 2026/10/2 5:50:12

DeepSeek Harness桌面端:安装配置、内网部署与插件实战

DeepSeek Harness 官方桌面端终于出了&#xff0c;这应该是很多在 CLI 里熬了几个月的人最想看到的消息。作为一款以编码代理和自动化任务为核心的 AI 工具&#xff0c;Harness 此前最大的门槛就是没有图形界面&#xff0c;装完依赖、在终端里敲命令、看 JSON 日志&#xff0c;…

作者头像 李华
网站建设 2026/10/2 5:49:44

自动扶梯AI图像识别监控系统设计与功能安全落地实践

上个月我接了一个电梯厂的活儿&#xff0c;要在自动扶梯上加一套AI图像识别监控系统。本来以为跟普通安防项目差不多&#xff0c;无非是部署几个摄像头、训练一个检测模型、出报警了推送给值班室——结果越做越深&#xff0c;涉及功能安全标准、安全回路改造、故障注入测试&…

作者头像 李华
网站建设 2026/10/2 5:49:21

手写Canvas转盘抽奖组件:动态绘制、动画控制与概率分配

转盘抽奖算是H5活动页里最经典的互动玩法了&#xff0c;各种营销活动换个皮肤就能用。最近我接了一个偏运营向的项目&#xff0c;要求“每期奖品不同、样式跟着设计师走、中奖结果由后端决定”&#xff0c;简单翻了翻网上现成的Html5转盘插件&#xff0c;要么样式写死不好改&am…

作者头像 李华