1. 为什么我开始搭多智能体集群:单Agent的瓶颈
前几天帮团队把一个内部工具站整体改版,最开始图省事,直接用单个Agent挂着十几个MCP工具从头跑到尾。结果改了首页忘了侧边栏,改完筛选逻辑回头又碰坏了登录态,Agent自己都晕了,上下文越滚越长,最后直接开始胡言乱语,把不相关的接口参数往代码里塞。那一下午我净在那儿当“救火队员”,帮它擦屁股。
后来我把思路换了:不再让一个Agent包办所有事,而是用DeepAgents搭了一个多智能体集群,让一个主Agent负责拆任务和统筹,几个子Agent分别管页面开发、接口联调、安全自检,Agent之间用A2A协议互相派活,底层工具统一走MCP协议接入,每个子Agent的固定流程和判断标准则沉淀成Skills。这一套跑通之后,整个改版流程顺畅了不少,单个Agent乱窜的问题基本绝迹。
这篇就把我这几天折腾的架构设计、实际配置、运行结果和踩过的坑一起放出来。如果你是做AI应用开发、在评估多Agent框架选型,或者已经被“Agent乱改代码”逼疯过,这篇文章应该能帮你少走不少弯路。
先说清楚这套栈里几个东西的分工,后面会逐个展开:
| 组件 | 角色 | 类比 |
|---|---|---|
| DeepAgents | 多智能体的组织框架 | 公司的管理架构,谁是主管、谁是干活的人 |
| MCP | Agent调用外部工具的统一协议 | 员工的双手,通过标准接口操作各类工具 |
| Skills | 可复用的专业知识与流程包 | 员工经过训练后沉淀的职业技能 |
| A2A | 智能体与智能体之间的通信协议 | 跨部门协作时使用的统一沟通语言 |
单Agent不是不能用,它的定位是“个人助手”:任务边界清楚、上下文可控,一个Agent配几个工具完全够用。但一旦任务横跨多个专业领域,牵扯到多轮工具调用、分步验收、并行执行,你就会发现单Agent的上下文窗口是硬瓶颈,注意力会被稀释,改前面的忘了后面的。多智能体集群的价值不在于“看起来高大上”,而在于把一个大任务拆成几个子任务,每个Agent只维护自己那一小块上下文和工具集,主Agent负责收敛结果。
2. DeepAgents:先把组织架构搭起来
DeepAgents是LangChain生态里的多智能体框架,和那些云端SaaS型Agent产品最大的区别是:它可以本地部署、可以编程式定义子代理、可以用LangGraph控制整个执行流程。也就是说,它不只是一个能聊天的Agent,而是一个你能亲手编排的Agent集群底座。
2.1 deep_agent与subagents的职责边界
DeepAgents的核心模型很朴素:一个deep_agent作为顶层协调者,下面挂若干subagents。每个子代理都有自己的职责、系统提示词和专属工具集。子代理处理不了的事情会向主代理报告,主代理再决定是换一种方式重新指派,还是调整任务描述后再次下发。
我实际用下来,最关键的设计决策是:主代理不要碰具体工具。这是很容易犯的错——主代理手里一堆MCP工具,看到子代理报告问题,忍不住自己上手去改。一旦主代理陷入具体执行,统筹逻辑就会让位于局部细节,整个集群就开始“群龙无首”。我搭的时候主代理只保留任务分解、任务派发、结果验收这三件事,具体写代码、跑测试、调接口全部压给子代理。
子代理的划分维度也要想清楚。我见过不少人按“功能模块”切,比如一个管登录、一个管订单,结果两个子代理同时改同一个文件,冲突不断。更好的切法是按“工作性质”切:一个管前端开发、一个管接口联调、一个管安全审计,各自产出不同产物,互不干扰。订单一侧的改动即使涉及前后端,也由主代理统一协调,而不是让多个子代理同时碰同一块代码。
2.2 和Claude Code、Manus摊开对比
网络热搜里有一条问“langchain的deepagents现在的能力咋样,与claude比差距在哪”,我最近几个项目两个都在用,直接说结论。
| 对比维度 | DeepAgents | Claude Code | Manus |
|---|---|---|---|
| 架构取向 | 编程式多Agent编排 | 单Agent+终端工具 | 内建多Agent工作台 |
| 本地可控性 | 高,可私有部署 | 中,依赖命令行工具 | 低,云端为主 |
| MCP支持 | 原生支持 | 原生支持 | 支持 |
| 可定制程度 | 高,代码级定义 | 中,Skills+配置 | 低,只开放少量配置 |
| 上手门槛 | 需要写代码 | 极低,适合开发者 | 低,适合非技术 |
差距主要在代码质量和上下文吸收上。Claude Code在改代码时对项目结构的感知明显更强,自动补全、跨文件重构、bug自修这些场景下,单Agent往往比“主代理+子代理”的集群更顺手。DeepAgents目前的短板在于:子代理拿到任务后如果描述不清晰,容易产出方向偏差比较大的结果,它对任务描述的敏感度比单Agent对话更高。换句话说,你在DeepAgents里需要花更多心思写子代理的系统提示词和任务说明,偷不了懒。
但反过来,DeepAgents的强项恰恰是Claude Code的弱项:跨任务的组织性和流程确定性。Claude Code你在一个会话里堆太多任务,它依然会陷入上下文混乱。DeepAgents因为每个子代理上下文独立,天然免疫这种“跨领域串味”的问题。所以我的选型建议是:单个任务、同一个代码库内的深度改动,用单Agent工具;跨领域、多步骤、需要分头并行的项目,用DeepAgents搭集群。
2.3 reports、客户函数与Flows的协作机制
DeepAgents里几个比较实用的协作机制值得单独说一下。
reports是子代理向主代理汇报的通道。子代理没跑完、遇到不确定情况、或者某个任务彻底失败,都会通过reports把状态传回主代理。我在配置里给reports分了等级,关键失败必须带错误码和日志摘要,普通进度报告只给一句话结论,避免主代理被细碎信息淹没。这点很重要——reports是全文本塞进主代理上下文的,说得越多,主代理的注意力越分散。
客户函数是当某个任务没有可用工具时,主代理直接调用自定义函数来处理。比如用户给一个Excel表格要求整理数据,没有现成MCP工具时,客户函数可以直接用Python处理完再返回结果。这算是一个“逃生舱”,避免为了一个小需求专门去配一个MCP服务。
Flows则是把LangGraph的状态机能力和DeepAgents结合起来,把“拆任务→派发→验收→重试→汇总”的整个流程固化成可重复执行的图。我的建议是:刚开始不要急着上Flows,先把多Agent的静态关系跑通,观察实际执行中哪一步总是卡壳,再把卡壳环节固化到Flows里。顺序反了,你会被复杂的流程图拖死。
3. MCP:给每个Agent装上统一工具总线
MCP全称Model Context Protocol,它解决的其实是三个老问题:每个Agent产品都要对接一遍不同工具的API、同一个工具在不同框架里接入方式还不一样、工具权限和安全边界难以统一管理。MCP把“模型和应用如何连接工具”这件事规范化了。
3.1 MCP的三个核心概念
MCP协议里最核心的模型是三层结构:MCP主机(Host)、MCP客户端(Client)、MCP服务端(Server)。放在DeepAgents的语境里,Host是主代理和子代理所在的运行时环境,Client是每个Agent内置的MCP连接器,各个工具(浏览器、数据库、Burp Suite、Blender这类)则通过MCP Server暴露能力。
每个MCP Server可以暴露三种能力:工具(Tools)、资源(Resources)、提示词(Prompts)。工具是“让模型执行某个动作”,资源是“给模型读取某些上下文”,提示词是“复用某段专业指令”。实际开发中我用得最多的是工具,其次是资源——比如把项目文档挂成Resource,让Agent直接读取,省得每次都在系统提示词里塞一堆背景资料。
MCP传输层有几种常见选择,我做了个对比表:
| 传输方式 | 适用场景 | 优点 | 注意点 |
|---|---|---|---|
| stdio | 本地子进程通信 | 简单、无端口冲突、权限隔离好 | 只能本地用 |
| HTTP | 远程MCP服务 | 标准统一、可跨网络 | 需要处理鉴权和超时 |
| SSE | 老式远程传输 | 服务端推送方便 | 连接管理复杂 |
| WebSocket | 网关类MCP服务 | 双向实时通信、适合长连接 | 多数要token鉴权 |
3.2 配置实例:stdio与远程端点
本地工具的MCP配置最简单,以Playwright MCP为例:
{ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }这个配置的意思是:Agent需要浏览器操作能力时,由Host拉起一个npx子进程,通过stdio和它通信。好处是权限边界清晰,子进程只做浏览器相关的事,干完了就退出,不会在系统里留常驻服务。
远程MCP服务的配置格式稍微复杂一点。很多网关类MCP服务端点都长这样:wss://xxx/mcp/?token=...,它本质是一个走WebSocket传输、带JWT认证的MCP Server。配置里需要把url和headers写好:
{ "mcpServers": { "remote-tools": { "url": "wss://example.com/mcp", "headers": { "Authorization": "Bearer 这里填你的token" } } } }关于远程MCP我有一条很实在的建议:不要把带token的完整配置直接提交进Git仓库。我见过一个团队把内网MCP网关的token写死在配置里推到了GitLab,结果token在代码里躺了三个月才换掉。正确做法是用环境变量引用:
{ "mcpServers": { "remote-tools": { "url": "wss://example.com/mcp", "headers": { "Authorization": "Bearer ${MCP_TOKEN}" } } } }3.3 实测常用的几个MCP服务
热词里频繁出现Playwright MCP、Chrome DevTools MCP、Burp Suite MCP、Blender MCP、Unity MCP,我挑三个实测体验说。
Playwright MCP是目前浏览器自动化里最稳的一个。它能打开页面、截图、读取DOM、点击、填表、甚至跑断言。对前端开发Agent来说,它是“眼睛和手”——写完代码自己开浏览器验证效果。我在前端子代理里挂上它之后,Agent可以写完一个页面马上截图自查,再根据截图反馈调整样式,这个闭环极大减少了“代码看着对、实际渲染稀碎”的情况。
Chrome DevTools MCP和Playwright MCP的定位容易混淆。前者是通过Chrome扩展桥接DevTools协议,适合调试网络请求、性能指标和执行JS;后者是完整的浏览器自动化,适合端到端操作。热词里有人问两者区别,我的理解是:要模拟用户操作流程用Playwright MCP,要做性能分析和请求级调试用Chrome DevTools MCP。
Burp Suite MCP则是安全方向比较有意思的接入。它可以把Burp Suite的拦截、扫描、重放能力暴露给Agent,让安全审计Agent直接对目标做请求级检查。需要注意的是一旦放开这个权限,Agent就有了向目标系统发包的能力,使用范围必须严格限定在授权测试环境里,子代理的系统提示词里要写清楚“只允许访问授权域名”。
3.4 MCP工具权限与安全边界
MCP接的每一个工具都是一项能力,能力越大,风险越大。我在集群里做了三条硬性约束。
第一,子代理只见自己该见的工具。前端子代理只需要Playwright和文件读写,那就只给这两个MCP Server;不要把Burp Suite的MCP也挂上去。MCP是支持按会话或按Agent做工具隔离的,这一点一定要用好。
第二,MCP服务端要限制操作范围。给Agent用数据库MCP时,我通常会提供一个只读账号,让Agent只执行SELECT,把INSERT、UPDATE、DELETE留在主代理的人工审批路径里。虽然多了一道手续,但能有效避免Agent在上下文混乱时对生产库发起意外操作。
第三,记录工具调用日志。每个MCP Server的调用情况都要有日志,出了事能回溯是哪条指令触发了哪个工具。深代理出问题的时候,没有日志排查非常痛苦,后面我专门讲。
4. Skills:把Agent的专业能力沉淀成可复用技能包
热词里有一大堆关于Skills的搜索:superpower skills、typesafe ai skills、前端开发skills、数学建模skills、安卓脱壳skills、AI漫剧常用skills……可见大家已经意识到:光有工具接口不够,Agent还得知道“这件事具体怎么做”。Skills就是用来封装这种“做事的套路”的。
4.1 Skills和MCP的关系:一个管连接,一个管能力
很多人一开始分不清Skills和MCP的差别。我用一句话概括:MCP解决的是连接问题,Skills解决的是专业方法问题。MCP告诉Agent“你有这个工具可以用”,Skills告诉Agent“碰到这类任务,你应该按这个流程来,用哪些工具,先做什么后做什么,判断标准是什么”。
举个例子,你给Agent挂了一个Burp Suite MCP,它知道可以发起扫描,但它不一定知道“做一次Web安全自检的完整流程”该是什么样。这时候写一个安全审计Skill,里面写明:先抓取目标URL的请求列表,过滤静态资源,寻找敏感接口,对登录接口做注入测试,最后输出一份风险清单。Agent读到这个Skill,才知道怎么把工具串成一条服务。
实测下来,好的Agent流程不是靠模型临场发挥,而是靠Skill把经验固化下来。模型能力再强,每次从零开始推理“怎么检查一个前端页面”,效率都很低,而且结果飘忽。Skill相当于给模型递了一份内部操作手册。
4.2 Skill的目录结构与配置
我习惯把Skill设计成一个自包含的目录,结构大概是这样的:
web-dev-skill/ ├── SKILL.md ├── scripts/ │ ├── screenshot_check.py │ └── console_error_extract.py ├── assets/ │ └── checklist.md └── requirements.txtSKILL.md是入口文件,里面有结构化描述:
--- name: web-dev-skill description: 前端页面开发与自查技能,适用于生成、修改带交互逻辑的页面。 capabilities: - 根据设计稿还原页面结构 - 使用 Playwright MCP 打开本地页面并截图验证 - 检查控制台错误与网络请求失败 workflow: 1. 解读需求并输出页面结构清单 2. 生成代码文件 3. 启动本地静态服务 4. 调用 Playwright MCP 打开页面并截图 5. 根据截图反馈调整样式与交互 --- # 前端开发Skill 详细的工作标准和注意事项写在这里。这里有个细节:description字段一定要写好。模型判断什么时候该加载这个Skill,主要靠description的语义匹配,写得太含糊,Agent就不知道什么时候该用。我吃过一次亏,把description写成“前端页面开发”,结果该Skill在各类与前端无关的任务里也被模型尝试加载。后来改成“前端页面开发与自查,适用于生成或修改带交互逻辑的页面”,匹配精度明显提升。
4.3 手动安装GitHub上的Skills
热词里有“claude code怎么手动装github上的skills”,这个步骤其实很通用,基本适用于所有支持Skills的Agent环境:
- 进入项目目录或用户配置目录下的skills文件夹(常见位置是
.claude/skills或~/.claude/skills) git clone目标Skill仓库,注意看仓库用的是单目录结构还是多Skill聚合仓库,聚合仓库要找到对应子目录再复制- 检查SKILL.md文件是否完整,frontmatter里的name和description是否规范
- 重启Agent会话,在交互里说一个触发该Skill的任务,观察模型是否加载它
- 没有生效的话,检查目录名是否和name字段一致,路径里有没有多余嵌套
不建议在没看代码的情况下直接跑第三方Skills。Skill本质上是文本指令加脚本,里面可能混着不安全的操作。我装任何第三方Skill都先打开SKILL.md通读一遍,再看scripts目录里的脚本干了什么。有一次我装一个“效率增强”Skill,脚本里居然带了一段从远程URL拉代码执行的逻辑,直接放弃。这年头GitHub上AI相关仓库鱼龙混杂,小心为上。
4.4 好Skills从哪里找
实测比较好用的几个渠道先说结论:GitHub上anthropics官方收录的skills仓库、typesafe出的ai-skills项目、社区常用的superpower skills、以及各类MCP生态附带的标准能力包。搜索的时候瞄准“awesome skills”“agents skills”这类关键词,比自己瞎造轮子省事。
数学建模方向的Skills也比较典型。这类Skill通常内嵌了三段内容:建模思路启发(给几种常见模型的方向)、数据探索流程(缺失值、分布、相关性)、论文输出规范(图表命名、公式排版要求)。我拿它生成过一份完整的数据分析报告,效果比裸模型直接写规范得多。它的本质是用文本把“建模老手的做事顺序”固化了下来,Agent照着走,结果就不会跑偏。
用到后面,你的Skills库会越来越庞杂。建议团队内部统一维护一个Skills仓库,所有Skill走Merge Request更新,SKILL.md里写清版本号和适用边界。我踩过的坑是:两个Skill同时定义了某个都叫“page_check”的脚本,Agent偶尔会加载错版本。后来统一了命名空间前缀和版本号字段,这个问题就消失了。
5. A2A:让Agent之间真正对话
MCP解决了Agent与工具之间的通信,但Agent之间的通信依旧是各说各话。A2A(Agent-to-Agent)协议就是用来统一这种“Agent对Agent”的通信格式。它解决的是多智能体中最容易出乱子的部分:任务怎么派发、进度怎么同步、结果怎么回传。
5.1 A2A与MCP的本质区别
MCP是垂直方向,Agent向下连工具;A2A是水平方向,Agent与Agent互发消息。热词里经常有人混淆这两个概念,其实它们的分工很明确:
| 维度 | MCP | A2A |
|---|---|---|
| 通信方向 | Agent → 工具 | Agent → Agent |
| 核心目标 | 统一工具接入标准 | 统一智能体协作标准 |
| 关系 | 指挥与被指挥 | 对等协作 |
| 典型传递内容 | 工具调用与结果 | 任务、消息、工件 |
一个多智能体系统里,MCP和A2A往往是同时存在的。子代理要调用工具时走MCP,子代理向主代理汇报或相互派活时走A2A。二者不冲突,而是分别解决不同层面的通信。
5.2 A2A的核心对象:Agent Card、Task、Message
A2A协议里几个关键概念我简单捋一下。
Agent Card相当于每个Agent的“简历”,写着这个Agent能做什么、擅长什么、通过什么端点通信。主代理拿到其他子代理的Agent Card才能知道该把什么任务派给谁。我搭集群时给每个子代理单独写了一版Agent Card,描述写得尽量具体,比如“frontend_agent:负责前端页面生成与修改,可调用浏览器截图工具,产出HTML/CSS/JS文件”。
Task是Agent之间传递的任务单位,生命周期一般有submitted、working、input-required、completed等状态。子代理接到Task后,会异步跑,完成后把状态更新为completed,附带结果。主代理不需要一直等,轮询或者靠回调都行,这比同步调用更适合耗时长的子任务。
Message是实际交流内容的载体,里面分成多个part,可以是纯文本,也可以是结构化数据。需要传文件时,最常见的做法不是把文件塞进消息体,而是在Message里放一个引用路径或Artifact的地址,让接收方按需去取。这个细节很重要,后面坑里细说。
5.3 三种常见的多Agent编排模式
实测下来,多Agent集群的编排模式大致有三种,不同场景选型差别很大。
主管-下属模式最常用,也最符合人的直觉。deep_agent作为主管,给子代理派Task,子代理只和自己的直属主管通信,子代理之间不直接对话。这种模式的好处是脉络清晰,问题容易定位;坏处是主管容易成为瓶颈,所有信息都要先汇到主管那里。适合任务边界分明、子代理数量不超过四五个的场景。
议程驱动模式是另一种玩法。所有子代理共享一份“议程清单”,谁有空谁认领任务,完成一个就更新议程。这种方式并行度很高,但需要设计好冲突规避——比如两个Agent不能同时改同一个文件,我会用文件锁或任务状态字段来做互斥。适合任务天然可并行的场景,比如数据采集、批量内容生成。
事件驱动模式相对进阶。Agent之间不显式派发任务,而是监听消息总线,收到相关事件就自动触发动作。比如安全Agent监听“代码文件已修改”的事件,一旦发现有文件变更就自动跑一遍安全检查。适合做“流水线式”的持续协作,但我建议先搭出前两种模式再碰事件驱动,直接上事件总线容易变成“谁都在响应、谁都没干完”的灾难。
5.4 一次真实的A2A协作流程
我这边有个实际案例:主代理收到用户需求“生成一个带登录功能的页面”。
主代理把任务拆成两条:一条Task派给frontend_agent,内容为“生成登录页HTML/CSS/JS,完成后用Playwright截图自检”;一条Task派给safety_agent,内容为“等frontend_agent交付代码后,检查登录接口是否存在常见注入风险”。两条Task通过A2A异步发出。
frontend_agent先收到Task,进入working状态,生成代码,调用本地MCP工具启动静态服务,再用Playwright MCP截图,确认页面正常,然后把代码路径作为Artifact回传给主代理。主代理更新Task状态,又触发safety_agent的Task开始执行。安全Agent完成后,把报告作为Artifact回传。主代理把两份Artifact汇总成最终交付。
这个流程用到的不是复杂的协议细节,而是把“谁负责什么、完成后通知谁、结果传到哪里”这三件事定清楚。A2A的价值在于标准化了这套流程,不换Agent框架就得重新适配一遍。
6. 全流程实战:一个三Agent协作案例
前面讲的都是组件,这一节把它们串起来,给一个完整可参考的实战案例。
6.1 场景设计
假设任务:做一个“活动报名页面”,包含表单、列表页、基础安全自检。要求Agent集群自己开发、自己验证、自己出报告。
这套任务如果交给单Agent,上下文里要同时装:需求描述、HTML/CSS/JS规范、Browser工具用法、安全检测标准、报告格式……上下文很容易爆。我拆成三个Agent,各管一摊:
- deep_agent(主代理):拆任务、派发、汇总
- frontend_agent(子代理):写页面,用Playwright MCP自查
- security_agent(子代理):等代码交付后做安全自检,用Burp Suite MCP做请求级检查
6.2 架构与配置文件
主代理的配置里只定义两个子代理和A2A的通信端点,不挂任何具体MCP工具:
from langchain_deepagents import create_deep_agent, create_sub_agent frontend_agent = create_sub_agent( name="frontend_agent", system_prompt="你负责前端页面生成与修改。", tools=[playwright_mcp_tool], mcp_servers=[local_static_server] ) security_agent = create_sub_agent( name="security_agent", system_prompt="你负责页面安全自检,只允许检查授权域名。", tools=[burp_mcp_tool] ) deep_agent = create_deep_agent( name="deep_agent", system_prompt="你负责任务拆解与结果汇总。", subagents=[frontend_agent, security_agent] )注意这里子代理的system_prompt写得都很短。长提示词我建议放到Skill里,而不是堆在Agent定义里——Agent定义里的提示词负责“身份定位”,Skill负责“操作细节”,分开管理更清爽。
Skills挂载方面,frontend_agent加载web-dev-skill,security_agent加载web-security-skill。这样每个子代理启动时只读自己相关的Skill,不会互相干扰。
6.3 运行流程拆解
用户提交需求后,deep_agent先做一轮任务拆解,生成两个Task:
- Task A给frontend_agent:“生成报名页面,包含姓名、电话、邮箱字段,提交按钮有基础校验,完成后用Playwright打开本地服务截图自查。”
- Task B给security_agent:“等待Task A交付后,检查页面中是否存在敏感表单校验缺失与接口暴露风险。”
Task A发出后,frontend_agent开始写代码。代码写到本地文件,然后启动静态服务,调用Playwright MCP打开页面,截图、读取Console错误、检查是否有请求失败。如果截图显示样式有问题,它自己再调整,再截图,直到通过。最终把代码目录和自检截图作为Artifact回传。
主代理收到Task A的completed消息后,把Artifact信息转发给Task B。security_agent拿到页面地址,先用Burp Suite MCP发起请求级检查,看表单提交接口是否有明显校验缺失,再看敏感路径是否可被未授权访问。检查完出一份风险清单,如果有问题就把问题描述回给主代理。
主代理判断:如果安全问题影响上线,就发一个Task给frontend_agent让ta修;如果问题轻微,就直接记录到最终报告。所有结果汇总后,输出一份交付报告:页面代码路径、自查截图、安全检查结论、遗留风险列表。
6.4 运行结果与调优
这套流程第一次完整跑下来,大概花了四十分钟。页面本身讲实话一般般,但胜在流程完整——不是代码生成完就拉倒,而是有验证、有安全审计、有修正。后面我又调了一轮,修改方向集中在三处:
一是frontend_agent的Skill里加入了“手机号校验规则”的明确要求,不然它默认只校验非空。二是security_agent的Skill里加入了“只检查表单提交接口,不扫描无关路径”的范围限制,不然它会拿着Burp对整站乱扫,耗时很长。三是主代理汇总报告时,增加了对Artifact的强制列举,否则它偶尔会漏掉安全报告。
这三处调优让我体会到一个点:多Agent集群的迭代重点不是改模型,而是改Skill里的工作标准和边界约束。模型能力是底座,Skill才是决定输出质量的上限。
7. 实战场最坑的六个地方
7.1 上下文窗口还是会被撑爆,但要学会隔离
很多人以为多Agent就不会爆上下文,其实照样会,只是爆的位置变了。主代理如果被设计成“所有子代理的所有进度都要实时同步给它”,它的上下文会迅速膨胀。我的解决办法是分级汇报:子代理执行过程中只上报状态变更和关键异常,不把中间过程的日志全量传回;只有最终结果和需要主代理决策的问题才完整上报。这相当于给主代理做了一轮上下文压缩。
7.2 工具回调死循环
MCP工具返回的结果会再次进入Agent的推理循环,有些Agent看到工具返回的信息,又会触发同一个工具,形成死循环。我最惨的一次,前端Agent截图后发现页面字体加载失败,就开始反复截图定位问题,截了四十多张图停不下来。最后在Skill里加了硬性规定:“截图只允许三张,第一张全局、第二张检查目标区域、第三张验证修改后效果,三张不足以下结论时升级给主代理。”加了这条之后,工具调用的收敛性好多了。
7.3 环境变量与密钥泄露
多Agent集群里每个子代理都可能需要访问不同服务的密钥,配置一多,管理就乱了。我的原则是:密钥只通过环境变量注入,绝不写进Skill或者Agent的system_prompt。主代理分发任务时,也不会在Task消息里携带任何密钥,子代理需要认证时自己从环境变量里读。这样即使task日志泄露,攻击者也拿不到有效凭证。
7.4 消息体过大
A2A消息里直接塞大文件是个隐形陷阱。一开始我图省事,让子代理把截图base64之后塞进Message里回传,结果主代理的上下文一下多了几百KB,推理速度肉眼可见变慢。后来所有二进制内容都走Artifact引用:子代理把截图存到共享目录,Message里只传路径。文件读取由主代理按需进行。这个改动当时就让我意识到,多Agent环境下“消息里只传元数据、不传实体”是必须遵守的纪律。
7.5 Skills命名冲突与加载错乱
当Skills库到了一定规模,很容易出现两个Skill的name字段重复,或者description写得太宽泛导致模型加载错。我的兜底做法是:每个Skill的name加团队前缀,比如团队名加内部分类号;description里明确写适用范围和排除范围。比如前端Skill的description末尾加一句“不适用于移动端页面,移动端请使用mobile-dev-skill”。模型匹配description时会因为这句排除规则少走很多弯路。
7.6 诊断问题没有日志链路
多Agent系统一旦出错,排查难度比单Agent大得多——因为问题可能出在子代理的推理、MCP工具的执行、A2A消息的传递、Skill的加载任意一个环节。我在项目一开始就养成了“每一条A2A消息都写日志、每一个MCP工具调用都记录参数与耗时”的习惯。出问题先看链路:Task发出去了没有、子代理接收后卡在哪一步、工具返回了什么、结果回传了没有。没有这层日志,我只能对着屏幕上Agent的自言自语乱猜。实践下来,绝大多数故障都能在日志链路的前三个节点里定位到。
8. 收尾:一次成功搭建后的个人体会
这套DeepAgents + MCP + A2A + Skills的组合跑通之后,我的一个很深感触是:多智能体集群的真正难点不在技术,而在“分工设计”。工具链再全,Protocol再标准,没有一个合理的主代理和子代理职责划分,集群依然会乱成一锅粥。
分享一个最后的小建议:如果要从零开始搭,先别追求大而全。用一个最简单的主代理加一个子代理配一条MCP工具,跑通一次“拆任务、派活、干活、汇报、汇总”的最小闭环。这个闭环一旦通了,再逐步加第二个子代理、挂第二个MCP服务、沉淀第一版Skill。我见过太多人一上来就想一步到位,结果三四个Agent同时出错,连问题出在哪都无从查起。先跑最小闭环,再逐步扩充——这套路在别处是老生常谈,但在多智能体系统上比什么都管用。