☰
DeepAgents+MCP+A2A+Skills:多智能体集群编排实战
2026/10/6 6:27:53 网站建设 项目流程

1. 为什么单一 Agent 撑不起"超级多智能体"这个目标

先讲一段我自己的真实经历。去年我在做一个内部知识处理系统,最初大家都很实在——用一个大模型接入一堆API,意图识别、工具调用、结果组装全塞到一个服务里。一开始demo演示效果很好,模型也确实能干很多事。但一旦把需求扩到多部门、多场景,问题立刻露出来了:一个Agent既要会写SQL,又要会调订单接口,还要懂前端展示规则,提示词越写越长,模型行为越来越飘,改一个场景的输出就会影响另一个场景的逻辑。

后来我尝试把不同职能拆成多个Agent,A负责数据查询,B负责分析,C负责生成报告。我以为把它们的API在代码里串一遍就行,结果是灾难——Agent之间完全不认识对方,输出格式各说各话,编排逻辑全硬编码在业务代码里,每加一个Agent就要改一轮主流程。那个阶段我强烈意识到,多智能体真正缺的不是"更多模型调用",而是一套约定好的互联协议和编排框架。

现在我比较认可的做法,就是题目里那套组合:DeepAgents(深度智能体)+ MCP(模型上下文协议)+ A2A(智能体间通信协议)+ Skills(可沉淀技能)。这四个词分别回答了一个问题:Agent本身怎么做深,Agent怎么接外部工具,Agent怎么和其他Agent说话,Agent的能力怎么复用到下一个场景。

这篇内容适合两类人:一类是正在做多Agent原型的开发者,另一类是已经在跑单Agent但被扩展性卡住、想升级集群架构的技术负责人。我尽量不把协议条文抄一遍,而是从"我到底是怎么把它们串起来"的角度来讲,包括踩过的坑。

1.1 先理清四个概念的分工,别在架构图里打架

我见过不少团队把MCP和A2A混着聊,一说Agent互联就说"走MCP啊"。这是最常见的第一误区。虽然这两个协议确实有配合,但它们解决的问题层次完全不同。

我的理解是这样的:如果把Agent集群比作一个公司。

  • MCP 解决的是人和工具的连接问题。员工(Agent)需要通过标准插头使用打印机、电脑、数据库(外部工具),MCP把"插座"统一了。之前每个设备要专线,现在一根USB-C全解决。
  • A2A 解决的是员工之间的协作问题。两个员工说话要用同一种语言、同一套公文格式、同一个送达地址。A2A管的是"人"之间的消息格式和路由。
  • Skills 解决的是经验沉淀问题。老员工把做PPT的流程、写代码的规范整理成标准作业手册,新员工拿到就能用。Skills就是给Agent的"作业手册包",不是临时写在prompt里的棉花絮。
  • DeepAgents 则是把这些载体装起来的行为体。它具备目标拆解、推理规划、自我反思和调用外部资源完成闭环的能力,而不是一个纯粹的"LLM API套壳"。

做个简单对照表可能更直观:

概念类比核心解决典型形态
MCP通用插座/数据线Agent与外部工具的连接标准化MCP Server暴露工具,MCP Client调用
A2A公司内部公文/协作协议Agent与Agent之间的发现、任务交接、状态同步Agent Card、Task、Message
Skills标准化作业手册Agent能力的沉淀、复用、组合指令模板+工具脚本+参数定义
DeepAgents一个会拆目标、会反思的执行主体单Agent的深度与自主性规划模块+执行模块+记忆模块+反思循环

在实际项目里,这四个并不是必选项的关系,更像一个横向栈:DeepAgents是执行主体,Skills给DeepAgents提供能力包,MCP给DeepAgents提供外部工具通路,A2A把这些DeepAgents串成一张网。

1.2 这套组合真正的价值:编排、互通、扩展

标题里三个关键词才是最终诉求:

  • 可编排:集群里Agent谁先谁后、结果怎么汇聚、异常怎么重试,要能被上层统一控制,而不是把逻辑散落在业务代码里。
  • 可互通:Agent之间能发现对方、调用对方、传递上下文。关键是建立一个通用的"语言"和"地址簿"。
  • 可扩展:加一个新能力时,不需要改老集群。新Agent写好Agent Card注册进来,其他Agent和编排层自动能看到它。

