☰
DeepAgents+MCP+A2A+Skills:构建可编排、可互通的多智能体集群
2026/10/3 11:17:47 网站建设 项目流程

上个月我把一个什么都干的单体 Agent 拆成了三个,第二天就后悔了——不是拆错了,是拆完才发现,让多个 Agent 协作这件事,比给单个 Agent 多接几个工具要麻烦十倍。麻烦集中在四件事上:谁负责哪一块(Skills)、用什么方式碰外部世界(MCP)、Agent 之间怎么通信(A2A)、以及最上面谁在盯着整条任务链流转(编排层)。这四个词最近在各种多智能体课程里高频出现,但真正把它们拆开讲透、再串成一个可运行集群的内容并不多。

这篇文章不打算复述概念定义,而是把"DeepAgents + MCP + A2A + Skills 构建可编排、可互通、可扩展的 Agent 集群"这件事,按我实际落地时的思考顺序讲清楚:先想明白为什么要集群化,再逐个解决工具接入、技能沉淀、Agent 互通、任务编排四个问题,最后给一个能直接照着搭的三 Agent 示例。适合已经写过几个 Agent、但觉得单智能体方案到瓶颈的人;纯新手也可以看,我会把必要的基础知识夹在过程中讲。

1. 单体 Agent 的尽头:先说清楚为什么要集群化

1.1 单体 Agent 的"三堵墙"

很多团队是从一个万能 Agent 开始的:给它塞一堆 System Prompt,挂上十几个工具,让它处理所有请求。早期确实爽,但随着场景变复杂,你会撞上三堵墙。

第一堵是上下文墙。每个模型窗口就那么大,工具定义要占、历史对话要占、中间结果要占。工具超过十个之后,光是保证每个工具的参数格式正确、不被其他工具说明干扰,就已经很难了。用户问一句"帮我查天气再写个出行建议",Agent 要把天气工具、地点工具、文档生成工具的定义全部载入上下文,真正的推理空间被压缩得很厉害。

第二堵是工具墙。工具是拿来即用的接口,但业务能力不等于接口。比如"生成周报"这件事,涉及取数、汇总格式、按模板排版、发送到群——你当然可以把它拆成四个工具依次调用,但每个 Agent 都要重新编排一遍流程,编排逻辑散落在 Prompt 里,改一次需求就要改十几个 Prompt。这种能力没有沉淀,换个模型、换个项目就全丢了。

第三堵是协作墙。真实业务的请求很少是单线完成的。有时候需要检索 Agent 先查资料、写作 Agent 再动笔、数据分析 Agent 提供图表数据。单体 Agent 要么把所有活都自己扛导致上下文爆炸,要么你每次在业务代码里写死调用顺序,Agent 之间完全没有"会话"的概念。

所以说,集群化不是赶时髦,而是这面墙撞到一定程度后的自然选择。

1.2 集群化的关键:给四件事分好工

我接触到的"超级多智能体"方案,基本上都在围绕四层做文章:

  • 能力层(Skills):把高频业务流程沉淀成可复用的技能包,解决"Agent 会不会干活"的问题。
  • 工具层(MCP):用统一协议对接外部系统,解决"Agent 有什么工具可用"的问题。
  • 通信层(A2A):让不同 Agent 之间能发现彼此、派发任务、回传结果,解决"Agent 之间怎么协作"的问题。
  • 编排层(DeepAgents):负责任务拆解、路由、状态管理、人工介入,解决"谁在控制整场戏"的问题。

这四层不是并列的可选项,而是层层递进的依赖关系。没有 Skills,Agent 只是个对话机器人;没有 MCP,Agent 碰不到外部数据;没有 A2A,Agent 集群只是"多个独立进程"而不是"一个系统";没有编排层,前三者都是散沙。这也是为什么很多课程把这四个词绑在一起讲,因为它们合起来才是完整的集群方案。

1.3 一个让我下决心的失败案例

我之前做过一个客服 Agent,初始需求是"能查订单、能退换货、能推荐商品"。我一个 Agent 挂了 9 个工具,跑了两个月,效果能接受。后来需求膨胀到需要对接工单系统、知识库、物流查询、优惠券计算,工具涨到 17 个。Prompt 里的工具说明越来越长,模型开始出现"工具幻觉"——明明该查物流,却调了订单接口;两个工具返回矛盾信息时,Agent 也不清楚该信哪个。

最崩溃的一次是促销期间,用户问"优惠券能不能叠加",Agent 把八竿子打不着的三个工具结果缝合出一个错误答案。那之后我彻底把架构改成多 Agent:一个意图识别 Agent 负责路由,一个订单 Agent 只管订单域,一个营销 Agent 只管优惠。跑通之后效果立竿见影,但那段时间踩的坑让我意识到:集群化的架构不是"酷",而是"必须"。

