☰
从单Agent到Agent集群:MCP、A2A与Skills组合实践复盘
2026/10/7 6:21:06 网站建设 项目流程

先说我为什么折腾这东西。半年前我还是坚定的"单 Agent 主义者",觉得什么任务都能塞进一个 Agent 里解决。直到接了一个业务需求——让 AI 从需求文档出发,自动产出原型代码加一份技术评审说明,我才发现自己错得离谱。单 Agent 跑起来后,上下文长度越来越紧张,工具调用链越来越长,改一个接口定义就得连带改一堆封装,最后那套代码我自己都不想维护。后来我腾出几周时间,把 MCP、A2A、Skills 三套东西和编排框架 DeepAgents 组合到一起,重构成一组可编排、可互通、可扩展的 Agent 集群。这篇就是完整复盘,讲讲协议原理、架构设计,以及生产环境里那些没人提前告诉你的坑。适合已经在单 Agent 上跑通 Demo、但一到规模化阶段就处处碰壁的开发者,也适合刚入局、想搞清楚这几个名词到底各自解决什么问题的朋友。

1. 为什么单 Agent 撑不起"超级应用":三个真实瓶颈

1.1 上下文天花板:Agent 不是越大越强

很多人以为给 Agent 塞的东西越多,它就越强,实测恰恰相反。我当时把二十多个工具的说明文档、几十条业务规则、历史对话摘要全压进 system prompt,结果模型在长上下文里开始"丢三落四"——基础指令执行着执行着就漏了,工具参数也开始填错。这不是玄学,Transformer 的注意力在超长上下文里会被稀释,离得远的指令优先级天然低于最近出现的内容。你让一个"全能 Agent"同时扮演产品经理、开发、测试和运维,本质上是让它在同一段上下文里频繁切换角色,切换次数越多,遗忘越严重。

我后来做了一个很蠢但很有效的实验:把同样一个任务分别丢给"满载 Agent"和"精简 Agent"跑十次,精简版成功率高出三十多个百分点。原因很简单,专精 Agent 的上下文干净,工具少,指令近,每轮推理的注意力能集中在自己擅长的方向上。这个实验直接让我放弃了"一个 Agent 打天下"的想法,开始认真考虑把职责拆给多个 Agent——这就是集群化的第一步。

1.2 工具链孤岛:每个 API 都是一段"一次性胶水代码"

单 Agent 阶段,接一个新工具的标准流程是:写一个函数、用 if-else 让模型调用它、处理鉴权、处理超时、写错误日志。看起来工作量不大,可一旦你有几十个工具,这套胶水代码就会变成灾难。我当时的项目里躺着一堆 fetch 封装,字段改动要全局搜索替换,换一个大模型品牌还要重新验证所有工具的传参格式。工具和 Agent 深度耦合,想复用其中一个,必须连着一大坨上下文一起搬。

MCP 协议出现之前,我解决这类问题的办法是自己写一个统一网关,把所有工具 API 包成 HTTP 接口。但网关本身又成了新的维护负担,而且不同 Agent 框架对工具的定义方式不一样,网关接口还是得适配好几套。现在回头看,标准协议的价值恰恰就在这里:它把"工具如何暴露""模型如何调用"这些约定固化下来,让大家按同一套格式接入,省的是一个生态的重复劳动。

1.3 串行执行与状态混乱:单核大脑跑不动多线任务

还有一个被低估的问题:单 Agent 只能串行思考。一个跨部门需求到手,要查资料、要写文档、要评审代码,单 Agent 只能一步一步来,前面卡住后面全停。更难受的是状态管理——单个 Agent 会话里混着多个任务的上下文,某个子任务中途改了状态,其他子任务还在用旧数据。我踩过一次挺典型的坑:Agent 生成的接口文档里引用了它自己中途改废掉的旧接口名,因为上下文里的历史版本污染了最新状态。

拆成多 Agent 之后,每个 Agent 只维护自己那一段上下文,状态天然隔离,互不干扰。编排层再把各 Agent 的结果汇聚起来,从源头上消灭了"上下文互相污染"的问题。这也是为什么我现在看任何 Agent 架构,第一件事就是问"状态边界在哪"——状态混乱的集群,规模越大越容易翻车。