这套体系做到位,多Agent才能从"demo好玩"变成"生产可用"。下面对每层展开讲我实际的落地做法。

2. 集群设计的起点:先定拓扑,再谈协议

很多人上手先写协议配置,我反倒建议先画拓扑。拿张白纸,把最终要跑的Agent画出来,然后问自己:谁向谁发起任务?任务结果谁负责汇总?如果一个人Agent挂了,谁来接管?这几个问题不回答,后面写A2A也罢、MCP也罢,都会像无头苍蝇。

2.1 三种编排模式该怎么选

我试过三种:链式(Pipeline)、主控-执行(Orchestrator-Worker)、网格(Mesh)。

链式最简单,A做完交给B,B做完交给C,适合流水线固定的场景,比如"抓取-清洗-入库"。但链式有个硬伤:中间断了,整个流程得重来,而且环节越多越难定位。

网格最自由,Agent之间谁都能找谁,适合探索性任务,但自由意味着不可控:A和B互相等、C调了D的结果但没人通知E,排错排到怀疑人生。

我生产环境里最常用的是主控-执行模式。一个主控Agent(Orchestrator)负责拆目标、派任务、收结果,下面挂多个专业Worker。这样编排逻辑收敛在单个主控里,Worker只认任务和输出格式,耦合最小,也方便后续横向加Worker。

2.2 主控-执行模式下的双层架构

我落地时把系统分成两层:

  • 编排层:只做目标拆解、任务分发、结果合并、异常重试。它不直接碰业务工具的API,只需要知道每个Worker在Agent Card里声明了什么能力。
  • 执行层:每个Worker是一个DeepAgent实例,有自己的记忆、推理循环和工具集。它们通过MCP接外部系统,通过A2A向上回传任务状态和结果。

这么设计之后有个直观好处:主控和Worker都变"蠢"了。主控不需要理解SQL怎么写、订单怎么查,只要知道"name: data_queryer,capabilities: sql_query, data_clean"就能派活。Worker不需要关心整个流程怎么编排,只负责把手头的任务做好。

2.3 Agent注册与能力路由:集群的地基

拓扑画完之后,第一件要落地的事情就是地址簿。我把这一步当作集群的"地基工程",包括三块:

  1. Agent能够被发现:唯一的Agent ID + 可访问的endpoint + 元数据描述,注册到Registry。
  2. 能力能被查询:Registry记录每个Agent拥有的Skills和暴露的工具能力,上层通过关键词或标签检索。
  3. 任务能被路由:主控根据任务描述找匹配的Worker,而不是硬编码"task_type A -> worker B"。

在实现上我分为了静态配置和动态发现两种。静态简单,挂在yaml里;动态靠A2A协议的Agent Card做服务自描述。下面章节会细讲。

3. MCP:把 Agent 与外部工具之间的"插座"标准统一起来

MCP(Model Context Protocol)在现在的Agent生态里几乎已经是事实标准。无论哪个框架的Agent,只要说"我要接外部工具",大概率都会看MCP有没有现成Server。我最初对它的态度是将信将疑:不就是JSON格式的API规范吗?直到我连续接了三五个不同系统的API后,才发现它最大的价值不是传输格式,而是把工具的接入方式从"代码直连"变成了"配置即插即用"。

3.1 MCP 的三层架构与传统工具调用的本质区别

一个MCP体系由三部分组成:

  • MCP Host(宿主):比如Claude Desktop、自研Agent进程,它是发起方。
  • MCP Client:在Host内部,负责与Server建立连接、请求工具调用。
  • MCP Server:一个独立进程或服务,负责把具体工具能力封装成标准接口,并按协议描述出来。

关键点在于:Server暴露的不是"一个HTTP接口",而是一份能力清单(工具定义、参数schema、说明),Client只根据这份清单动态决定何时调用、传什么参数。

