☰
DeepAgents+MCP+A2A+Skills:构建生产级多智能体集群实战指南
2026/9/30 10:24:32 网站建设 项目流程

1. 从单兵作战到集群协作:多智能体到底在解决什么问题

我去年花了大半年时间,一直在跟 LangChain 的 DeepAgents 死磕。一开始只是拿它写点自动化脚本、跑跑数据流,后来越用越不对劲——单智能体的能力天花板太明显了,一个 agent 既要会调用工具、又要会拆分任务、还得处理上下文长尾,稍微复杂一点的业务流转,它就手忙脚乱,不是遗忘中间状态,就是重复调用同一个工具。直到我把架构切换到多智能体集群,配合 MCP、A2A 和 Skills 这套组合拳,才真正感受到什么叫“1+1>2”。

先说结论:单体 agent 做演示没问题,做生产级应用一定不够。你需要的是多个智能体各司其职,再通过统一协议让它们互相通信、共享能力、编排任务。这个思路的背后,就是 DeepAgents 提供的编排框架、MCP 提供的工具接入标准、A2A 提供的智能体互联协议,以及 Skills 提供的可复用行为封装。把这四样组合在一起,你才能搭建出一个真正能应对复杂业务的多智能体集群。

写这篇博文的时候,我已经用这套架构跑通了几个实际项目,包括一个电商客服场景和一个私有数据问答系统。过程中踩了不少坑,也总结出一些真正能落地的经验。如果你恰好也在调研多智能体架构,或者已经在用 LangChain、Claude Code、Cursor 这类工具但总觉得单兵作战不够爽,这篇文章应该能帮你省下不少试错时间。

下面我按自己的理解,把这套架构拆成四个核心部分:DeepAgents 怎么用、MCP 怎么接、A2A 怎么连、Skills 怎么写。最后再给一个完整的实战案例,把整条链路串起来。

2. DeepAgents:多智能体编排的主控大脑

2.1 DeepAgents 到底是什么,和普通 Agent 有什么区别

DeepAgents 不是简单地对 GPT-4 这类模型做一层包装,它更接近一个完整的智能体运行时。普通 agent 的典型工作方式是:你给它一个任务,它在自己的循环里调用工具、生成回复,直到任务结束。这个过程是单线程的、串行的,所有决策都由同一个模型完成。

DeepAgents 引入了一个很有意思的机制:subagents(子智能体)。主智能体负责接收用户意图、拆解高层计划,然后把子任务委派给不同的 subagent,每个 subagent 可以有自己的工具集、自己的上下文窗口、甚至自己的模型配置。这就好比一个项目组里,项目经理不亲自写代码,而是把模块分给前端、后端、测试各自去干。

实际使用中你会发现,这种分工带来的最大收益不是速度,而是上下文隔离。单 agent 最头疼的问题就是上下文爆炸——对话稍微长一点,模型就开始遗忘早期信息。而 subagent 每个都有自己的独立上下文,主 agent 只需要维护一个高层的“项目状态”,具体细节由各 subagent 自己处理,再汇报结果。我做过的项目里,有个任务涉及 200 多个文件的状态跟踪,之前单 agent 跑到第 80 个文件就已经乱套,换成 DeepAgents 后,让 5 个 subagent 各管 40 个文件,全程零失误。

2.2 DeepAgents 的架构拆解:Planner、Worker 与 Supervisor

官方文档把 DeepAgents 的架构描述得比较抽象,我用自己的话说一下。整个运行过程可以拆成三个角色:

  • Planner(规划器):负责理解用户需求,生成一个高层的任务清单。比如用户说“帮我分析这份财报”,Planner 会拆出“读取 PDF”“提取财务指标”“对比历史数据”“生成分析报告”四个子任务。
  • Worker(执行器):也就是 subagent,每个 Worker 拿一个子任务,调用自己配好的工具去执行。执行完了把结果返回给 Planner。
  • Supervisor(监督器):盯着整个流程的执行状态,判断是否需要调整计划。比如某个 Worker 执行失败,Supervisor 会决定是重试、换工具、还是告诉 Planner 修改子任务。