2. MCP:Agent 与世界的"标准化插座"

2.1 先澄清一个基本问题:MCP 是软件协议,不是硬件协议

热搜里经常会看到"MCP 是软件协议还是硬件协议"的疑问,这其实是用 USB-C 类比多了之后的困惑。明确回答:MCP(Model Context Protocol)是应用层的软件协议,走的是 JSON-RPC 2.0,和硬件没有任何关系。大家习惯拿 USB-C 来打比方,是因为它在逻辑上太像了——USB-C 统一了充电口和数据口,而 MCP 统一了 AI 应用接入外部工具和数据的接口。

在没有 MCP 之前,接一个工具是一套代码:对接订单 API 写一套 HTTP 调用,对接数据库写一套查询封装,对接浏览器操作再写一套自动化脚本。每多接一个工具,就是 N×M 的集成矩阵。而且这些工具接口长什么样、参数怎么组织,全部取决于各家 API 自己的风格,Agent 光理解这些接口就要消耗大量上下文。MCP 要解决的就是这件事:把"工具提供方"和"AI 入口"解耦,大家按同一套协议来。

2.2 MCP 的核心模型:Client、Server 与三种原语

MCP 的角色划分很简单:MCP Client 是 AI 应用(宿主),MCP Server 是能力提供方。一次连接的生命周期是全双工的,协议层主要靠三个原语在工作:

  • Tools:Agent 显式调用的函数,比如get_weather、query_order,这是大家最常用的。
  • Resources:需要给 Agent 预加载的数据片段,比如文档、配置文件、数据库 Schema,按 URI 去读。
  • Prompts:服务端预置的交互模板,Agent 可以按特定流程去调用。

从底层角度,这三个原语都是通过initialize、tools/list、tools/call、resources/read这些 JSON-RPC 方法下发与返回的。传输方式目前最常见的是 stdio(本地子进程通信)和 HTTP/SSE(远程服务)。

我刚开始学的时候,把 MCP 当成"一个特别牛的 API 框架",后来才体会到它核心价值不在传输,而在"标准化":所有工具描述长一样、调用方式长一样、错误格式长一样,Agent 只需要一种工具识别能力就能用天下所有的 MCP Server。这对集群编排特别重要——编排层不需要为每个工具写适配器。

2.3 十分钟跑通一个 MCP Server

说再多不如跑一个。FastMCP 是目前最快的上手方式,Python 环境一行安装:

pip install fastmcp

建一个order_server.py:

from fastmcp import FastMCP # 创建一个名为 order-demo 的 MCP Server mcp = FastMCP("order-demo") # 用装饰器定义一个 Tool @mcp.tool() def query_order(order_id: str) -> str: """根据订单号查询订单状态和物流信息""" # 这里实际会去调业务 API,先返回模拟数据 return f"订单 {order_id}: 已发货, 物流单号 SF1234567890" # 再定义一个 Resource,Agent 可以直接读取 @mcp.resource("orders://{order_id}") def get_order(order_id: str) -> str: """读取订单详细信息""" return f"订单 {order_id} 的收货地址: 杭州市西湖区..." if __name__ == "__main__": # stdio 传输方式,适合被本地 Agent 拉起 mcp.run(transport="stdio")

然后启动:

python order_server.py

这时候再用任何支持 MCP 的客户端(Claude 桌面端、Cursor、自研 Agent 框架里的 MCP Client),连接这个 stdio 进程,就能看到query_order工具被自动发现。关键点是:工具的描述字符串"""根据订单号查询订单状态和物流信息"""会被作为工具元数据传给模型,决定模型什么时候调用它。所以写 MCP 工具时,描述要比代码注释还认真,描述写不清楚,模型就不可能在正确时机调用。

2.4 选型参考:MCP 与普通 API 怎么选,Browser Use 与 Playwright 又有什么区别

不是所有接入都非得走 MCP。我的判断标准:

场景推荐方案理由
Agent 要动态决定调用哪个工具MCP工具可被发现、描述可被模型理解
固定流程的数据对接普通 API 封装少一层进程通信,简单直接
需要频繁调整工具集MCP改服务端即可,客户端自动发现
一次性脚本直接函数调用上 MCP 是过度设计