对比传统方式,假设我要让Agent能查订单。传统做法是我写个queryOrder(orderId)函数,塞进Agent的工具列表。换一个系统,再写一遍。接入方式千奇百怪,有的走REST,有的走Python SDK,有的只给数据库账号。MCP的做法是:写一个order_server,对外声明"我有query_order工具,参数是order_id: string"。任何MCP Client连上来都能在运行时看到这个工具,不需要预编译。

这让我想起早年USB接口统一各种设备充电口的场景。之前每个设备一根线,现在一个口全解决。MCP就是Agent世界的USB-C。

3.2 自建一个最小的 MCP Server

我本地搭过很多次MCP Server,这里贴一个最小可运行的例子,用官方的Python SDK。首先安装依赖:

pip install mcp

然后写一个Server,暴露一个简单的计算器工具:

# calculator_server.py from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent app = Server("calculator") @app.list_tools() async def list_tools(): return [ Tool( name="add", description="Add two numbers", inputSchema={ "type": "object", "properties": { "a": {"type": "number"}, "b": {"type": "number"} }, "required": ["a", "b"] } ) ] @app.call_tool() async def call_tool(name: str, arguments: dict): if name == "add": result = arguments["a"] + arguments["b"] return [TextContent(type="text", text=str(result))] raise ValueError(f"Unknown tool: {name}") async def main(): async with stdio_server() as (read_stream, write_stream): await app.run(read_stream, write_stream, app.create_initialization_options()) if __name__ == "__main__": import asyncio asyncio.run(main())

这个Server可以通过标准输入输出(stdio)被Client拉起。在Agent进程里,配置一行指向它:

{ "mcpServers": { "calculator": { "command": "python", "args": ["calculator_server.py"] } } }

从连接建立开始,Client端就能自动拿到add工具的描述和参数定义,Agent在对话中需要算数时就会以结构化JSON发起调用。整个过程没有二次hardcode。

3.3 多 Agent 共享 MCP 时的连接治理

单Agent接MCP很简单,集群里就要认真治理。我在集群里跑十几个Worker,每个Worker都各自起进程去连接同一批MCP Server,结果资源消耗和连接数直接爆掉。后来改成共享连接池:MCP Server作为常驻服务,Agent侧复用连接句柄,而不是每个任务启动一个子进程。

另一个坑是权限隔离。如果所有Agent都能调用同一个MCP Server上的全部工具,"查余额"和"转账"就是同一个tool,权限边界直接崩了。我现在的方案是:MCP Server按Agent角色设置scope,每个Worker在接入时声明需要的工具子集。这一步不能省,尤其在生产环境。

4. A2A:让分身之间真正对话和交接任务

如果说MCP解决了"Agent与工具的连接",A2A(Agent-to-Agent)解决的就是"Agent与Agent的协作"。我在第一期实践时最大的痛点也在这:两个Agent明明都是LLM,却无法自然对话。

4.1 Agent Card:集群的地址簿与能力说明书

A2A协议里第一个要暴露的组件是Agent Card。它是一份JSON文档,描述了这个Agent的身份标识、能力范围、支持的认证方式和endpoint地址。

下面是一份简化的Agent Card:

{ "name": "data-analyst", "description": "负责数据查询、清洗、聚合分析的专业分析Agent", "url": "http://agent-cluster.internal/data-analyst", "skills": [ { "id": "sql_runner", "name": "SQL Runner", "description": "连接数仓执行只读SQL查询并返回表格结果" }, { "id": "data_visualizer", "name": "Data Visualizer", "description": "将结构化数据转为图表配置JSON" } ], "capabilities": { "streaming": true, "push_notifications": false }, "security": { "auth_type": "mTLS" } }

在主控选Worker时,实际就是在Registry里扫这些Card,然后按能力清单匹配。A2A的Agent Card解决了"我凭什么信任这个Agent能干这活"的问题有了标准答案。

4.2 A2A 的 Task 生命周期:一次协作的实际流转

