讲个最近被问炸了的问题:很多朋友看到 MCP、A2A、Skills、DeepAgents 这四个词同时出现在一个标题里,第一反应是"又出新技术了?学不过来了"。我自己的感受正好相反——这四个东西凑在一起,恰恰说明 AI Agent 开发已经从"调接口玩具"阶段进入"搭系统架构"阶段了。MCP 解决的是 Agent 怎么用工具,A2A 解决的是 Agent 怎么找彼此协作,Skills 解决的是能力怎么复用沉淀,而 DeepAgents 这类深度多智能体框架解决的是前三个怎么被编排成一个整体。
这篇文章我不会给你讲一堆 PPT 概念,我想从工程落地的角度把这些技术挨个拆开,再拼回去,让你看完之后能回答三个问题:这套组合拳各自负责哪一层、它们之间怎么传数据、如果真的要从零搭一个可编排的 Agent 集群,第一步该干什么。适合已经在做 Agent 开发、但总觉得"单 Agent 不够用"的人,或者是想给团队设计一套标准化 Agent 基础设施的架构师。
1. 先搞清楚这四样东西谁干谁的活
1.1 单体 Agent 的天花板在哪里
我先说个扎心的事实:你做出来的单个 Agent 模型再聪明、提示词写得再花,它的能力边界就摆在那——一次只能处理一个上下文,工具调多了上下文就爆,一旦任务链条拉长,中间任何一步输出质量问题都会传导到最终结果。我维护过一个调研类 Agent,单机跑的时候经常出现"前面搜资料搜得挺好,写总结的时候忽然忘了前面一半的内容"。
单体 Agent 靠堆提示词是走不远的。这是所有多智能体架构的出发点:一个 Agent 做不了的事,就拆成多个 Agent 分工;多个 Agent 协作,就必须有协议来沟通。这个"拆开再拼上"的思路,就是"超级多智能体集群"和之前单 Agent 应用最本质的区别。
1.2 四个组件的职责边界
先说结论,这四个词根本不是同一层的东西,混在一起谈才让人头大:
- DeepAgents 是框架层(编排层),它管Agent 集群的拓扑、任务分配、生命周期和状态流转。你可以理解成整个系统的大脑和骨架。
- MCP 是工具层协议,它管 Agent 怎么调用外部工具和数据源。它解决的是"竖切"问题——Agent 向下接入搜索、数据库、文件系统。
- A2A 是互联层协议,它管 Agent 与 Agent 之间怎么发现对方、怎么发起任务、怎么传结果。它解决的是"横连"问题——集群里的各个 Agent 互相协作。
- Skills 是能力层,它管怎么把一组指令、脚本、模板打包成一个可复用的技能包,让 Agent 在执行某类任务时按需加载。它解决的是"沉淀"问题。
打个加水站式的比方:DeepAgents 是调度中心,决定哪个水车去哪条线路;MCP 是标准水管接头,让水车能接上各种水源;A2A 是水车之间的通信协议,让几辆水车能接力;Skills 是司机的操作规程手册,告诉他这条路具体怎么跑最规范。
1.3 别急着写代码,先画一张分层图
我动手写任何多智能体项目之前,一定会先在纸上画一张四层结构图:最底层是资源和工具,往上接 MCP Server;中间层是各个 Agent 角色,每个角色内部挂载若干 Skills;再往上是 A2A 的通信总线,让 Agent 之间能传任务;最顶层是 DeepAgents 的编排器,统筹整个集群。你把这张图贴在工位旁边,后面写代码的时候才发现它对你有用——因为你会发现,现实中遇到的所有"这个 Agent 该不该直接调那个工具的 API"问题,在分层图里都有明确答案:不该,工具调用必须走 MCP;Agent 之间的任何往来必须走 A2A;业务规则必须放进 Skills;任务的拆分与合并只允许编排器管。
2. DeepAgents 的编排模型:把集群当成一支团队在管
2.1 从单 Agent 到多智能体的两级变化
DeepAgents 这类深度智能体框架,在我看来核心价值就是两级变化:第一级是把"一个全能 Agent"拆成"一群专职 Agent";第二级是给这群专职 Agent 建立起一套明确的任务流转规则。这两级变化缺一不可——只拆不编,那叫"多个 Agent 同时跑",不叫集群。
我见过很多团队踩过同一个坑:他们把任务拆给了多个 Agent,但 Agent 之间没有编排层,全靠一个业务脚本硬串。结果业务一复杂,分支逻辑全堆在主控代码里,改一个分支就要动全局。编排层要做的事情就是把这些流程从业务代码里解放出来,变成一种可描述、可观测、可重试的系统行为。
2.2 规划器、执行器、评审器:最小的可运行编排结构
如果你第一次搭 DeepAgents 架构,我的建议是直接从最小的三角色模型开始,别一上来就搞十几个 Agent 的大阵仗。
- 规划器(Planner):接收用户目标,把大任务拆解成子任务列表,决定每个子任务交给谁、依赖关系是什么、验收标准是什么。
- 执行器(Executor):一组专职 Agent,各自负责一类具体的执行工作,比如检索资料、数据分析、代码生成。执行器不关心整体目标,只关心自己拿到的任务项。
- 评审器(Reviewer):对执行器的产出做质量检验,不合格就打回重做,合格才让它进入下一环节。
这套三角色的好处在于它的容错逻辑特别自然:执行器输出质量不靠谱,那是常态,评审器存在的意义就是兜住这个不靠谱。等跑顺了,你可以在三角色基础上扩展出记忆管理、冲突仲裁、多级规划这些高级功能,但底层骨架没变。我在项目里经常跟同事说一句话:多智能体架构的复杂度不是靠加角色解决的,是靠理清角色之间的关系解决的。三角色是最小的关系闭环。
2.3 集群拓扑的伸缩:任务树、角色注册与节点边界
再往后,集群规模一大,编排层要处理的就不只是"任务怎么派",还有"角色怎么注册、节点怎么发现、任务树怎么组织"。这就是我之前踩过的一个大坑:初期把所有 Agent 写死在配置里,后面每加一个角色就要改一遍编排代码,非常痛苦。
正确做法是把角色注册做成动态的。每个 Agent 在启动时向编排器注册自己的能力(能做什么、接受什么输入、产出什么格式),编排器维护一个角色注册表。规划器拆解任务后,根据注册表匹配执行器,而不是写死在代码里的映射关系。DeepAgents 框架能被称为"可扩展",靠的就是这套注册机制——加新能力不用改旧逻辑,动态注册即可。
任务树方面,我建议除了分解任务,还要显式记录任务间的依赖关系。A 任务没完成,B 任务就不能启动,这类约束在编排器里必须是一等公民,不能靠执行器自觉。否则一旦并发跑起来,数据竞争和重复执行会让你排查到怀疑人生。
3. MCP 落地的关键细节:让工具真正成为可插拔的"技能插座"
3.1 一次完整的工具调用里发生了什么
MCP(Model Context Protocol)这套标准的本质,是给"Agent 用工具"这件事定了一个统一协议。我以前写 Agent 调用外部工具,每个工具一个 SDK,写法五花八门;接 MCP 之后,工具发现和工具调用都走同一套 JSON-RPC 2.0 消息格式。
一次完整调用的链路是这样的:MCP Client 先跟 MCP Server 建立连接,发起 initialize 握手,服务器返回自己的能力清单(tools、resources、prompts 等);客户端确认后,调用 tools/list 拉取可用工具列表;Agent 根据工具描述决定用哪个,发起 tools/call 请求;服务器执行具体逻辑,返回结构化结果。整个过程对 Agent 来说,所有工具只剩两个动作:列出、调用。
我贴一个最简的 MCP 工具调用请求,你感受一下这个"统一"的含义:
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "web_search", "arguments": { "query": "2025 LLM Agent 技术选型", "count": 10 } } }不管这个 web_search 背后是搜索引擎 API、还是你们公司内部的文档检索服务,Agent 看到的接口都是一样的。这才是 MCP 的威力——它把工具的异构性屏蔽掉了。
3.2 工具定义的质量决定了 Agent 的下限
MCP 落地之后,我发现一个经常被忽略的细节:工具本身怎么写 description,直接影响 Agent 用得好不好。这是我最想提醒你的一件事。
MCP 的工具描述是给模型看的,不是给人看的。你得让模型一看就知道"这个工具什么时候该用、什么时候不该用、参数怎么填"。我见过不少团队的 MCP Server 把工具描述写成"获取天气信息",模型真需要天气的时候倒是会调,但遇到"今天适不适合户外跑步"这种需要组合推理的场景,模型往往不会想起去调天气工具——因为描述里没写"可用于判断户外活动适宜性"。
同时还要小心参数定义的膨胀。给工具定义二十个参数,Agent 每次调用前都要把参数说明塞进上下文,Token 很快会被吃光。我的习惯是:一个工具的入参控制在七个以内,能用可选参数就别用必填参数,能用字符串就别用嵌套对象。工具是给 Agent 用的,参数越重,模型越容易填错,推理成本也越高。
3.3 传输方式与部署形态怎么选
市面上 MCP Server 的传输方式主要有两种:stdio 和 Streamable HTTP(老版本的 SSE 也在用)。简单说,stdio 适合本地进程内工具,比如给 IDE 插件挂一个代码分析工具,进程起落由 Client 管;HTTP 适合远程工具服务,部署在服务器上供多个 Client 并发调用,这也是企业级接入的常态,因为工具可以独立扩缩容。
我现在的选型原则是:能远程化就远程化。因为 stdio 模式下,每个 Client 要拉起一个子进程,Agent 集群一多,进程数跟着爆炸,资源根本扛不住。HTTP 模式可以把同一个 MCP Server 暴露给集群里所有 Agent,共享连接池,维护也方便。唯一要留意的是鉴权——HTTP 接口一旦暴露,工具那就是真暴露了,JWT 或者 API Key 至少要上一种,千万别裸奔。
4. A2A 落地细节:Agent 与 Agent 之间的任务交接协议
4.1 Agent Card:先让对方知道你能干什么
MCP 解决的是 Agent 向下调工具,A2A(Agent-to-Agent)协议解决的是 Agent 横向找 Agent。这个区别一定要记牢:A2A 不是用来调工具的,是用来发起协作任务、交换结果的。
A2A 协议里有个特别务实的设计:Agent Card。每个 Agent 通过一个 JSON 文件向外宣告自己的能力、入口地址、支持的功能特性。其他 Agent 想找协作对象,先去拿对方的 Agent Card,解析完卡片,就知道这个 Agent 能干什么、支持流式响应还是推送通知。这个模式和人类社会的"自我介绍+名片"是一模一样的,好处是解耦——调用方不需要提前硬编码对方的接口,只要知道去哪个地址取名片就够了。
一个最简的 Agent Card 片段长这样:
{ "name": "research-agent", "description": "针对给定主题执行深度资料检索并输出摘要", "url": "https://agent.example.com/research", "capabilities": { "streaming": true, "pushNotifications": false }, "skills": [ { "id": "deep_research", "name": "深度调研", "description": "输入主题,输出带来源的结构化调研摘要" } ] }4.2 任务生命周期与消息格式
A2A 协议的核心动作是"任务"(Task),不是"消息"(Message)。这个设计我一开始没太在意,后来才发现它是整个协议最聪明的地方。发起方创建任务,返回任务 ID,后续所有状态更新都挂在任务 ID 下面,任务的公开状态包括 submitted(已提交)、working(执行中)、input-required(需要补充输入)、completed(完成)、canceled(取消)、failed(失败)等。
有了任务 ID 和状态机,分布式系统里最麻烦的"结果对账"就变得可实现了。请求方不用一直阻塞等待,可以轮询、可以订阅状态回调,也可以使用流式输出持续接收进度。各 Agent 之间完全是异步协作,不会因为某个 Agent 响应慢而把整条链路卡死。
创建任务的请求同样是 JSON-RPC 2.0 风格:
{ "jsonrpc": "2.0", "id": 2, "method": "tasks/send", "params": { "taskId": "task-20250101-001", "message": { "role": "user", "parts": [ { "text": "请调研 MCP 协议在 2025 年的生态现状,输出一份 1000 字摘要" } ] } } }你可以看到,A2A 把任务 ID 的幂等性直接做进了协议层——同样的 taskId 重复发消息,服务端可以根据状态决定是忽略还是补充处理。这一手对防止重试风暴简直是刚需。
4.3 流式输出与多 Agent 协作的边界
A2A 支持流式输出,这个能力在多 Agent 协作里非常重要。比如规划器把任务派给研究 Agent,研究 Agent 边搜边返回中间结果,规划器就能更早地发现"这个方向没资料"并提前调整方案,而不是等到最后拿到一个失败的最终结果才反应过来。
但我也要提醒你:A2A 别啥事都往上传。Agent 之间的中间调试信息、内部思考链、临时缓存,这些不应该通过 A2A 传递。A2A 上流动的应该是"协作者需要知道的业务信息"——任务说明、结果、附件、状态变化。你把内部噪声全传上去,协作双方 Token 都不够烧的。边界画清楚了,A2A 才能真的轻量、高效。
5. Skills:把团队的提示词和脚本沉淀成标准作业包
5.1 SKILL.md 到底写了什么
Skills(技能包)这层,我理解它解决的是"怎么让 Agent 稳定复现一套高质量工作方法"的问题。最简单的形态就是一个目录加一个 SKILL.md 文件,里面用 Markdown 写清楚:这个技能是干什么的、触发条件是什么、执行步骤是什么、输出规范是什么。还可以附带一些模板文件、脚本、示例数据。
一个调研报告写作技能包的骨架大概是:
--- name: report-writing description: 产出结构化的中文技术调研报告,包含摘要、背景、对比表、结论与参考来源 --- # 报告写作规范 1. 先输出摘要,控制在 200 字以内。 2. 正文按"背景—现状—对比—结论"四段结构展开。 3. 所有对比必须用表格呈现。 4. 结论部分必须给出明确的选型建议。 5. 引用来源必须带链接。Skill 的价值在于:它把"团队最佳实践"从人的脑子里搬到了文件系统里。新人接手项目的时候,不需要问"你们老员工写的报告怎么那么整齐",把技能包挂上就行。它做的是 Agent 的"标准作业指导书"。
5.2 Skills、MCP 和 Prompt 三者如何分工
这里我给你一个我自己的理解框架,帮你绕开概念混淆:
- Prompt 是一次性的:写在系统提示词里,每次对话都加载,适合放全局性的、每轮都必须遵守的规则。缺点是塞多了浪费 Token。
- Skills 是按需加载的:平时不占上下文,Agent 遇到对应任务时才把技能全文读进去。适合放领域性强、只在特定任务里需要的操作规范。
- MCP 是"做"的部分:提供能执行的工具和能力,比如搜索、读文件、调 API。Skills 是"怎么做才合格"的部分:提供做事的方法和标准。两者天然互补。
举个具体场景:MCP 给你接了一个文件系统工具(这是能力),但你的项目要求输出文件必须带版本号、必须按目录结构归档(这是规矩)。规矩就应该写进 Skill,而不是硬编码在 Agent 的 system prompt 里——因为规矩会变,系统提示词一变,全集群都受影响;Skill 变了,只有用到它的 Agent 下一轮任务才重新加载。
5.3 一个技能包的完整示例与复用方式
我建议你建一个内部的"技能市场":团队里谁总结出高效的方法,就整理成一个技能包提交上去,代码评审后发布。这个模式很像开源社区的 Cookbook 文化,但针对的是 Agent 的工作规范,沉淀速度非常快。
技能包之间还可以继承组合。我们团队有一个"基础调研技能包"专管资料来源筛选和三方数据交叉验证;上面再叠"垂直行业报告技能包",引用基础包的方法,再增加行业术语规范和竞品对比模板。组合式技能包最爽的地方是——你改基础包里"来源必须是一手数据"这条规则,所有上层派生技能全部生效,不用逐个改文件。这就是可扩展的甜头。
6. 研究助手集群实战:从架构到可跑的最小实现
6.1 场景与集群拓扑设计
理论讲完,我给你一个真正可以复刻的最小项目:搭一个"技术选型研究助手"集群。目标输入是"帮我做一份 XX 技术选型调研报告",输出是一份结构化的对比分析报告。
集群拓扑我设计成四个角色:
| 角色 | 职责 | 依赖的协议/能力 |
|---|---|---|
| Planner 规划器 | 拆分任务、派单、汇总 | DeepAgents 编排、A2A 下发任务 |
| ResearcherA 检索员 | 收集公开资料、搜索网页 | MCP 搜索工具、MCP 文档库读取 |
| ResearcherB 数据库查询员 | 查询内部知识库、结构化数据 | MCP 数据库工具、A2A 接收查询请求 |
| Writer 写作员 | 按报告规范输出成稿 | Skills 中的 report-writing 技能包 |
链路是:Planner 先通过 A2A 派单给 ResearcherA 和 ResearcherB(并行);两个研究员各自通过 MCP 调工具拿数据;产生的结构化结果通过 A2A 回传给 Planner;Planner 聚合后把写作任务派给 Writer;Writer 加载 report-writing 技能包,按照里面的规范组合内容,输出报告;最后加一层人工确认环节兜底。
6.2 关键代码与配置片段
核心编排逻辑用伪代码描述一下,你照着迁移到自己的代码里就行:
class AgentOrchestrator: def __init__(self): self.agents = load_agent_registry() # 从注册表加载所有角色的卡片 def run(self, user_goal: str): task_tree = self.planner.decompose(user_goal) # 拆解成 DAG 任务树 for task in task_tree.ready_tasks(): agent = self.select_agent(task.required_capability) a2a_task_id = self.send_a2a_task( agent_card_url=agent.card_url, task_payload=task ) while not self.is_finished(a2a_task_id): update = self.poll_or_stream(a2a_task_id) self.route(update) # 中间结果流转到聚合器 draft = self.writer.write(task_tree.collected_results) self.reviewer.check(draft) return draft研究员侧的 MCP 调用也很直接,核心就两行:
search_result = await mcp_client.call_tool("web_search", {"query": topic}) db_rows = await mcp_client.call_tool("query_knowledge_base", {"sql": sql})Abstraction 之后,覆盖不同数据源只是加 Server 的事。
6.3 一次任务调用的完整链路
跑通后的实际效果是:用户在对话里说"我想选一个开源的工作流引擎,比较一下 n8n 和自研方案的利弊"。Planner 把目标拆成三个子任务:资料收集(交给 ResearcherA)、内部访谈记录查询(交给 ResearcherB)、报告输出(交给 Writer)。
ResearcherA 通过 MCP 搜索到 7 篇有效资料,返回摘要;ResearcherB 通过 MCP 从内部知识库查到两条历史选型结论;两者结果都回到 Planner 的消息聚合区。Planner 把材料一起交给 Writer,Writer 根据技能包里的报告规范生成初稿,初稿只推到内部页面不直接发出去。从发出指令到拿到初稿,我实测大概 3 分钟,如果单 Agent 从头干,这活儿没有 20 分钟下不来,而且质量还飘忽不定。
7. 部署后你躲不开的三个大坑
7.1 上下文窗口被协议回填撑爆
这绝对是多智能体集群的第一个杀手。MCP 的 tools/list 返回几十个工具,每个工具的 JSON Schema 都很长;A2A 的历史消息来回同步;Skills 的全文又全都塞进去——几个来回下来,上下文窗口就被这些"框架开销"吃干净了,真正留给业务推理的容量所剩无几。
我自己的缓解方案有三板斧:第一,Skill 必须按需加载,不是全局常驻;第二,MCP 工具列表要分组裁剪,根据当前任务角色只加载它可能用到的工具子集;第三,A2A 传给下游 Agent 的只是聚合后的结果摘要,绝不让原始消息全量流动。记住一个原则:每一层只传"对方完成任务所必需的最小信息"。
7.2 并发控制与幂等设计
集群一跑起来,并发问题立刻暴露。多个 Agent 同时向同一个 MCP Server 发请求、同一个任务被重试发出两次、A2A 的 Task 状态被两个线程同时更新——这些问题在单体应用里根本不存在,在集群里每天都可能发生。
拥抱协议里的幂等思路是最快的解法:所有请求尽量带明确的请求 ID;A2A 的 Task ID 生成后不再改变,重复消息靠任务状态去重;MCP 调用要设置超时和重试语义,但重试前必须确认上一次请求没有副作用。如果再激进一点,把高频任务队列放到 Redis 之类的中间件里解耦,执行节点只管消费,队列消息的 ack 机制天然防重。
7.3 认证授权与技能包来源安全
多智能体集群的安全边界,比单应用复杂得多,因为入口点太多:MCP Server 是入口、A2A 的 Agent Card 是入口,甚至技能包的加载也是入口。尤其要警惕技能包里的提示词注入风险——一个被恶意构造的技能包,可以让 Agent 在不知不觉中执行危险指令。所以技能包必须有来源校验,最好只从受控仓库加载并做签名校验,外部下载的一律先审查再入库。
Agent Card 暴露的接口也要收着点:某个 Agent 只要做到"接受查询、返回结果",就别把它的执行类接口全部挂上去。A2A 的鉴权、MCP 接口的鉴权都要单独配,不要图省事统一个"内部网络"就完事——内部网络里的服务间调用一旦被绕过,后果谁也兜不住。
最后说点实在的。这四个词凑在一起,不是让你把所有最新的东西都堆进系统,而是给你一套组合框架:用 DeepAgents 管编排,用 MCP 管工具接入,用 A2A 管智能体协作,用 Skills 管能力沉淀。我自己的体会是,最先跑通最小闭环比什么都重要,哪怕你只有 Planner 加一个执行器,先把 MCP 和 A2A 的链路接通,再慢慢往集群里加角色,都比一开始就设计一个十四五个 Agent 的宏大架构靠谱得多。这套架构最可爱的特点就是:扩展是逐步发生的,能力是滚雪球积累的。