☰
多智能体系统实战:DeepAgents+MCP+A2A+Skills全解析
2026/10/31 16:12:52 网站建设 项目流程

这两年做 AI 应用,最让人头疼的往往不是模型能力不够,而是单 Agent 越用越不可控。所以当我在慕课平台上看到"DeepAgents+MCP+A2A+Skills 超级多智能体"这个项目标题时,第一反应就是:这正是我一直在琢磨的东西。整个项目拆开看,本质就一句话——用 DeepAgents 打造单个 Agent 的深度能力,用 MCP 统一工具接入,用 A2A 打通 Agent 之间的协作,再用 Skills 让能力像积木一样可复用,最终形成一个可编排、可互通、可扩展的 Agent 集群。

这个项目适合两类人:一类是正在做 Agent 应用、被多工具集成和 Agent 间协作搞到头大的开发者;另一类是天天刷到 MCP、A2A、Skills 这些热词,想知道它们到底怎么落地的技术爱好者。下面我会把课程项目的设计思路、每个协议层面的实现要点、以及我实际跑通过程中踩过的坑都整理出来,尽量做到照着能复现。

1. 为什么要拆成多智能体,而不是堆一个更大的单体 Agent

1.1 单体 Agent 的天花板

很多人一开始的想法很朴素:一个 Agent 什么都能干不就行了?给它接上搜索引擎、数据库、代码执行器、文档工具,它就能包办一切。这个思路在 demo 阶段确实爽,但一旦进入真实业务场景,问题会接二连三冒出来。

首先是上下文污染。一个 Agent 的所有工具调用、中间思考、历史记录全挤在同一个上下文窗口里。它查了十次资料、调了三轮代码,前面的内容还在占着位置。结果是模型越长越"健忘",明明早期对话里有明确指令,到后面就开始自作主张。业内管这个叫"lost in the middle",模型对长上下文中部内容的关注度会显著下降。

其次是权限放大的风险。单体 Agent 为了干活,往往被赋予高权限的工具,数据库写权限、文件系统权限、外部 API 调用权限全挂在同一个身份下。一旦它的某次规划出现偏差,破坏面是整体性的。我见过一个做报表的单体 Agent 因为工具描述写得含糊,把测试库当成生产库执行了更新——这种事故在多人多职责的架构里其实更容易被拦住。

最后是迭代成本。你想给"资料检索"这个能力升级,却要动整个 Agent 的提示词和工具链,因为你没法保证改动只影响检索环节。改完一轮,以前调通的代码生成能力可能又崩了。本质上,单体 Agent 把"高内聚、低耦合"这个软件工程的基本盘给丢掉了。

1.2 多智能体打开了什么新空间

拆成多个 Agent 之后,很多问题会自然消失:研究型 Agent 只负责收集和整理资料,写作型 Agent 只负责产出文案,审核型 Agent 只负责质检。每个 Agent 的上下文窗口里只有自己那一亩三分地的信息,污染面被控制住了。权限也能按节点最小化,研究 Agent 拿不到数据库写权限,发布 Agent 只接触发布接口。

另一方面,多智能体带来了并行和容错。一个串行执行的调研任务,拆成"市场情报、竞品分析、用户评论"三个 Agent 并行跑,整体耗时能压到原来的三分之一。某个 Agent 挂了,其他节点照常工作;你只需要让编排层把失败节点重新调度就好。这种冗余能力在单体架构里是完全没有的。

多智能体还有一个不太容易被注意到的收益:使命边界清晰。每个 Agent 的提示词可以写得更精确,因为它的职责范围就是那一小段逻辑。我实测下来,拆细之后的单 Agent 任务成功率高了不少,因为提示词里不用再塞"如果遇到××情况请绕道处理"这类模糊兜底条款了。

1.3 四个关键词的分工定位

第一次看到"DeepAgents+MCP+A2A+Skills"这个组合,很容易被术语绕晕。我用自己的理解给它们排了个序:

组件一句话定位解决的问题
DeepAgents单个 Agent 的"内功"深度推理、多步规划、自我纠错
MCP工具侧的"标准插口"Agent 与外部工具、数据源的统一接入
A2AAgent 之间的"通用语言"跨节点、跨厂商的相互发现与协作
Skills能力的"标准化积木"让特定技能可打包、可分发、可复用

