ARTICLE DETAIL

资讯详情

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

DeepAgents+MCP+A2A+Skills:多智能体集群搭建实战复盘

DeepAgents+MCP+A2A+Skills:多智能体集群搭建实战复盘 前两天我把一个叫DeepAgents MCP A2A Skills 超级多智能体的课程项目从头到尾啃了一遍还顺手把它从 demo 改造成了一套能接真实业务的 Agent 集群。这套组合之所以值得花时间研究是因为它几乎把当下多智能体领域最重要的四块拼图凑齐了MCP 统一工具接入A2A 统一智能体之间的通信Skills 统一能力沉淀DeepAgents 负责把这一切编排成可调度的整体。这篇文章就是完整复盘覆盖架构选型、协议细节、代码实现、排坑实录目标是让看完的人能自己搭一套多智能体集群。适合三类人刚接触 Agent 开发想找路线的已经用单个 Agent 但觉得它搞不定复杂任务的以及在团队里推 Agent 基建但不知道怎么下手的技术负责人。1. 为什么单 Agent 不够用集群化才是出路1.1 单 Agent 的上下文墙与职责混乱单个 Agent 的本质是大模型 工具 记忆 循环。让它查天气、写周报、算个税体验都还不错。可一旦任务变成从二十个数据源里抽数据、交叉验证、生成报告、再按角色分发问题立刻暴露上下文被撑爆工具调用链越拉越长中间任何一步出错都要从头排查。真正的问题不是模型能力不够而是所有职责堆在一个循环里。让一个人同时当采购、会计、销售总监流程一复杂必乱。Agent 也一样——上下文窗口是稀缺资源塞进去的历史越多模型注意力越分散关键信息反而容易被淹没。更现实的是成本长上下文的 token 消耗是按次计费的单 Agent 硬扛复杂任务费用增长几乎是线性的。1.2 拆是核心不是多多智能体的核心不是把一堆 Agent 堆在一起而是拆。把大任务拆成子任务子任务按专长分配给不同 Agent编排者负责合并结果。拆得好每个 Agent 的上下文都干净工具职责清晰出错能定位到具体环节重跑的成本也低。但拆的前提是标准化能力。工具接入要标准否则每个 Agent 各写各的连接器Agent 之间通信要标准否则互相调 API 变成蜘蛛网经验沉淀要标准否则换个模型所有调优白费。这就是标题里四件套的由来MCP 管工具A2A 管互通Skills 管沉淀DeepAgents 管编排。四者缺一个集群就会退化成一堆脚本互相调接口比单 Agent 更乱。2. MCP、A2A、Skills、DeepAgents 各管哪一段2.1 MCP 管用手把工具接入变成标准接口MCPModel Context Protocol由 Anthropic 开源解决的是模型连接外部工具和数据源难的问题。拿生活类比以前每个 AI 应用想接数据库、接浏览器、接内部 API都得单独写适配器就像每个设备配一种充电线。MCP 相当于把充电口统一成 USB-C服务端暴露标准接口客户端统一消费。需要强调一点MCP 是软件协议不是硬件协议理解成 HTTP 那种应用层协议更准确。它定义了三种角色Host宿主应用比如 IDE 插件或 Agent 运行时、Client负责与 Server 建立会话、Server暴露工具、资源、提示词。传输层有两种本地用 stdio远程用 Streamable HTTP。在集群架构里MCP 就是 Agent 的手。我实际测试下来的体感是这个协议最大的价值不是技术多深而是生态。以前接一个内部系统要写一整条链路现在对方只要提供一个 MCP Server所有 Agent 都能直接用。国内不少后台管理框架把 MCP 能力合并进主线也印证了这个趋势——它正在从 AI 圈往传统软件圈渗透。2.2 A2A 管交棒Agent 之间说同一种语言A2AAgent2Agent是 Google 在 2025 年推出的开源协议和 MCP 正好互补。MCP 解决 Agent 连工具A2A 解决 Agent 连 Agent。它基于 JSON-RPC 2.0 和 HTTP几个核心概念需要先记住AgentCard一个 JSON 文件描述自己是谁、能干什么、怎么连接。相当于 Agent 的名片。Task任务的状态机包括 submitted、working、input-required、completed、failed 等状态。MessageAgent 之间传递的具体内容。Artifact任务产生的结构化产物比如文件、表格、代码片段。一个 Agent 拿到对方的 AgentCard就知道它能不能接这个活然后发 Task 过去通过轮询或回调拿结果。简单讲MCP 让 Agent 长了手A2A 让 Agent 有了互相交接工作的规矩。我刚开始学的时候总把两者搞混后来用一句话记住了MCP 是 Agent 和工具之间的语言A2A 是 Agent 和 Agent 之间的语言。2.3 Skills 管经验把会做的事打包成可复用单元Skills 这个概念各家实现略有差异但本质一致把一组指令、模板、脚本、校验规则打包成一个目录让模型按需加载。最典型的是 Anthropic 提出的 SKILL.md 规范——一个文件夹就是一个 Skill里面用 Markdown 描述能力、适用场景、操作步骤模型读到后知道什么时候该调用它怎么调用它。实际项目里我会把周报生成代码审查SQL 优化竞品信息抽取这类高频动作做成 Skills让多个 Agent 共享。Skills 的价值在于把隐性经验显性化老员工怎么写的周报、团队代码审查关注哪些点都可以被固化下来。它是 Agent 的肌肉记忆也是团队知识沉淀的载体。值得一提的是市面上已经出现不少现成 Skills 市场比如 Claude 官方市场、社区维护的 skills 仓库甚至有人把特定行业方法论也打成了 Skill。后面实操部分我会演示一个完整的 Skill 包长什么样。2.4 DeepAgents 管编排集群的调度中枢DeepAgents 在这里不是一个特定开源项目的名字而是一类深度智能体编排思路的代号。它的职责是拆解目标、派发任务、收集结果、校验质量、异常重试。一句话总结四者关系MCP 让 Agent 聪明地用手A2A 让 Agent 互相交棒Skills 让 Agent 记住怎么把事做好DeepAgents 决定谁在什么时候做什么。3. 集群架构怎么设计才扛得住真实业务3.1 三层角色划分我搭的这套集群采用经典三层结构每一层职责单一方便独立扩容协调层DeepAgents 编排器。负责接收用户目标、拆分子任务、调度执行 Agent、汇总校验。这是整个集群唯一能看到全局的地方。执行层多个专业 Agent。每个 Agent 只负责一个领域比如订单 Agent、售后 Agent、内容生成 Agent。它们之间不直接通信只和协调层通信。资源层MCP Server 群和 Skills 库。MCP Server 提供可调用的工具和数据源Skills 库提供可复用的操作流程。这种分层最大的好处是任何一个执行 Agent 挂了协调层可以直接把任务重新派给同类的另一个实例任何一个 MCP Server 出问题只影响依赖它的 Agent不会拖垮整个集群。3.2 编排模式怎么选多 Agent 的编排模式大致有四种各有适用场景Pipeline流水线适合有固定顺序的流程比如抽取数据 → 清洗 → 分析 → 生成报告前一个 Agent 的输出是后一个的输入。Map-Reduce并行汇总适合大量独立子任务比如让十个 Agent 分别分析十个竞品再统一汇总。Supervisor主管模式一个老板管多个下属老板负责拆解和验收下属只干活。这是最常用的模式。Debate辩论模式多个 Agent 从不同角度审视同一个问题适合需要交叉验证的决策场景比如风险评估。我的经验是真实业务很少只用一种模式。订单售后这个场景我用的就是 Supervisor 为主、Pipeline 为辅——编排器先把任务拆成订单查询和售后判断两条线售后判断那条线内部再走两步流水线。建议新手先从 Supervisor 模式起步因为它最符合人对项目经理的理解。3.3 通信拓扑与部署边界Agent 之间的通信拓扑一定要用 Hub-Spoke 模式而不是全连接。全连接看起来灵活但每个 Agent 都要维护对所有人的连接配置排查问题的时候谁都在跟谁说话根本定位不了。Hub-Spoke 下所有 A2A 流量都经过协调层日志集中问题链路清晰。部署边界有几个细节值得注意。MCP Server 尽量独立进程部署别跟 Agent 塞在同一个进程里否则一个工具崩溃可能带着 Agent 一起挂。Skills 仓库用统一版本管理每次更新走发布流程避免不同 Agent 用了不同版本的操作流程。所有 Agent 的地址配置放在一个注册中心或者配置中心里不要硬编码。4. 实操搭一个能跑的三 Agent 集群4.1 环境准备与技术选型我的技术栈选用 Python 3.11 uv FastAPI核心依赖是 mcp 和 a2a-sdk。uv init agent-cluster uv add mcp[cli] a2a-sdk fastapi uvicorn httpx选 Python 没什么悬念MCP 和 A2A 的官方 SDK 生态最成熟的就在 Python。FastAPI 用来承载 A2A 的 HTTP 端点。4.2 写一个完整的 Skills 包我先写一个订单状态速查Skill。目录结构如下skills/order_skill/ ├── SKILL.md ├── scripts/ │ └── check_order.py └── templates/ └── summary.mdSKILL.md 是核心它告诉模型这个 Skill 是干什么的、什么时候用、怎么用--- name: order_status_check description: 快速查询订单状态并生成用户可读的摘要。当用户询问我的订单到哪了发货没时使用。 when_to_use: 订单查询、物流状态、售后入口判断 --- # 订单状态速查 ## 使用步骤 1. 调用 MCP 工具 query_order 获取原始订单数据。 2. 根据 status 字段映射为用户可读文案 - PENDING → 待支付 - SHIPPED → 已发货 - DELIVERED → 已签收 - REFUNDED → 已退款 3. 使用 templates/summary.md 中的格式生成回复。关键点在于when_to_use字段。模型靠它判断什么时候加载这个 Skill写得太泛模型会误用写得太窄又容易被忽略。我踩过的坑是刚开始只写了 description没有写反例结果模型在用户问退款政策的时候也去加载订单查询 Skill白费上下文。4.3 用 MCP Server 暴露工具接下来写一个订单服务的 MCP Server。这里用的是 FastMCP 这个高层封装写起来非常快from mcp.server.fastmcp import FastMCP mcp FastMCP(order-service) mcp.tool() def query_order(order_id: str) - dict: 按订单号查询订单状态与金额。 Args: order_id: 订单号格式如 ORD-2025-0001 # 实际项目中这里替换为数据库或内部 API 调用 return { order_id: order_id, status: SHIPPED, amount: 299.00, tracking_no: SF1234567890, } if __name__ __main__: mcp.run(transportstdio)然后把它注册到 Agent 的配置里。我在 Agent 用的配置文件中加入{ mcpServers: { order-service: { command: python, args: [services/order_mcp_server.py] } } }这里解释一个很多新手会问的点MCP 工具函数的 docstring 不是给人看的注释是给模型看的说明书。模型的工具选择依赖函数名和 docstring 的语义匹配写得好不好直接影响工具调用准确率。我在测试中发现把参数格式和示例写进 docstring 后工具调用成功率大概提升了三成。4.4 用 A2A 把 Agent 暴露成服务现在做一个订单 Agent通过 A2A 协议暴露能力。核心是两件事提供 AgentCard处理 Task。AgentCard 是一个 JSON 文件相当于名片{ name: order-agent, description: 负责订单状态查询与售后前置判断可并行处理多个查询请求。, url: http://localhost:8001/a2a, skills: [order_status_check, refund_check], capabilities: { streaming: false, pushNotifications: false } }服务端处理 Task 的简化代码from a2a.sdk import A2AClient, A2AServer from a2a.types import Task, Message, TaskStatus def handle_task(task: Task) - Task: # 从消息里提取用户问题 user_text task.messages[-1].content # 这里会触发模型调用模型根据 Skills 决定是否调用 MCP 工具 result run_agent_with_skills(user_text) task.status TaskStatus.COMPLETED task.artifacts [{type: text, content: result}] return task server A2AServer( agent_cardload_agent_card(), handle_taskhandle_task, ) server.run(host0.0.0.0, port8001)A2A 的好处在这一步体现出来协调层不需要知道 order-agent 内部是怎么实现的它只需要读 AgentCard发 Task收结果。Agent 内部用的什么模型、什么 Skills完全透明。4.5 编排器调度逻辑最后是 DeepAgents 编排器。它要做的核心事情是三步拆解、派发、汇总。我用一个大模型做拆解用 A2A Client 做派发再做一次汇总校验import asyncio from a2a.sdk import A2AClient AGENTS { order: A2AClient(http://localhost:8001/a2a), refund: A2AClient(http://localhost:8002/a2a), } async def run(user_request: str): # 1. 拆解让编排模型输出子任务清单 plan coordinator_llm.decompose(user_request) # plan 示例: [{target: order, query: 查询订单 ORD-2025-0001}, ...] # 2. 并行派发 async def dispatch(item): client AGENTS[item[target]] return await client.send_task(item[query]) results await asyncio.gather(*[dispatch(item) for item in plan]) # 3. 汇总让编排模型合并结果并校验完整性 final_answer coordinator_llm.merge(plan, results) return final_answer这段代码是整个集群的中枢。实际项目里还要加超时控制、重试、结果校验比如让另一个 Agent 检查报告里有没有遗漏数据但这些是加固项核心骨架就是拆解、派发、汇总这三板斧。5. 常见问题与排查技巧实录5.1 问题速查表把我在实操中遇到的高频问题整理成了下表基本覆盖了集群搭建初期 90% 的坑现象排查思路解决方案MCP 工具列表为空先看 Server 进程是否存活再看 client 是否连上用mcp dev单独调试 Server确认工具注册成功后再接 AgentA2A 握手失败抓 HTTP 请求看 AgentCard 能不能正常返回检查 AgentCard 的url是否可达确认端口和路径一致Skills 不生效看模型有没有读到 SKILL.md 的when_to_use在 prompt 里显式声明可用 Skills 清单检查目录命名是否被忽略并发请求一多就超时看下游 MCP Server 和 Agent 的并发上限给编排器加信号量限流给 A2A 请求加超时与指数退避重试上下文越调越长看是不是把历史全塞进上下文用 Message 摘要代替完整历史只保留关键产物 ArtifactAgent 进入死循环看日志里重复执行同一工具设最大调用次数上限循环超过阈值就返回 failed5.2 几个值得单独说的坑第一个坑是 MCP Server 的并发隔离。刚开始我把所有 MCP Server 都串在一个进程里结果一个工具阻塞所有 Agent 都卡住。后来改成一个 MCP Server 一个进程 独立连接池情况立刻好转。工具类 MCP 和自动化类 MCP 要分开部署前者要求低延迟后者允许长任务混在一起互相拖累。第二个坑是幂等设计。A2A 的 Task 重试机制会带来重复执行问题。比如订单查询是幂等的没问题但生成退款单这种写操作如果被重试两次就会产生两笔退款单。我的做法是给每个 Task 加 request ID在 Agent 内部做去重同一个 ID 的重复请求直接返回上一次的结果。第三个坑是关于 Skills 和模型的适配问题。不同模型对 SKILL.md 格式的敏感度不一样有的模型能自动遵循有的模型需要你显式把 Skills 列表写进系统提示词里。别指望协议一接就万事大吉实测调整 prompt 结构能解决大部分模型不听话的问题。另外注意不同客户端对 Skills 的实现有差异跨环境迁移时先做好兼容验证。6. 个人经验与后续扩展这套集群从搭起来到现在跑了两个多月我最深的体会是多智能体的复杂度不在单个组件而在组件之间的接口约定。MCP、A2A、Skills 之所以重要不是因为它们多先进而是它们把接口这件事提前标准化了。你在设计阶段省下的每一次联调都是后期运维阶段的救命稻草。给想上手的人三个建议。第一先小后大别一上来就搞十个 Agent先用一个协调者加两个执行者跑通一个端到端场景再逐步加角色。第二日志先行把协调层的拆解结果、派发记录、汇总结果都结构化落盘出了问题能按 Task ID 回溯全链路这比任何调试工具都管用。第三把 Skills 当产品维护定期根据真实使用反馈修订 SKILL.md 的描述和步骤好的 Skills 库是整个集群最有价值的资产。这套架构后续还可以往几个方向扩展给协调层加记忆能力让它记住用户偏好把 MCP Server 接进消息队列让 Agent 能处理异步任务或者给 Skills 库加评分机制让集群自己淘汰不好用的 Skill。多智能体的路还很长但先把协议层做扎实后面怎么长都不会歪。
返回列表