另外热搜里常被问到"Browser Use MCP 和 Playwright MCP 有什么区别"。这两者经常被并排提起,但定位差异很大。Playwright MCP 是把浏览器自动化能力包装成 MCP 工具,它偏"控制":导航、点击、填表、截图,适合做 UI 自动化测试和数据采集。Browser Use MCP 则偏向"理解":它内部会用多模态模型去解析页面结构,把网页上的信息抽成结构化的上下文,再交还给主 Agent 决策。简单说:Playwright 是手,Browser Use 是手加眼睛加脑子。做爬虫、表单操作选 Playwright 更稳;做"读网页然后回答问题"这种任务,Browser Use 更省心。

3. Skills:让 Agent 不只"能调用工具",而是真的"会干活"

3.1 Skill 的本质:一个文件夹加一个 SKILL.md

MCP 解决了"Agent 有什么可用",但很多业务能力不是简单工具调用能覆盖的。比如"写一篇产品周报",你需要先知道周报的结构、取数的口径、排版规范、语气要求。把这些零散指令硬塞进 System Prompt,会污染上下文,换个场景就不适用。

这就是 Skills 的用武之地。一个 Claude-style Skill 本质上是一个目录:

weekly-report/ ├── SKILL.md ├── templates/ │ └── report_template.md └── scripts/ └── collect_data.py

SKILL.md是这个技能包的说明书,里面写清楚触发条件、工作流程、注意事项、输出规范。当 Agent 判断当前任务需要用这个技能时,会读取 SKILL.md,按里面的步骤执行,必要时调用同目录下的脚本和模板。再回头看我的理解:Skill 就是把"业务最佳实践"固化成文件,让不同的 Agent、不同的对话会话都能复用同一套方法论。

3.2 Skills 与 MCP 的分工:一个是工具箱,一个是操作手册

很多同学刚接触时会把 Skills 和 MCP 搞混,甚至会问"有了 MCP 还要 Skill 干什么"。我的理解是:MCP 提供"能做什么"的原子能力,Skill 描述"怎么做才专业"。举一个贴切的类比:MCP 像你家里的工具箱,里面有螺丝刀、扳手、电钻;Skill 像师傅的操作手册,告诉你修一个漏水水龙头要先用扳手拧下螺母、再用生料带缠绕几圈、最后用电钻固定支架。工具是通用的,手艺是专属的。

落到代码架构上,协作方式通常是这样的:Agent 先决定要不要启用某个 Skill,Skill 的执行步骤里再调用 MCP 工具取数。Skill 管流程和判断,MCP 管连接和动作,两者不是替代关系,而是上下游关系。

3.3 自己写一个 Skill:从高频重复任务抽象出来

写 Skill 没有想象中复杂,核心是把你在某个任务上的操作经验结构化成 Markdown。我建议按这个骨架来写:

--- name: weekly-report description: 根据项目周数据自动生成中文周报 --- ## 触发条件 - 用户要求生成周报/月报 - 项目数据已更新到本周 ## 工作流程 1. 调用数据源 MCP 工具获取本周完成需求数、缺陷数、工时 2. 读取 templates/report_template.md 的正文结构 3. 按"本周进展 -> 数据表现 -> 风险与问题 -> 下周计划"组织内容 4. 不要捏造数据, 缺失指标用"待补充"标出 ## 输出规范 - 长度 600-1200 字 - 不使用夸张广告用语 - 数据需要标注来源

真正决定 Skill 质量的是"可操作性"。很多新手写 Skill 通篇都是"生成一份高质量的周报""确保逻辑清晰"这种模糊指令,模型看完等于没看。好 Skill 里每条指令都是可以执行的动作:说要调哪个工具、按什么顺序、产出什么格式、避开什么坑。我把这当成写文档的最高标准:让一个完全没做过这任务的模型,按 SKILL.md 走一遍,能交出七八十分的结果,就算成功。

3.4 Skills 生态:市场上已经有大量现成技能包

如果你不想从零写,现在能找到的现成 Skill 已经非常多。Anthropic 官方有 Skills 市场,社区也有大量聚合仓库。GitHub 搜 Awesome Claude Skills、或者直接搜 "superpowers",能找到不少高质量技能包——从写论文、做前端页面、代码审查、数据分析到各种垂直领域都有。注意一点:下载回来的 Skill 别直接塞给生产环境,先读一遍 SKILL.md,确认里面的工作流和你期望的一致,最好再让 Agent 跑两个测试任务验证一下。社区包里偶尔会夹带一些不合适的指令,这跟装第三方依赖要锁版本、走 review 是一个道理。

前端开发 skills、codex skills、论文写作 skills 这几个方向在社区里非常活跃。多提一嘴 codex 用户关心的:现在不少主流的 IDE 和 Agent 客户端都支持直接把某个 GitHub 仓库里的 Skill 文件夹导入,或者通过官方市场一键安装,安装路径一般会在配置目录下的skills/文件夹,具体以你所用的客户端文档为准。