2. MCP 协议层:把工具栏变成热插拔的标准化插座

2.1 MCP 解决的核心问题:工具接入的"USB 化"

先说什么叫 MCP。Model Context Protocol,模型上下文协议,最早由 Anthropic 提出并开源的一套标准,目的是给 AI 应用提供一种统一访问外部工具和数据源的方式。我习惯把它类比成 USB:USB 出现之前,打印机、键盘、鼠标各有各的接口和驱动,接一台新设备要装一堆专用驱动;USB 出现之后,所有设备按统一接口规范接入,插上就能用。MCP 对 Agent 生态做的就是这么件事——把"怎么暴露工具""怎么描述工具""怎么处理调用结果"标准化。

在 MCP 的架构里有三个角色:Host 是跑模型的 AI 应用,Client 是应用里发起连接的连接器,Server 是工具和数据源的服务端。Server 对外暴露三类能力:工具(Tools,模型主动调用的动作)、资源(Resources,可读入上下文的数据)、提示(Prompts,可复用的提示词模板)。大部分场景你主要跟 Tools 打交道,资源适合做知识库注入,提示词模板则跟后面要讲的 Skills 有部分重叠,边界问题我后面细说。

我对 MCP 最大的感触是:它把"工具所有权"和"Agent 开发"彻底解耦了。工具团队只需要维护好 MCP Server,Agent 团队只需要面向协议开发,两边不需要互相等版本、互相看代码。这在多人协作的项目里省掉的沟通成本,远比协议本身带来的学习成本高。

2.2 搭一个 MCP Server 的正确姿势

实操层面,我推荐直接用各语言的官方 SDK,不要手搓 server 实现。Python 环境下面我用的是 FastMCP 这个封装库,声明工具非常简洁,基本上就是装饰器加类型注解。下面是一个典型示例,暴露一个"检索内部知识库"的工具:

from mcp.server.fastmcp import FastMCP mcp = FastMCP( "knowledge-base-search", instructions="提供内部知识库文档检索能力,返回按相关度排序的结果列表" ) @mcp.tool() def search_docs(keyword: str, limit: int = 5) -> list[dict]: """按关键词检索内部知识库,返回文档标题、摘要和链接。""" # 实际实现里这里会走向量检索服务 results = kb_client.search(keyword, top_k=limit) return [ {"title": r.title, "snippet": r.snippet, "url": r.url} for r in results ] if __name__ == "__main__": mcp.run(transport="stdio")

这里有几个细节值得留意。第一,函数的 docstring 就是给模型看的工具描述,一定要写清楚用途和参数含义,因为模型是凭这段描述决定什么时候调用它的;描述写得含糊,模型要么不敢调,要么乱调。第二,transport="stdio"表示 Server 通过标准输入输出和宿主进程通信,这种模式适合本地部署、一个 Agent 进程直接拉起子进程的场景;如果涉及多个服务共享同一个 Server,就需要用 HTTP/SSE 传输,把 Server 独立部署成服务。

另外我建议把工具的返回结构设计成稳定的字典格式,别让模型自由发挥。模型调用工具的返回结果也会被塞回上下文,格式越规整,后续推理越不容易出错。

2.3 一个 MCP Server 喂饱多个 Agent:共享工具的威力

集群化之后,MCP 的价值会被放大。我现在的架构里有七八个专职 Agent,它们名下并没有各自封装一套工具,而是通过 MCP Client 统一连到同一批 Server 上。搜索 Agent 要用知识库检索,写作 Agent 要查参考资料,评审 Agent 要核对技术文档——它们连的是同一个 knowledge-base-search Server。

这样做的好处非常直接:新增一个工具时,只需要新增或修改一个 MCP Server,所有 Agent 共享同一份能力,不需要挨个改 Agent 的工具列表。更妙的是,MCP Server 本身可以按需启停,某个 Server 挂了,Agent 只是少一个工具,不会像以前那样整段逻辑崩掉。我把这叫做"工具的横向扩展",它是整个集群扩展性的地基。