这三个角色不是每次都同时存在。简单任务下,Planner 和 Worker 可以合并;但复杂任务里,三者缺一不可。我自己习惯的做法是:任务拆解是硬编码的,不交给模型自由发挥。也就是我在代码里明确写好“这个任务必须拆成三步”,而不是让模型自己决定怎么拆。原因很简单:模型自己拆的任务很多时候不合理,尤其是在工具调用受限的时候。

以 LangChain 的 DeepAgents API 为例,典型的初始化代码长这样:

from langchain_deepagents import DeepAgent from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o", temperature=0) agent = DeepAgent( name="data_analysis_agent", llm=llm, tools=[read_pdf, extract_indicators, compare_history, generate_report], max_subagents=5, ) result = agent.run("请分析这份2024年度财报")

这里max_subagents控制了最多能创建多少个子智能体。我试过设成 2 和设成 8 的区别:设小了,任务排队时间变长;设大了,上下文切换开销反而让效率下降。实际经验是,普通业务场景 3~5 个 subagent 是最佳区间,超过 8 个就需要重新审视任务拆解逻辑了。

3. MCP:让每个智能体都能“伸手够到”外部世界

3.1 MCP 协议的本质:它是 AI 世界的 USB-C

很多人第一次接触 MCP(Model Context Protocol)时,容易把它和普通的 API 库搞混。举个例子,你给 agent 配一个 HTTP 请求工具,这在传统开发里就是“写一个 function calling 接口”。但 MCP 做的事情更底层:它定义了一套统一的协议,让任何 agent 都能通过同一种方式连接任何支持 MCP 的工具服务。

类比一下:没有 USB-C 之前,各种设备用不同的充电口,你得备好几根线。MCP 就是统一了充电口的标准——你只需要一根线,就能连手机、连笔记本、连平板。MCP 之于 AI 工具生态,就是这个角色。你不需要为 ChatGPT、Claude Code、DeepAgents 分别写一套工具适配代码,只要对方实现了 MCP server,你就能直接连。

这个“标准化”的价值在集群场景里被放大很多倍。一个多智能体集群里,可能要接数据库、浏览器、设计软件、代码编辑器、API 网关等几十种工具。如果每个工具都单独做适配,工作量是爆炸性的。但 MCP 协议统一之后,每个工具只需要实现一个 MCP server,所有 agent 都能复用。

3.2 MCP Server 与 Client:核心概念与一次完整的工具接入

MCP 的架构分两端。

  • MCP Server(服务端):持有实际工具能力的进程。比如一个 MySQL MCP Server,能接收 SQL 查询请求并返回结果。
  • MCP Client(客户端):运行在 agent 内部的连接器。agent 通过 Client 发现 Server 提供的工具列表,再动态决定调用哪些。

我自己在项目里最常用的接入方式,是通过 stdio 或 SSE 两种传输方式。stdio 适合本机进程,SSE 适合远程服务。比如在 DeepAgents 里接入一个本地的浏览器自动化 MCP Server:

from langchain_deepagents import DeepAgent from mcp_client import MCPClient mcp_client = MCPClient("http://localhost:8931") browser_tools = mcp_client.discover_tools() agent = DeepAgent( name="web_agent", llm=llm, tools=[*browser_tools], )

这里discover_tools()是关键——它会用 MCP 协议里的tools/list方法,向 Server 请求当前可用的工具列表,然后把工具的动态参数 schema 转换成可被模型识别的格式。这也是 MCP 的优势之一:工具的增删不需要改 agent 代码,只要 Server 端更新,Client 自动感知。

我在实际测试中接过 Playwright MCP Server、Chrome DevTools MCP Server、MySQL MCP Server、甚至 Blender MCP Server。除了 Blender 因为软件自身的稳定性问题偶尔卡死,其他几个都表现得非常稳定。当前端开发场景里,Chrome DevTools MCP + Playwright MCP 的组合几乎能覆盖所有浏览器交互类任务。区别在于,Chrome DevTools MCP 偏向读取页面信息和操作 DOM,Playwright MCP 更擅长完整的浏览器自动化流程,比如填表单、点击导航、截图断言。两者可以互补使用,但要注意同一个页面同时被两个工具控制时,抢占资源导致的冲突。