4. DeepAgents 编排层:队列、路由与集群状态管理

4.1 编排层到底要管哪些事

前面三层解决的是"能力供给",而 DeepAgents 这个层面的核心是"任务如何流转"。如果只有 Skills、MCP、A2A,没有编排层,Agent 集群充其量是"多个能干的个体",不是一个整体。编排层的职责我总结为四件事:

  1. 任务解析:把用户原始请求拆成子任务,决定哪些自己做、哪些分发给其他 Agent。
  2. 路由:根据子任务类型,选择合适的 Agent 或 Skill。
  3. 并发与优先级:多个任务同时进来时,怎么排队、怎么限流、谁能插队。
  4. 状态管理:任务执行到哪一步、中间结果存哪里、出错了怎么重试或转人工。

很多框架(LangGraph、CrewAI)都在做这件事,但如果你像我是自研集群,最朴素可靠的实现是"任务队列 + Worker + 路由表"三者组合。

4.2 一种可落地的编排设计:表驱动的路由 Worker

我不太喜欢把路由逻辑写死在代码里,因为路由规则会随着新 Agent 接入频繁变动。更好的做法是"表驱动"——把路由规则抽成配置,Agent 元信息注册到一张表里,编排 Worker 按表里的字段做分发。伪代码大概长这样:

# 注册表: 每个 Agent 的能力声明 AGENT_REGISTRY = [ { "name": "rag-reader", "description": "擅长从知识库检索资料, 回答事实性问题", "route_keywords": ["查询", "资料", "文档", "知识库"], }, { "name": "data-analyst", "description": "擅长计算指标, 生成数据表格和图表", "route_keywords": ["统计", "指标", "环比", "图表"], }, { "name": "writer", "description": "擅长撰写文章, 报告, 总结", "route_keywords": ["写", "生成报告", "总结", "周报"], }, ] def route_task(task_text: str) -> str: """按关键词粗排, 必要时让意图 Agent 做精细判断""" for agent in AGENT_REGISTRY: for keyword in agent["route_keywords"]: if keyword in task_text: return agent["name"] # 没匹配上, 找兜底 Agent 或转人工 return "fallback"

这个示例故意用了最简单的关键词匹配来说明思路,实际项目里建议用一个意图路由 Agent 来做语义判断。但不管用哪种方式,原则是一样的:调度逻辑和 Agent 能力要解耦,新增一个 Agent 只需要注册它的能力描述,不需要改编排代码。

4.3 状态管理:撑住长任务的骨架

多 Agent 协作的一个大坑是任务周期长,中间某个 Agent 调用了外部 MCP 工具,等了 30 秒,结果自身进程重启了,整个任务链条断了。单体 Agent 时代任务都是短对话,出问题重来就行;集群时代任务可能跑几分钟甚至几小时,中间还有人工审批环节,这时候没有状态持久化,重来一次的成本难以接受。

我的做法是把任务状态写进一个task_status表,字段大致包括:任务 ID、当前步骤、涉及 Agent 列表、每步的输入输出快照、运行批次号、终态标记。每个 Agent 执行完一步就上报一次状态,编排层通过状态机推进下一步。这样即使 Worker 崩溃,也能从最后成功的那一步恢复,不用整条任务重跑。

还有一个经常被忽略的点:编排层要记录"每步是谁干的、用了什么工具、给了什么结果"。别小看这个日志,它一方面用于全链路排障,另一方面,当最终结果不对劲时,你能反推是哪个 Agent 的错误判断导致了问题。没有这个记录,多 Agent 集群就是个黑盒。

4.4 人工介入(HITL):集群里必须留的"人位"

做多 Agent 集群最忌讳的是把一切交给自动化,尤其是涉及对外发送、支付、删除这类不可逆操作。DeepAgents 编排层里必须有一个人工审批节点,任务执行到敏感步骤时,状态变成awaiting_human_approval,暂停在队列里,等人工确认后再继续。我见过不少事故,都是因为贪图全自动,跳过了这个节点。集群越复杂,人工兜底的位置越重要——这不是效率妥协,而是事故保险。

5. A2A:Agent 之间怎么"对上话"

5.1 A2A 解决的核心问题:Agent 发现 Agent

MCP 解决 Agent 与工具之间的纵向打通,而 A2A(Agent-to-Agent)解决的是 Agent 与 Agent 之间的横向互通。它要回答三个问题:我怎么知道其他 Agent 存在?我怎么把任务托付给它们?我怎么拿到结果并确认它完成?