3. A2A 协议层:让不同框架的 Agent 互相对话

3.1 Agent Card:联网自我介绍的能力名片

MCP 解决了"Agent 和工具"的互联,但"Agent 和 Agent"之间还是各说各话。我在做集群的时候,第一个 Agent 用的是 LangGraph,第二个用自研框架,第三个干脆是别人用 Rust 写的开源 Agent……想让它们协作,你得为它们之间定义一套双方都能理解的通信格式。A2A(Agent2Agent)协议就是干这个的,它最早由 Google 提出,后来捐给了 Linux Foundation 做中立化治理,核心思路是把 Agent 之间的交互建立在 HTTP + JSON 消息之上,不要求双方使用同一个框架。

A2A 里最核心的概念是 Agent Card。我把它理解成"Agent 的名片"——一份公开的 JSON 文档,描述这个 Agent 是谁、能干什么、怎么联系它。一个简化版的 Agent Card 长这样:

{ "name": "research-agent", "description": "负责资料检索与信息汇总,支持知识库与网页搜索", "url": "https://agents.internal/research", "version": "1.2.0", "capabilities": { "skills": ["search", "summarize", "citation"], "max_concurrent_tasks": 4 }, "security": { "auth_method": "bearer_token" } }

其他 Agent 拿到这份 Card,就知道该把什么类型的任务委托给它、用哪种方式鉴权、它能同时接多少活。换句话说,Agent Card 是集群里"服务发现"的基石——编排器不可能提前写死每个 Agent 的所有信息,但可以靠 Card 做动态发现和路由。

3.2 任务生命周期:一次跨 Agent 请求的完整流转

A2A 的消息模型围绕 Task 展开。一个 Agent(Client Agent)向另一个 Agent(Server Agent)发起 task/send 请求,服务端响应一个 Task ID 和初始状态;之后双方通过 task/get 或者事件流(task/stream)持续同步状态,直到任务进入 completed 状态,最终产出称为 Artifact 的结构化结果。

我实际跑通的最简流转是这样:编排器把"收集本周技术资讯"分派给资讯 Agent,资讯 Agent 的 A2A 客户端发 task/send 给检索 Agent,检索 Agent 处理时通过 task/stream 推送"正在检索知识库""正在抓取订阅源"的过程状态,最后回传一个 Artifact——整理好的资讯列表 JSON。整个过程里,两边用的框架完全不同:一侧是我用 Python 写的,另一侧是一个基于 Erlang 的开源 Agent,A2A 让它们像两个人用同一张表格沟通一样顺畅。

值得注意的是,A2A 的 Task 是长事务,不是一次 HTTP 请求就完事。我建议对状态轮询做超时和重试设计,不然一个耗时任务能把编排器的线程池拖死。我在项目里就吃过这个亏,最初轮询间隔设置得不合理,20 个 Agent 同时起任务,编排器直接打满 CPU。后来把轮询改成事件流推送,再加上任务级超时,才把这块稳住。

3.3 MCP 和 A2A 的分工:连接工具 vs 连接智能体

我刚接触这两个协议时最常被绕晕的问题就是:MCP 和 A2A 到底什么关系?其实分工非常清楚——MCP 面向"Agent-工具"层,解决的是模型怎么调用外部能力的问题;A2A 面向"Agent-Agent"层,解决的是智能体之间怎么协作的问题。你可以把 MCP 理解为 Agent 的手和脚,A2A 是它们之间的电话线。

两者在实践中的侧重点也不一样。MCP 更关注工具描述、调用格式、数据返回的规范化;A2A 更关注能力发现、任务状态管理、结果传递和鉴权。一个 Agent 集群里,理想状态是:对外工具能力全部走 MCP,Agent 之间协作全部走 A2A,两层协议各管各的,互不越界。谁要是拿 A2A 当工具调用协议用,或者拿 MCP 硬撑 Agent 间通信,最后都会很别扭。

4. Skills 能力层:把高频操作沉淀为可移植的经验包

4.1 Skill 的本质:方法论 + 脚本 + 校验,打包成一叠资料