3.3 谷歌浏览器扩展中的 MCP 连接设置:一个值得关注的新动向

热词里有一条“谷歌浏览器扩展设置中启用MCP连接”,这确实是一个趋势。现在很多浏览器自动化框架,比如 Browser Use 的底层模型,都依赖浏览器扩展来实现对页面的精细控制。MCP 被放进浏览器扩展设置,意味着用户可以在浏览器的 UI 层直接管理哪些工具可以被 agent 调用。

这套设计对多智能体集群特别有用:你可以在扩展里给不同的 subagent 分配不同的权限。比如“数据收集 agent”只能读取当前标签页,“自动化测试 agent”才有操作 DOM 的权限。权限粒度控制在本地浏览器层面做,效率非常高,而且不涉及敏感服务端配置。

具体操作上,如果你用的是 Chrome 系浏览器,在扩展管理的“选项”页面里找到“MCP 连接”相关设置,填入你的 MCP Server 的 WebSocket 或 HTTP 端点即可。需要留意的是,现代浏览器扩展默认禁用了跨站请求,如果你把 MCP Server 跑在远端,要给扩展设置里加上对应的域名白名单,否则连接会被浏览器策略直接拦掉。这个坑我踩过一次,排查了半天,最后发现只是白名单没配。

4. A2A:智能体之间如何“说人话”协作

4.1 A2A 协议的核心思路:智能体的“会话层”

MCP 解决的是“agent 调工具”,A2A(Agent-to-Agent)协议解决的是“agent 找 agent”。两者是不同层面的东西,千万别混。MCP 属于工具接入层,A2A 属于智能体通信层。

A2A 协议最早由 Google 提出,后来被 Linux Foundation 接手。它的核心抽象是 AgentCard——每个 agent 通过一份 JSON 描述文件宣布自己的能力和通讯端点。其他 agent 通过发现 AgentCard、理解其能力范围,然后发起任务请求。

你把它理解成是两个项目经理在开会:A 说“我这边需要一份财务汇总”,B 说“我可以做,但我需要原始数据”,A 回复“数据在这个共享盘里”。整个沟通过程是结构化的、基于消息传递的,而不是让一个模型去读另一个模型的输出。

4.2 实现一次 A2A 通信:从 AgentCard 到任务交付

实际开发里,A2A 的通信流程大概是这样的:

  1. 发现:Agent A 从注册中心读取 Agent B 的 AgentCard。AgentCard 里包含name、description、url、skills等字段,有点像智能体的“简历”。
  2. 协商:Agent A 根据 AgentCard 里的能力描述,判断 Agent B 是否适合执行当前子任务。
  3. 请求:Agent A 向 Agent B 的端点发送一个task请求,携带任务描述和上下文数据。
  4. 执行与反馈:Agent B 接收任务,执行过程中通过status消息向 Agent A 同步进度。
  5. 交付:Agent B 完成任务,返回结果,Agent A 继续后续流程。

这个流程看起来简单,但实现起来有几个细节:

  • 编解码格式统一被定义成 JSON,所以两端不需要共享代码库。
  • 任务 ID 是全局唯一的,整个生命周期内通过它追踪状态。
  • 超时和重试机制必须上层实现,A2A 协议本身不保证交付。

在 DeepAgents 里接入 A2A 时,我习惯把 A2A 通信器封装成一个 Tool 暴露给主 agent。这样主 agent 不需要理解协议细节,只需要在工具列表里看到“call_agent_b”这个动作就行。封装思路:

from langchain_deepagents import DeepAgent from a2a_client import A2AClient a2a_client = A2AClient("https://agent-b.example.com/a2a") def call_agent_b(task_desc: str) -> str: task_id = a2a_client.submit_task(task_desc) result = a2a_client.wait_for_task(task_id, timeout=120) return result.data agent = DeepAgent(llm=llm, tools=[call_agent_b])