打个比方:DeepAgents 决定的是这个"员工"聪不聪明,MCP 决定的是他能不能熟练使用各种工具,A2A 解决的是员工之间怎么开会对齐,Skills 则是他随身带的专业技能包。四者分工明确,互不越界。明白了这层关系,后面所有设计都顺理成章。

2. DeepAgents:先把每个节点做到"有主见"

2.1 深度推理不是"多问几句"

DeepAgents 这个说法并不是某个官方框架名称,而是一类设计范式的统称。它强调的是 Agent 不能只会"一问一答",而要有完整的感知-规划-行动-反思闭环。

常见的实现路径是 ReAct 循环:模型先观察当前状态,然后思考下一步该做什么,再决定调用哪个工具,拿到工具结果后重新观察,如此往复。在此基础上,稍微进阶一点的做法是引入 plan-and-execute:先让模型在任务开始时输出一份完整的执行计划,把大目标拆成多个小步骤,然后逐步执行。这个模式配合"进度检查点",能明显减少 Agent 在一半时跑偏的概率。

我在课程项目里还加了 reflection 环节,也就是让 Agent 在执行完一轮之后,自己审视一下"我这个结果真的满足最初的需求吗"。这一步看着费 token,实际上非常值。做过内容生成的都知道,AI 写出来的初稿经常"看起来没错但味道不对",反思 Agent 就是那个专门挑刺的编辑。

2.2 节点的最小设计清单

设计一个 DeepAgent 节点,我的经验是至少包含四部分:

  • 角色定义:用一段话说明这个 Agent 的职责边界,明确"它不做什么"往往比"它做什么"更重要。
  • 决策逻辑:给它一个统一的思考框架,比如"先收集→再分析→再输出"的流程。
  • 工具清单:只挂载它真正需要的那几个 MCP 工具,权限最小化是铁律。
  • 输出规范:定义返回结果的结构,方便 A2A 协议把结果传给下一个节点。

项目里我把这些配置全写成了 JSON 配置文件,每个 Agent 启动时加载一份。这样做的好处是改角色不用改代码,换个场景换个配置就能跑,后期做"A2A 互通"时也方便向别的 Agent 暴露自己的描述。

2.3 一个经典的反例

我也见过把 DeepAgents 理解成"堆参数"的做法——给 Agent 塞一大段要求、几百行规则、几十个示例,指望模型记住一切。结果是:模型确实变"听话"了,但也变得极其迟钝,每轮思考的 token 消耗暴涨,而且规则之间互相打架,越执行越混乱。

真正有效的深度设计是"少而精"的原则:角色边界清晰,工具职责单一,反思时机固定。你给 Agent 的自由度越大,它对模糊任务的发挥反而越差。这个反直觉的结论,我在后面编排集群时体会更深——集群的稳定性,很大程度上取决于每个节点在多大程度上"不可发挥"。

3. MCP:给 Agent 一个标准工具箱插口

3.1 MCP 的核心架构

MCP(Model Context Protocol)现在的地位有点像 AI 应用圈的 USB-C 口——之前每个工具都要单独写插件适配,有了 MCP 之后,一套协议通吃。它的架构里有两个角色:MCP Host 和 MCP Server。

Host 是跑着 AI 应用的地方,比如你的 Agent 框架、IDE、桌面应用。Host 内部有一个 MCP Client 负责维护与 Server 的长连接。Server 则是工具提供方,它通过 MCP 协议把自己暴露成三类能力:Tools(可调用函数)、Resources(可读取的数据资源)、Prompts(可复用的提示词模板)。

传输层有两种主流方式。本地开发用 stdio,也就是 Server 以子进程方式启动,Host 和它通过标准输入输出通信,简单直接。远程部署用 Streamable HTTP,Server 跑成一个 HTTP 服务,这样多个 Agent 可以共享同一个工具后端。我在项目里是本地调试用 stdio,上到集群环境就统一切成 HTTP。

3.2 手写一个 MCP Server

课程里最过瘾的部分是十分钟手写一个 MCP Server。用 Python 的官方 SDK,代码量小得惊人:

from mcp.server.fastmcp import FastMCP mcp = FastMCP("content-research") @mcp.tool() def query_knowledge_base(keyword: str) -> str: """从内部知识库检索指定关键词的相关资料""" # 实际逻辑:连接向量数据库,召回 Top-K 文档 return "检索结果摘要……" @mcp.resource("notes://{topic}") def get_notes(topic: str) -> str: """按主题读取本地笔记""" return f"关于 {topic} 的笔记内容" if __name__ == "__main__": mcp.run()