如果说 MCP 解决"能用哪些工具",A2A 解决"怎么找同伴",那 Skills 解决的是"知道怎么干活"。这里说的 Skills,指的是一类很具体的东西:把一个完整任务的执行方法论,连同辅助脚本、参考资料、校验清单,打包成一个可以被加载进 Agent 上下文的文件夹。这个概念被 Claude 的 Agent Skills 带火之后,现在很多框架都原生支持,已经算事实上的标准做法了。

为什么需要 Skills?因为光有工具不够。比如让 Agent 做代码审查,它当然可以调用 git 命令、调 MCP 里的代码分析工具,但它首先得知道审查流程是什么:先看什么文件、从哪些维度打分、怎么输出建议。这些"方法论"如果每次都靠提示词现编,不同 Agent 的执行质量会忽高忽低。把它们固化成一个 Skill,就等于把某位资深工程师的审查习惯完整复制给了每一个 Agent。

4.2 一个高质量 Skill 的目录结构

我参考社区里公认的做法,定了这么一套规范结构:

code-review-skill/ ├── SKILL.md # 核心说明:何时使用、执行步骤、输出要求 ├── scripts/ │ └── review.py # 辅助脚本:拉取 diff、统计改动规模 ├── references/ │ ├── checklist.md # 审查检查清单 │ └── examples.md # 好的审查报告示例 └── tests/ └── test_review.py # 自检脚本,验证 Skill 本身可用

SKILL.md 的开头必须有 frontmatter,至少要包含 name 和 description。name 就是 Skill 的标识,description 是给编排器和 Agent 看的"何时该用我"的说明,这两项写得好不好,直接决定 Skill 能不能被正确路由。我见过太多人辛辛苦苦写 skill,description 却写成了"帮助用户做代码审查",太泛了,模型反而不知道该在什么场景触发。描述里应该讲清楚输入是什么、输出是什么、典型的适用场景是什么。

执行主体部分我习惯用清晰的编号步骤,尽量提供"遇到 X 情况就做 Y"的分支指示。模型在推理时对明确条件的执行效果,远好于对开放式描述的发挥。一句话:Skill 是写给模型看的工程手册,不是写给人类看的散文。

4.3 我实际沉淀的 3 个 Skill 案例

第一个是代码审查 Skill。它会在 Agent 拿到一次 PR 的 diff 之后,按"安全性、可读性、性能、测试覆盖"四个维度打分,并输出标准格式的评审结论。这个 Skill 里附带了一个脚本,自动把 diff 拆分成按文件分组的 JSON,省得 Agent 自己解析 git 输出。团队后面每次评审都用它,评审口径从此统一了。

第二个是接口文档生成 Skill。它的执行流程是:读取接口定义文件 → 提取参数和返回结构 → 按团队模板生成中文文档 → 用脚本校验必填字段和文档里的术语表。和 MCP 的区别是,它不连接任何外部系统,纯粹是一套"基于静态文件做事"的方法论,所以做成 Skill 非常合适。

第三个是数据清洗 Skill,给数据 Agent 用。里面沉淀了处理缺失值、去重、字段映射的一整套规范,还带一个 pandas 辅助脚本。数据 Agent 每次拿到脏数据,先加载这个 Skill,再决定调用哪些 MCP 工具落地执行。实际效果就是清洗结果的可复现性大幅提高,同样一份数据,不同批次跑出来的逻辑完全一致。

4.4 Skills 和 MCP 的边界:什么时候用哪个

我总结了三条判断标准,可以帮大家少走弯路:

  • 依赖外部系统(数据库、搜索服务、SaaS API)→ MCP Server;
  • 纯静态方法论 + 脚本 + 参考资料,不依赖外部账号 → Skill;
  • 既有流程又有外部调用,那就 Skill 负责流程,MCP 负责具体调用,两者配合。

比如"数据清洗"里,"怎么判断缺失值"是方法论,放 Skill;"从数据库读原始表"是外部调用,走 MCP。这样拆完,Skill 可以跟着 git 做版本管理,MCP Server 可以独立部署独立扩容,两边互不拖累。