拿一个典型的查询任务举例。主控收到用户请求"统计上月各品类销售额",它把请求拆成两个Task:Task A分配给>skills/ sql-analyst/ SKILL.md # 流程指引、思维链路、示例 scripts/ run_query.py # 实际执行脚本,封装底层MCP调用 validate.py # 输出校验收 schemas/ input_schema.json examples/ demo_query.json

SKILL.md是核心,写的是步骤化指导。比如一个"数仓取数"的Skill,它的SKILL.md大致长这样:先提取用户筛选条件,然后校验表名校验权限,再调用run_query.py执行只读SQL,最后把结果按标准格式返回。这比在Agent的system prompt里写一大堆"你要善于使用数据库"要靠谱得多,因为每个步骤都对应具体动作。

5.2 从任务拆解到 Skill 注册:一个实战示例

我第一次做Skill遇到的最大困惑是:怎么判断什么适合沉淀成Skill?后来总结出一个经验:凡是同一类任务,我做过三次以上,就应该写Skill。因为三次意味着逻辑稳定,值得固化。

举个例子,我让Agent定期生成周报。最初我是在prompt里描述"请根据本周围绕XX框架生成周报",但每次生成的格式都不一样,老板不满意。后来我做了weekly-report-generator这个Skill包:

  • SKILL.md里规定了周报必须包含5个板块(本周进展、风险、下周计划、资源需求、数据附录)
  • scripts里定义了从MCP接入的周数据拉取工具
  • schemas里定义了每板块的JSON输出格式

注册这个Skill之后,Agent每次生成周报都遵循同一模板,输出结构稳定、可被下游程序解析。这才是Skills真正的价值:把经验变成规范,把规范变成可执行包,可复用给所有有权限的Agent。

5.3 Skill 的版本管理与权限控制

Skill本身的版本管理很重要。我经历过一次惨痛的教训:一个数据分析Agent同时被两个项目复用,项目A要求用新版取数口径,项目B还在用老口径。因为Skill包没有版本隔离,一次更新导致项目B的数据全错了。

现在的做法是:Registry里给每个Skill带上版本号,Agent在接入时显式声明要哪个版本。比如sql_runner@2.1.0。同时配置变更走"灰度"——先让测试Agent加载新版本跑一轮,确认没问题再放开给生产Agent。

权限方面,Skill包要跟随Agent的角色做访问控制。举个例子:不是所有Agent都应该能加载"转账执行"这个Skill,只有支付域Agent可以。这一点是安全底线,不能省。

6. 从头搭建一个可编排、可互通、可扩展的 Agent 集群

前面把概念说明白了,接下来给出一套我现在用得比较顺的落地路径,照着做可以快速拿到一个能跑的多Agent集群。

6.1 技术选型与项目骨架

我用的是Python技术栈,核心组件如下:

  • DeepAgents运行时:基于LangGraph构建Worker内部的状态机(支持规划、执行、反思的循环)
  • MCP SDK:官方Python SDK,跑MCP Server
  • A2A实现:暂用较简单的自建消息中心模拟A2A的Task管理,如果想要更省事也有官方参考实现可供接入
  • Registry:用Redis存Agent信息和Skill元数据,TTL设短一点,方便动态上下线
  • API网关:FastAPI做编排层入口

目录骨架示意:

agent-cluster/ orchestrator/ main.py task_queue.py agent_registry.py workers/ data_analyst/ agent.py report_writer/ agent.py skills/ sql_runner/ weekly_report/ mcp_servers/ database_server/ api_server/ config/ cluster.yaml

6.2 配置编排层与注册表(关键代码)

cluster.yaml的核心配置大概长这样:

cluster: registry: type: redis addr: localhost:6379 orchestrator: max_concurrent_tasks: 16 default_timeout_seconds: 120 workers: - id: data_analyst endpoint: http://localhost:8101 skills: [sql_runner@2.1.0, data_visualizer@1.3.0] mcp_servers: [database_server, visualization_server] auth: token-xxx - id: report_writer endpoint: http://localhost:8102 skills: [weekly_report@1.0.0] mcp_servers: [doc_server] auth: token-yyy