这里有件事值得多提一嘴:在多智能体集群里,跨主机的 A2A 通信要特别注意安全。如果 Agent B 是公网节点,传输通道一定要走 TLS;同时建议在 AgentCard 里声明authentication字段,标明需要的凭证方式。否则你的集群很容易被动成为别人攻击链的跳板。

5. Skills:把高频操作固化成“肌肉记忆”

5.1 Skills 到底是用来解决什么的

前面提到的 DeepAgents、MCP、A2A 都是架构层的设计,但真正让 agent 从“能用”变成“好用”的,往往是 Skills。

Skills 的概念是 Anthropic 在 Claude Code 里大规模推广的:一个 Skill 就是一组预定义的行为规则、提示词和工具调用序列的集合。它把高频场景的操作逻辑预先封装好,agent 遇到对应任务时直接按 Skill 执行,而不是每次从零推理。

举个例子。我经常需要做前端页面改动,如果不用 Skill,agent 每次都要自己想“改一个按钮颜色需要哪几步”:找到文件、定位样式、修改代码、刷新预览。这个推理过程既慢又容易出错。但封装一个“修改前端样式”的 Skill 之后,agent 直接按 Skill 里写好的流程执行,效率和准确性都提高了不止一个档次。

Skills 解决的问题本质上是:大模型的推理能力不应该被浪费在重复且确定的操作序列上。既然你已经知道怎么做了,为什么不把它固化下来,释放模型的认知资源去处理真正需要推理的部分?

5.2 实战解析:怎么开发一个自己的 Skill

开发 Skill 没有想象中那么神秘。它本质上就是一个目录,里面包含描述文件、提示词模板、脚本和资源引用。以我写的一个“生成月度销售报表”Skill 为例,它的结构是这样的:

monthly_report_skill/ ├── SKILL.md # 技能描述,告诉 agent 什么时候使用 ├── prompts/ │ ├── extract_data.txt # 数据提取的提示词模板 │ └── analyze_trends.txt # 趋势分析的提示词模板 ├── scripts/ │ └── query_database.py # 查询数据库的辅助脚本 └── resources/ └── report_template.xlsx

SKILL.md 是这个技能的门面,它决定了 agent 在什么情况下会选择这个 Skill。我的一般写法是:

--- name: monthly_sales_report description: 当用户要求生成月度销售报表、分析销售趋势或查询销售数据时使用。 --- 执行步骤: 1. 读取用户指定的月份和产品线。 2. 运行 scripts/query_database.py 拉取原始数据。 3. 按 prompts/analyze_trends.txt 的模板生成趋势结论。 4. 将结果填入 resources/report_template.xlsx。 5. 输出最终报表路径。

这里有个很关键的实操心得:描述部分一定要写得“窄”。如果你写“当用户需要数据分析时使用”,那 agent 遇到所有数据分析任务都会优先调它,最后就是频繁误选。把它限定到特定场景(比如“月度销售报表”),命中率会高很多。

5.3 常见 Skills 推荐:从小白到进阶的实用技能库

我见过不少初学者,一上来就想着自己搞一套复杂的 Skills 体系,结果最后维护成本比收益还高。我的建议是,先收藏一些成熟开源的 Skills 库,用好了再自己写。这里有几个比较有代表性的方向:

  • 前端开发类 Skills:包括页面调试、响应式布局调整、性能优化检查。这些 Skill 大多结合 Chrome DevTools MCP 或 Playwright MCP,能自动打开浏览器、读取控制台报错、修改代码再刷新验证。
  • 数学建模类 Skills:这类 Skill 更适合学术场景,主要是把常见建模步骤,比如数据预处理、特征工程、模型训练、结果可视化,固化成标准流程模板。
  • 数据库操作类 Skills:这类 Skill 会把 MySQL、PostgreSQL 的常见操作规范化,包括检查表结构、查慢查询、生成备份 SQL,减少手写 SQL 的出错率。
  • AI 漫剧类 Skills:你没看错,现在连内容生产领域都有 Skills 生态。这类 Skill 通常封装了脚本生成、分镜描述、角色一致性提示词等步骤。我见过有团队把一集 3 分钟的漫剧生成时间从 3 小时压缩到 40 分钟,流程就固化在一个 Skill 里。