维度MCPSkills
本质外部工具/数据接入协议方法论 + 脚本 + 参考资料的包
依赖需要运行的服务、账号、鉴权通常是静态文件,可版本化
扩展方式部署新 Servergit 提交新文件夹
典型场景搜索、数据库、API 调用代码审查、文档生成、数据处理规范
与 Agent 的关系通过协议连接,运行时发现加载进上下文,按需启用

这张表我在团队内部发过很多次,每次有新人问"这个能力该上 MCP 还是上 Skill",直接对表查就行。

5. DeepAgents 编排层:把三套协议拼成一台机器

5.1 四层架构:Skill 层、连接层、通信层、编排层

前面的能力都齐了,还差一个把它们组织起来的"大脑"——也就是 DeepAgents 这套编排框架在我架构里的位置。我理解的 DeepAgents,核心不是某一个特定的 Agent,而是一整套"深度 Agent 化"的设计思路:编排器做任务分解和调度,各专职 Agent 执行,协议层负责互通,能力层负责沉淀。

我最终落地的四层架构是这样的:

  • 能力层:存放各种 Skills,按仓库目录组织,可被任意 Agent 按需加载;
  • 连接层:统一部署 MCP Server 集群,提供外部工具和数据源能力;
  • 通信层:基于 A2A 协议,让异构 Agent 之间互相发现、互发任务;
  • 编排层:DeepAgents 编排器,负责理解用户意图、拆解任务、分派给合适的 Agent、汇聚结果。

分层的最大好处是每一层都可以独立演进。我在中期换过两个 Agent 实现,通信层完全没动;新增一个能力,只需要在能力层加一个 Skill 文件夹,或者连接层挂一个新 MCP Server。这就是标题里说的"可编排、可互通、可扩展"三个词的含义,它们不是口号,是逐层设计出来的结果。

5.2 编排器的工作机制:注册表、任务分解与结果汇聚

编排器干的事,说白了就是三件:看注册表、拆任务、汇结果。注册表里存着每个 Agent 的 Agent Card,编排器根据任务描述匹配能力;拆任务用的是 planner 模式,把一个大目标分解成若干子任务;汇结果则是把各 Agent 返回的 Artifact 做后处理,拼装成最终回复。

这里有个值得注意的设计点:任务分解不要拆得太碎。我最早把"写周报"这个任务拆成了八个子步骤,每个子步骤丢给不同的 Agent,结果光是协调上下文和格式对齐就花了几十倍的开销。后来改成"三层拆解"——编排器只拆到子任务粒度,每个子任务由一个专职 Agent 内部自行规划,编排层只做粗粒度控制。瘦身后的编排器现在非常轻,它不参与具体执行细节,只负责路由和兜底。

5.3 一次真实的跨 Agent 任务流转

拿开头提到的每周技术分享来说,完整链路是这样的:

用户对编排器说"整理本周技术周报,并生成一份分享大纲"。编排器先进入规划模式,得出三个子任务:检索本周技术资讯、整理归纳、生成分享大纲。第一步,编排器把检索任务通过 A2A 发给资讯 Agent,资讯 Agent 加载检索 Skill、调用知识库 MCP Server,回传一批原始链接。第二步,编排器把整理归纳任务发给写作 Agent,写作 Agent 加载摘要 Skill,对原始内容做结构化整理。第三步,编排器把大纲生成任务发回写作 Agent,同时拉上评审 Agent 对大纲做一次质量检查。最后编排器汇总 Artifact,按用户输入的格式输出完整周报和大纲。

这条链路里,A2A 承担了三次跨 Agent 通信,MCP 承担了两次外部数据调用,Skills 被加载了三次,而编排器始终只做路由和汇总。换成传统单 Agent,这条链路全挤在一个上下文里,大概率会在第三步就因为上下文混乱而出错。集群化带来的体验变化是质的,不是量的。

6. 上生产前必须处理的四个问题

6.1 并发与限流:集群再强也要排队

多 Agent 集群最大的威胁是自激:一个任务发出十几个子任务,每个子任务又触发多次 MCP 调用,瞬间就能把后端服务打爆。我在压测时就见过一次,资讯 Agent 一次任务触发了 40 多次知识库检索,把检索服务的线程池直接打挂了。