A2A 协议给我的感觉更像"企业微服务通信规范"而不是"工具调用协议"。它定义了一套基于 JSON-RPC 2.0 的交互方式,核心模块有:

  • AgentCard:每个 Agent 对外发布的"名片",声明自己的身份、能力、可接受的输入类型,供其他 Agent 发现。
  • Task:一次跨 Agent 请求的完整生命周期,状态从submitted→working→input-required→completed/failed/canceled流转。
  • Message:A2A 通信中传递的消息体,可以包含文本、文件引用、结构化数据。
  • Negotiation/Partners:用来协商双方能否合作、以什么条件合作。

5.2 AgentCard 到底是什么样的

一个 Agent 接入了 A2A,最简单的事情就是先给出自己的 AgentCard。类似这样:

{ "name": "data-agent", "description": "数据分析服务, 可计算聚合指标并生成图表", "url": "a2a://agent.internal/data-agent", "capabilities": { "streaming": true, "push_notifications": false }, "skills": ["data-aggregation", "chart-generation"] }

其他 Agent 拿到这个卡片后,就能根据skills字段判断"这件事该不该派给它",再通过url发起 A2A 请求。整个发现机制是 可拔插 的,不像单体代码里通过 import 另一个模块来调用那样耦合。这也是"可互通"的落地点:只要对方发布了 AgentCard,不需要知道它的实现语言、部署位置,就能协作。

5.3 A2A 与 MCP 的关系:我会用一个例子说清楚

很多人问"A2A 是不是 MCP 的替代品",真不是。二者解决的是不同维度的问题,我常用一个比方:MCP 是 Agent 的"手脚",A2A 是 Agent 的"同事"。

假设你是一个写报告 Agent,接到主任务"生成季度数据报告"。你需要从数据分析 Agent 那里拿数据,于是通过 A2A 给它发一个 Task:"统计 Q2 各产品线营收,按周聚合"。数据分析 Agent 收到任务后,它的执行阶段会调用数据库的 MCP Server(工具层),把数据取回来,加工成结构化表格,再以 A2A Message 的结果回传给写报告 Agent。

在这条链路里,A2A 负责"Agent 间的请求与响应",MCP 负责"单个 Agent 与外部系统间的动作"。纵向用 MCP 接触世界,横向用 A2A 连接同事,两者是正交组合关系,不冲突。集群架构里,你既要有 MCP 工具层,也要有 A2A 通信层。

5.4 A2A 生态现状与 Spring 集成

A2A 的 SDK 已经比较成熟,官方维护了 Python、TypeScript/JavaScript、Java 等语言的实现。Java 世界里a2a-spring是一个值得关注的集成方向——它基于 Spring AI,能在 Spring Boot 应用里快速把业务服务包装成符合 A2A 规范的 Agent 端点,对已有 Java 技术栈的团队格外友好。如果你们的 Agent 后端是 AI Gateway 或 Java 微服务,可以重点研究一下a2a-spring的 Starter 用法,先跑通一个服务间 A2A 请求,再扩展外部 Agent。

6. 端到端示例:从零搭一个三 Agent 协作集群

6.1 场景定义:一份日报是怎么被协同完成的

理论部分讲多了容易飘,我拿一个真实落地过的场景完整串一遍:企业知识库问答 + 日报生成 + 数据分析。这三个能力分别交给三个 Agent:

  • knowledge-agent:负责知识库检索,回答事实性问题,属于检索 Agent。
  • writer-agent:负责撰写日报、周报,属于写作 Agent。
  • >from fastmcp import FastMCP project_mcp = FastMCP("project-system") @project_mcp.tool() def get_project_metrics(project_id: str, start_date: str, end_date: str) -> str: """获取指定项目的需求数、缺陷数、工时等汇总指标""" # 对接项目管理系统 API ... @project_mcp.tool() def get_milestones(project_id: str) -> str: """获取项目的里程碑列表及进度""" ...

    同时knowledge-agent挂的是知识库 MCP Server,提供search_docs工具。工具层各归各,Agent 通过 MCP Client 连接自己需要的 Server。MCP 的"标准化"好处在这里就体现出来了:三个 Agent 各自只用一套 MCP Client 逻辑,改工具只需动 Server。

    6.4 一起跑起来:一次请求的完整调用链

    编排层收到"生成今天的项目日报"后,识别出这是一种daily-report型任务,路由到writer-agent。writer-agent的流程如下:

    1. 从用户请求里解析出项目 ID 和时间范围。
    2. 通过 A2A 向>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询