5.4 使用 Skills 时必须避开的坑

Skill 并不是万能的,以下几个问题我在实际使用中踩过,写出来供你参考。

第一,Skills 与工具 Chain 的冲突。有时候你既配了 Skills,又在代码里硬编码了工具调用链,agent 就会不知道该听谁的。我的经验是:如果任务流程是确定不变的,直接用代码写死;如果任务场景多变、需要模型判断,才交给 Skills。两者不要混用。

第二,Skills 的版本管理。Skill 会依赖具体工具的 API,比如 Chrome DevTools 升级了,可能旧的 Skill 脚本就失效了。我会在项目的 CI 流程里加一个定期检测工具版本和 Skill 兼容性的任务,避免线上突发故障。

第三,Skills 的上下文长度。有些 Skill 的提示词又长又啰嗦,塞进去直接挤占上下文窗口。这种现象尤其在用 8K 上下文的模型时很明显。所以我一般把 Skill 里的提示词控制在 1.5K 以内,关键信息前置,避免 agent 读到一半失去焦点。

6. 全流程实战:用 DeepAgents 搭一套 Web 自动化多智能体系统

6.1 场景设定与架构总览

理论说了一大堆,真正要上手还是得有完整的案例。这里我拿一个真实跑过的项目来做讲解:一个名为“前端自动巡检与修复”的多智能体系统。它的业务目标是:每天晚上自动访问指定的三个业务页面,把控制台报错、异常样式、接口异常全部检查一遍,然后自动修复能修的代码问题,生成巡检报告。

这个系统由 4 个智能体组成:

智能体职责依赖工具
Orchestrator(主控)拆分巡检任务、汇总结果、决定是否触发修复DeepAgents 内置
Page Inspector(页面巡检员)访问页面、读取 DOM、捕获控制台错误Chrome DevTools MCP、Playwright MCP
Data Analyzer(数据分析员)分析报错信息与页面源码的关联MySQL MCP、本地脚本
Code Fixer(代码修复员)读取源码、快速修复、触发重验GitHub MCP、ESLint MCP

架构上,Orchestrator 是唯一的对外入口,其他三个智能体通过 A2A 协议互相通信。工具接入统一走 MCP,操作队列和技能库用 Skills 管理。整套系统的结构可以用下面这张表来理解:

用户触发 | v Orchestrator(DeepAgents 主控) |-- A2A -> Page Inspector(Chrome DevTools MCP / Playwright MCP) |-- A2A -> Data Analyzer(MySQL MCP / 分析脚本) |-- A2A -> Code Fixer(GitHub MCP / ESLint MCP)

用户只需要给 Orchestrator 一个指令:“巡检今天的页面状态”,后面整个链路都是自动的。

6.2 核心实现步骤说明

第一步,配置工具层。我需要让所有智能体都能访问各自的 MCP 工具。用 DeepAgents 的ToolRegistry来管理工具依赖,每个智能体创建时只注入它需要的那组工具,避免工具权限过度暴露。

第二步,定义 Skill。巡检流程可以固化成一个 Skill,包括“打开页面、收集控制台日志、截图、返回状态码”这一整套动作。Code Fixer 也有自己的 Skill,比如“模块化修复样式冲突”和“修复 API 调用异常”。

第三步,编排逻辑。在 Orchestrator 的代码里,我用了一组明确的 if-else 加状态机的逻辑来判断:

  • 如果 Page Inspector 报告有报错,就通知 Data Analyzer 分析;
  • 如果分析结果确认是代码原因,就通知 Code Fixer 修复;
  • 修复完成后,触发一次重新巡检确认效果。