在编排层,主控在收到任务后做三件事:

  1. 拆解子任务(可以用LLM做一个planner,也能用规则)
  2. 在Redis里按remap tag找到能干的Worker
  3. 通过A2A风格的Message把任务发出去,监听Task状态回传

我在实现时给task定义了统一结构,保证主控不用关心某个Worker内部用的什么模型:

@dataclass class AgentTask: task_id: str target_agent: str skill_id: str payload: dict status: str # submitted / working / completed / failed result: dict | None

任务提交后,主控持续拉取Task状态,直到completed或failed。超时的任务会进入重试队列,最多重试两次,然后转人工。

6.3 验证集群跑通的 Checklist

一个集群搭完后,不要急着上生产,先跑完我的这份验证清单:

  • [ ] 所有Worker的Agent Card都能在Registry里查到
  • [ ] 每个Worker能通过MCP调用它声明过的工具;未声明的工具应被拒绝
  • [ ] 主控能按描述找到正确Worker并派发任务;派错解释得清除原因
  • [ ] 一个Worker异常失败后,主控能感知并触发重试或降级
  • [ ] 新增一个Worker后,不改动编排层代码即可被发现并调度
  • [ ] 端到端延迟和token消耗在可接受范围

前三条基本是"能跑",第四条和第五条才是"可编排、可扩展"的实锤。我见过不少demo集群倒在后两条上。

7. 从测试到上线:我遇到的高频问题与处理方法

最后把实战里踩过的几个高频坑记录在这里,这些在官方文档里基本不会写。

7.1 并发和超时:Agent再聪明,也抵抗不了系统瓶颈

多Agent集群本质上是并发密集系统。我最初把每个Worker的MCP连接都做成同步阻塞,导致一个慢查询把整条流程拖住。后来改成异步Client + 超时控制,主控侧也设置了任务级超时和重试。建议每个环节都设置超时,包括模型推理环节,因为LLM的p95延迟可能远超平均值。

一个具体参数参考值:单次工具调用超时30秒,单Agent任务超时2分钟,整条链路上限5分钟。如果你的场景需要更长,就拆成更多异步子任务而不是拉长同步等待。

7.2 安全与权限边界:工具暴露越多,事故面越大

MCP Server一旦上线就是集群的公共入口。我经历过一次安全事故排查:某个Server把所有工具都暴露出去,其中一个写操作被另一个Agent误调用,差点把测试数据清了。从那以后,我在MCP Server侧做两件事:一是按Agent身份做scope隔离,二是对所有写操作增加二次确认机制。A2A侧也要注意:不要信任任何内部Agent的输入,校验skill_id和token不能省。

7.3 可观测性:多Agent链路日志怎么追

排错时最大的问题是"消息到底卡在哪个Agent"?我一开始每个Agent只打自己的日志,出了问题要挨个查。后来引入统一的trace_id,从主控接收用户请求开始生成,通过A2A消息头和MCP工具调用上下文一路透传。所有日志按trace_id聚合,一个请求从进集群到出集群的全链路一目了然。这一步强烈建议早期就做,后期补太痛苦。

7.4 别让测试Agent和线上Agent共用一套技能

这是我曾经踩过最难受的坑。测试环境里改了一个Skill的细节,结果线上同名的Agent行为直接变了。现在我的Registry强制区分环境,测试环境名打上dev-前缀,线上的Worker只能加载线上的版本。

8. 最后分享一点我的使用体会

这套DeepAgents+MCP+A2A+Skills的架构目前已经稳定跑在我几个内部项目里。回头看,最值得投入精细化打磨的并不是某个协议的高阶特性,而是Agent Card里写的描述是否足够准确。很多问题看起来是"路由错了""Agent犯了蠢",根子上其实是能力描述写得模糊,让主控没法判断下发任务给谁。

另外一个体会是:不要一开始就追求全自动。集群可以先从编排层硬编码路由跑起来,让业务先通,再逐步把路由决策交给LLM做动态规划。稳扎稳打才是多Agent系统能上生产的正确姿势。希望这篇内容能帮你少走几周弯路,也欢迎有不同实践思路的朋友多交流。

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

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

立即咨询