现在我在编排器里加了三层保护:任务级并发上限(同一时刻最多跑 N 个 Agent 任务)、MCP 调用令牌桶限流、对后端服务的心跳检测。超时的调用统一走指数退避重试,但重试必须保证幂等——之前有个 Agent 重复创建了三条重复工单,就是因为重试时没有幂等控制,复盘时大家脸色都不太好看。

6.2 权限边界:最小权限原则要贯彻到每个 Server

多 Agent 意味着多入口,每个入口都可能被恶意提示词攻击。我对安全的态度很保守:每个 MCP Server 使用独立的鉴权凭据,而且权限范围按该 Server 的真实职责最小化。比如知识库检索 Server 的 token 只读权限、不能访问内部管理接口;文件操作 Server 只允许访问白名单目录,任何路径穿越尝试直接拒绝。

A2A 通信层也要做双向认证,不能让任何携带合法格式的消息就能直接进来。我还有一个习惯:编排器对所有 Agent 的返回结果做一次输出校验,限制中可以携带的敏感关键词,防止某个被污染的 Agent 把内部数据带到外部。多 Agent 系统的安全性,取决于最薄弱的那个节点,所以每个节点都不能放松。

6.3 可观测性:没有链路追踪,排查问题等于大海捞针

单 Agent 出错,看一段日志就能定位。多 Agent 出错,任务可能在编排器、三个 Agent、两个 MCP Server 之间来回跳,没有链路追踪根本不知道断点在哪。我在第一版里吃了大亏,生产环境报了一次"周报内容丢失",我足足查了两个小时,才发现是写作 Agent 的 A2A 回调超时,结果被编排器静默丢弃了。

现在每个 A2A 任务都会生成一个 trace-id,贯穿编排器、各 Agent、MCP 调用全过程。所有日志统一 JSON 结构化,至少包含 trace-id、agent_id、task_id、耗时、调用方这五个字段。告警规则里有一条我一直保留:如果某个 Agent 连续三次任务失败,立刻报警,不要等用户发现。

6.4 降级与容错:一个 Agent 挂了,不能拖垮整个集群

集群化之后,单个 Agent 的故障不再只是它自己的事。我在架构里给每个关键职责至少准备了一个备用方案。检索 Agent 挂了,编排器可以把检索任务临时转给通用 Agent,效果差一点但链路能跑通;MCP Server 挂了,相关 Agent 要能感知并降级——比如知识库检索不可用时,自动改用本地缓存。

超时配置也要按任务特性分档:简单的工具调用 5 秒超时,跨 Agent 的复杂任务给到 60 秒以上,不能一刀切。这条建议是我从一次事故里换来的:当时所有任务都用同一个超时时间,慢一点的 A2A 任务成批失败,编排器又无限重试,差点把整个集群拖死。

7. 我的复盘:这套组合拳到底值不值得学

最后说说我的真实感受。MCP 是四样东西里投入产出比最高的,它让工具系统从"写死"变成"热插拔",一次改造长期受益。A2A 的上手成本最高,如果你的 Agent 都在同一个框架内部,可以先不上,等真的出现跨框架协作需求再引入。Skills 是我用得最顺手的一层,它把团队经验沉淀成了可版本化复用的资产,新 Agent 上线第一天就能继承团队的全部方法论。DeepAgents 编排层则是连接所有这些的骨架,它的核心设计原则是"编排器要笨、执行者要专"——编排器只做路由和汇聚,专业判断全部下放给专职 Agent。

如果你也想搭一套类似的集群,我给的建议是别一上来就搞大的。先搭一个编排器加两个专职 Agent,一个负责检索,一个负责写作,用 MCP 接一个真实工具,用 A2A 打通两者通信,再往其中一个 Agent 挂一个 Skill。跑通这条最小闭环之后,你会发现后面每加一个 Agent、每加一个 Server,都是在往这套骨架上长肌肉,而不是重新发明轮子。这套组合拳的复杂度是真实的,但收益也是真实的——它把 Agent 开发从"写脚本"提升到了"搭平台"的层面,这大概就是下一代 Agent 集群最值得投入的地方。

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

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

立即咨询