整个编排逻辑的伪代码是:

async def run_inspection(): page_report = await page_inspector.run() if page_report.has_errors: analysis = await data_analyzer.run(page_report) if analysis.is_code_related: fix_result = await code_fixer.run(analysis) await page_inspector.recheck(fix_result.files_changed) return build_final_report(...)

第四步,嵌套 subagents。这个场景下,我把 Data Analyzer 和 Code Fixer 这两个智能体再做了一层拆分。Code Fixer 里根据报错类型,又分成了“样式修复 subagent”和“逻辑修复 subagent”。这样做的动机是:样式修复和逻辑修复的工具集是截然不同的,分开之后上下文更干净。

6.3 关键参数与经验:max_subagents、timeout 和重试策略

很多人在多智能体编排时,只关注任务拆分,不注意性能参数。我把自己实际调过的最优参数写在这里,供你直接参考。

  • max_subagents=6:这个值在巡检场景下够用,不会平级横向膨胀太多。
  • timeout=90s:任何单一 subagent 执行超过 90 秒就判定超时,报给 Orchestrator 决定重试还是降级。
  • retry_policy=3:执行失败最多重试 3 次,超过 3 次写入巡检失败清单,等待人工介入。
  • concurrency=2:同一时间最多两个 subagent 并行执行。设成 5 的时候,浏览器实例开得太多,资源竞争反而更耗时。

这套参数在实际运行了两周,整体成功率稳定在 98% 以上,唯一一次告警是页面本身改版导致旧 Skill 里的选择器失效。这也印证了之前说的:Skills 的维护不能一劳永逸,业务页面变了,Skill 就得跟得改。

6.4 这套架构放在企业级场景中的扩展思路

如果你看完前面的案例,觉得这套架构离自己的业务还远,不用急。我再补充一个思路——怎么把上面的系统扩展成更通用的企业级集群。

多智能体集群架构最重要的扩展方向之一是横向扩容:A2A 协议天然支持不同物理机上的 agent 通信,你可以把 Page Inspector 部署在 A 机器上,Data Analyzer 在 B 机器上,Code Fixer 在 C 机器上,只要它们能通过 AgentCard 互相发现,整个集群就和在一台机器上没什么区别。

另一个扩展点是针对业务做权限隔离。每个 subagent 只赋予完成其任务所需的最小权限。不要让数据分析员直接拿到生产数据库的写权限,也不要让代码修复员直接推 main 分支。权限隔离不仅是安全要求,也能避免 agent 在复杂逻辑下无限调工具。

还有一点我特别想强调:在多智能体集群里,日志追踪是命根子。单个 agent 出错你还能翻对话记录,5 个 agent 互相调用下来,没有统一的 trace 系统根本定位不了问题。我在项目里用的是 OpenTelemetry,把 A2A 消息和 MCP 工具调用全部做成 span 上报到 Jaeger,排查问题的时间至少缩短了一半。

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

这部分我整理了自己和其他开发者交流时最常被问到的几个问题,按问题现象、原因、排查思路、实操解决方法的顺序来写。

7.1 DeepAgents 创建 subagent 不生效或数量超限

现象:你在代码里设了max_subagents=3,但实际运行中 agent 还是只用了 1 个。或者反过来,设了 3,agent 却一次性创建了 8 个,直接把上下文和工具会话数打爆。

原因分析:这个和模型对任务拆分逻辑的理解直接相关。DeepAgents 不是每次运行都创建满额 subagents,它需要模型自己“判断”任务复杂度是否值得额外创建子智能体。模型倾向于保守。

排查建议:在提示词里显式引导拆解。比如在任务描述里明确写“这个任务包含 3 个独立子任务,请分别处理”,模型会明显更愿意创建对应数量的 subagents。另外,检查你的工具列表里是否有“Task Decomposition”类工具,如果有,它的返回值会直接影响模型对复杂度的判断。

7.2 MCP Server 连接失败:connection refused或ETIMEDOUT

现象:Agent 初始化时报错,连不上本地的 MCP Server,尤其是在 Docker 化部署之后。