这段代码跑起来之后,任何一个理解 MCP 协议的 Agent 都能直接调用 query_knowledge_base 这个工具。你不需要给不同的 Agent 写不同的适配层,它们用的是同一个协议、同一个接口契约。

这里有个设计细节值得注意:工具描述要写得足够精确。MCP 协议里工具描述是模型决定"该不该调用、什么时候调用"的唯一依据。描述写得太宽泛,模型会在不该用的时候乱用;写得太死板,模型该用的时候又识别不出来。我一般会在描述里补上使用场景和典型参数示例,实测对命中率提升非常明显。

3.3 三个容易踩的坑

第一是超时设置。默认的 Streamable HTTP 请求可能没有针对长任务的超时保护,Agent 调用一个耗时 30 秒的批处理工具时,连接可能提前断掉。我在 Server 端统一返回任务 ID,客户端轮询结果,而不是干等一个同步响应。

第二是工具返回体量。有些工具一返回就是几万字,直接把上下文塞爆。我的做法是在 MCP Server 里做一层"返回裁剪":超过一定长度就自动摘要,并提供分页查询参数。上下文窗口是你的宝贵资源,不能让工具输出白白消耗掉。

第三是版本兼容。MCP 协议还处于快速演进期,不同版本的 SDK 之间偶有行为差异。我的建议是项目里统一锁定 SDK 版本,并在 CI 流程里对每个 MCP Server 做一次连通性冒烟测试。

4. A2A:让 Agent 之间能"对上话"

4.1 解决的是跨 Agent 协作问题

MCP 解决的是 Agent 和工具的问题,但 Agent 和 Agent 之间的协作,MCP 管不了。A2A(Agent-to-Agent)协议就是为了补上这一块,它的思路是给每个 Agent 一份"名片"(Agent Card),描述自己是谁、能干什么、怎么联系,其他 Agent 通过这张名片发现并调用它。

A2A 协议基于 JSON-RPC 2.0,核心交互是任务(Task)和消息(Message)。一个 Agent 可以把任务委托给另一个 Agent,任务的状态、进度、结果都通过标准化的消息交换。它和 MCP 的分工非常明确:MCP 是"人与工具"的协议,A2A 是"智能体与智能体"的协议。

课程里用了一个很直观的比喻:MCP 像给你一台打印机配了统一的 USB 接口,A2A 则是让几个人能说同一种语言开会。没有 A2A 之前,多个 Agent 协作只能靠编排框架内部写死调用关系;有了 A2A,Agent 之间可以动态发现、动态组队,甚至跨厂商协作——只要大家都遵守协议。

4.2 一个完整的 Agent Card

我项目中为"写作 Agent"写的 Agent Card 长这样:

{ "name": "writer-agent", "description": "负责将研究资料整理为结构化文章初稿", "url": "https://agents.internal.example.com/writer", "capabilities": { "protocolVersion": "0.1.0", "skills": ["writing", "seo-check"], "auth": "none" } }

关键点在于 description 和 skills 字段。其他 Agent 的编排逻辑通过读取这张名片来决定"这件事该找谁"。所以名片上的描述必须跟实际能力严格对应,写大了会招来不该接的任务,写小了又会被大材小用。

4.3 任务流转的注意点

A2A 的任务交互有同步、异步之分。简单任务可以用同步请求直接拿结果;耗时任务最好是异步模式——先创建任务,再通过 agent 的 message 接口轮询状态。我在项目里对异步任务做了统一的超时上限,超过 5 分钟还没完成就触发重试或降级。

还有一个实操细节:A2A 消息中是携带"上下文摘要"还是只传"必要数据"?我最初图省事直接把上游 Agent 的完整输出塞给下游,结果下游 Agent 的上下文很快就被污染。后来改成只传结构化摘要和关键字段引用,下游如果需要详细数据,再通过 MCP 工具去查。这一步让整体准确率上了一个台阶。

5. Skills:让能力变成可复用的积木

5.1 为什么需要 Skills

在 MCP 和 A2A 都就位之后,你会发现还有一个问题没解决:Agent 的"专业技能"怎么标准化打包。比如"撰写 SEO 友好的标题"这个能力,它既不是一个 MCP 工具,也不是一个独立 Agent,它是写作 Agent 内部应该掌握的一项技能。

Skills 解决的就是这个问题。它的本质是一个目录结构:一个 SKILL.md 文件描述技能的使用方式和触发条件,再加上若干辅助资源(示例、模板、脚本)。Agent 加载之后,它在适当场景下会自动调用这个技能。简单说,Skills 是把提示词工程从"写在系统提示词里的一团文字"升级成了"可安装、可卸载、可分享的能力包"。

5.2 一个 Skill 的标准结构

我项目里的一个 SEO 检查 Skill 长这样:

seo-keyword-check/ ├── SKILL.md # 技能说明与使用指令 ├── checklist.md # 检查清单 └── examples/ └── good-headline.md

SKILL.md 的开头是 YAML 元信息,然后是正文指令:

--- name: seo-keyword-check description: 在输出文章前检查标题关键词密度和结构合理性 适用场景: 完成初稿之后、提交审核之前 --- 执行以下检查: 1. 标题是否包含核心关键词 2. 关键词密度是否在合理范围 3. 是否至少有一个吸引点击的修饰角度 4. 给出修改建议

关键是把触发条件和检查流程写清楚。Skills 和 MCP 工具的区别就在这里:工具是"被调用"的,技能是"被内化"的。Agent 看到合适的场景会主动想起来用。

5.3 分发和版本管理

Skills 越来越多之后,分发管理就成了问题。课程项目里给了一个很务实的方案:Skill 仓库走 Git 管理,每个 Skill 一个子目录,用语义化版本号标记;Agent 启动时从仓库拉取自己角色清单里需要的 Skills,并锁定版本。

我最开始图省事把所有 Skills 塞进一个"总提示词",结果改一个技能要全量重启所有 Agent。改成目录化分发之后,加一个技能就像给系统插拔一个插件,编排层的改动量基本为零。

6. 实操:搭一个四 Agent 的内容生产集群

6.1 场景与角色划分

为了把前面所有组件串起来,课程里设计了一个内容生产场景,我也在本地完整跑通了。四个 Agent 分别是:

  • 研究 Agent:负责搜集素材、整理事实、输出结构化资料包。
  • 写作 Agent:基于资料包生成文章初稿,并内化 SEO 检查技能。
  • 审核 Agent:检查事实错误、语气一致性、敏感表述。
  • 发布 Agent:把终稿转成 Markdown 并产出发布配置。

每个 Agent 都是一个独立的 DeepAgent 节点,它们通过 A2A 串联,研究 Agent 的输出是写作 Agent 的输入,写作 Agent 的初稿又交给审核 Agent。

6.2 工具层用 MCP 统一挂载

研究 Agent 需要访问内部知识库和外部搜索,这些能力我封装成两个 MCP Server:knowledge-base-server 和 web-search-server。写作 Agent 不需要直接访问它们,它的工具只有"读取上游资料包"和"调用自己的技能"。审核 Agent 的工具是"可疑事实标记器",接到疑似不实信息时自动生成复核请求。

这里体现了 MCP 的真正价值:工具能力集中沉淀在 Server 层,Agent 按需挂载。新增一个数据源时只需加一个 Server,所有需要它的 Agent 自动获得能力,不需要改任何 Agent 代码。

6.3 A2A 把四个节点串起来

任务从研究 Agent 发起,它把最终资料整理成结构化 JSON,通过 A2A 协议创建一个"写作任务"发往写作 Agent。写作 Agent 完成后,创建"审核任务"发往审核 Agent。审核 Agent 发现问题后,会把任务状态标记为 needs_revision,带上修改意见回发。写作 Agent 收到后修订一轮再重新提交。

这个任务流转模型的健壮性来源于状态机的严格定义:PENDING、RUNNING、COMPLETED、FAILED、NEEDS_REVISION。任何一步出问题,编排层都能从状态里看出卡点在哪。我在本地用脚本模拟了任务卡死的情况,结果能准确定位到具体是哪个 Agent 没响应,这在单体架构里是不可想象的。

6.4 编排层该做什么、不该做什么

编排层是整个集群的中枢,但我在实践里最重要的体会是:编排层要克制。它只负责三件事:启动任务、监听状态、处理失败重试。至于每个 Agent 内部怎么思考、怎么调用工具,编排层一概不管。

有人喜欢把业务流程也写进编排层,比如"先让 A 做,再看结果决定 B 或 C"。这不是不行,但维护成本极高。我的做法是把业务流程"下沉"到 Agent 之间的 A2A 对话里,编排层只做事件的调度员。这样业务流程变更的时候,你只需要改相关 Agent 的配置,编排层一行代码都不用动。