原因分析:八成是因为 MCP Server 运行在容器的 localhost,而 agent 在另一个容器里,localhost指向的是容器自己,不是宿主机。此外,如果你用的是 SSE 传输,CORS 策略也会造成连接被拒。

排查步骤:

  1. 先在本地命令行用curl或 Postman 直接访问 MCP Server 的健康检查端点,确认 Server 本身没问题。
  2. 检查 agent 运行的网络命名空间与 Server 是否一致。跨容器时,用宿主机的局域网 IP 代替localhost。
  3. 检查 Server 日志,确认是否有拒绝特定 Origin 的记录。SSE 模式下,大多数 MCP Server 默认只接受来自http://localhost的请求,需要显式配置允许的源。

7.3 Skills 被模型选择但效果不如预期

现象:Skill 能被正确命中,但执行出来的结果不完整,经常跳过中间某个步骤。

原因分析:我发现最常见的原因是提示词模板里的步骤写得太泛,没有强调“必须按顺序执行”。模型的默认行为是“能省则省”,凡是看起来不影响最终结果的步骤,它可能直接省略。

解决方案:在 SKILL.md 里加硬性约束。比如在步骤开头加一句“严格按照以下顺序执行,不得跳过任何步骤”,或者在每个步骤之间用变量依赖来锁住顺序(比如第二步的输入是第一步的输出)。这就从机制上避免了模型跳过关键环节。

7.4 A2A 消息丢失或乱序

现象:Agent A 向 Agent B 发了任务,Agent B 也执行完了,但 A 一直拿不到结果。或者两次消息的顺序反了。

原因分析:A2A 协议本身不保证消息顺序,如果你的底层通信是异步的,又没有做消息编号,就会出现乱序。另外,任务超时设置过短也会导致 A 认为消息丢失,实际上 B 还在跑。

排查建议:

  1. 检查 A2A 消息体里的task_id和message_id是否正确递增。
  2. 把超时时间调大到正常执行耗时的 2 倍以上,先排除超时误判。
  3. 在 Agent B 的日志里确认任务状态流转是否完整:submitted -> running -> completed。

7.5 全套排查速查表

问题核心原因快速解决方法
子智能体数量不足模型没有拆解足够子任务提示词中显式写明子任务数量
subagents 数量爆满任务拆得过细,权限混乱调低 max_subagents,合并同类任务
MCP 连接失败网络命名空间不一致或 CORS检查容器网络,配置允许 Origin
Skill 执行跳步提示词约束不足添加依赖变量,锁定执行顺序
A2A 消息乱序异步通信无消息编号为 message_id 做严格递增
工具调用循环重复模型未理解任务已经完成在 Skill 中增加终止条件,比如“当检测到 success 标志时结束”

8. 我最后的几句体会

玩了大半年 DeepAgents、MCP、A2A、Skills 的组合,最大的感受是:这套技术栈的难点不在于单个工具的使用,而在于把它们的边界想清楚。MCP 管工具接入,A2A 管智能体通信,Skills 管行为固化,DeepAgents 管整体编排。每一层只做好自己的事,系统才能稳定。

如果你现在还在用单智能体处理复杂业务,我建议你抽一个周末,尝试把任务拆给两三个 subagent,再配一个简单的 MCP Server 和一个基础 Skill。不用追求一次到位,先跑通链路,再逐步丰富工具和技能库。等这套链路跑顺了,你会跟我一样,很难再退回单体 agent 的“刀耕火种”时代。

最后再分享一个小技巧:多智能体集群跑起来之后,发现无论是 MCP 还是 A2A,它们的调试最好都保留在一个统一的可视化页面里。我自己用的是 LangSmith 搭配 Jaeger,把每一次工具调用、每一条 A2A 消息都记录下来。项目上线前多花半天做链路追踪,后期排查问题会省下大把时间。踩过坑之后你会明白,可观测性才是多智能体生产环境里最容易忽略、也最影响体验的一环。

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

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

立即咨询