7. 常见问题与排查技巧实录

7.1 MCP 连接不稳定

现象:Agent 偶尔报"工具调用失败",检查发现是 MCP Host 和 Server 之间的连接中断。

排查思路:先分本地还是远程。本地 stdio 模式大概率是子进程异常退出,看进程日志;远程模式先 ping 一下 Server 的 health 接口,再看超时设置。我最终把远程 MCP 调用统一改成异步任务模式,配合重试三次的机制,稳定性从惨不忍睹提升到 99% 以上。

7.2 A2A 消息风暴

现象:Agent 之间互相触发任务,形成循环调用,日志刷屏。

排查思路:A2A 的 Agent Card 里一定要声明"接受哪些类型的任务"和"拒绝哪些类型的任务"。我在审核 Agent 里明确禁止"审核审核 Agent"这类递归调用。另外给每个任务加上唯一的 trace-id,追踪消息链路,一旦发现同一个 trace-id 在机群里转了两圈,直接拦截。

7.3 Skills 之间互相冲突

现象:两个技能同时被触发,给出的指导方向相反。

排查思路:Skills 的触发条件要设计成互斥的。比如 SEO 检查技能声明"仅在文章初稿完成后触发",敏感词检查技能声明"仅在审核阶段触发"。如果确实存在交叉场景,就在 SKILL.md 里写明优先级顺序,Agent 会先执行优先级高的技能。

7.4 上下文里塞了太多工具说明书

现象:Agent 的上下文窗口被技能说明和工具描述占掉一大半,真正用来推理的空间所剩无几。

排查思路:MCP 协议里有个概念叫"工具裁剪",你可以动态决定当前对话暴露哪些工具。我按任务阶段划分工具集:研究阶段只暴露搜索工具,写作阶段只暴露校验工具。这样每个 Agent 在任何时刻看到的工具清单都不超过 5 个,上下文开销锐减,推理质量明显上升。

我把这些问题整理成了一张速查表:

症状大概率原因快速处理
工具调用超时MCP 长任务无异步机制改为任务 ID + 轮询
Agent 间循环调用A2A 任务类型无边界收紧 Agent Card 的接收声明
输出质量下降工具描述混入上下文阶段性裁剪工具集
技能冲突SKILL.md 触发条件重叠设定优先级或拆分场景

7.5 一个治本的观察

排查来排查去,最后发现大部分问题的根源是同一个:我对单个 Agent 的"期望"超过了它该承担的范围。每当某个 Agent 出现莫名其妙的错误,先别急着调提示词或加工具,先问问"这个任务是不是根本不该它做"。多智能体架构最大的优势就是你可以把问题交给更合适的节点,但我发现大多数人(包括我自己)天生倾向于让一个已经能跑的 Agent 硬扛更多活。学会拒绝给 Agent 加戏,比学会加工具更重要。

8. 一些个人体会

把这套集群完整跑下来,我最深的感触是:DeepAgents、MCP、A2A、Skills 这四个概念单拎出来都不难,难的是把它们组合成一个有机体时的"取舍感"。

MCP 让工具接入变得标准化,但也让"什么都能接"变成了一种诱惑。我一度接了十几个 Server,结果 Agent 每轮决策都在一大堆工具里犹豫,性能肉眼可见地下降。后来砍到只剩四个核心 Server,配合阶段性的工具裁剪,效果反而更好。工具不是越多越好,这跟"提示词不是越长越好"是同一个道理。

A2A 让我重新理解了"系统集成"。以前做系统对接,定 API、写文档、联调,一套流程下来累得半死。A2A 把 Agent 之间的协作协议标准化之后,新增一个节点就是在集群里"投一张名片"的事情。这种动态组队的能力,在业务快速变化的场景下价值极大。

最后说一个细节:Skills 的维护其实是一个长期工程。我最初把所有技能都压在一个目录里,后来技能越来越多,互相之间的边界开始模糊。我现在养成的习惯是每个技能单独建库、单独版本管理,并且每半个月清理一次调用率低、效果确认不佳的技能。技能的增删和 Agent 的角色绑定,做到"即插即用",集群才能一直保持轻盈。这套东西后续我还在往"技能市场"的方向扩展——把团队内积累的技能打上标签开放给其他项目复用,那又是一个深坑,但确实值得继续折腾。

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

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

立即咨询