说实话,过去半年我把市面上的多智能体方案几乎都试了一遍,踩坑无数之后,最后收敛到一套组合:DeepAgents做编排、MCP接工具、A2A做智能体间的通信、Skills沉淀可复用的干活流程。这套架构能解决的真实痛点只有一个——让多个智能体像一支成熟团队一样协作,而不是各干各的、互相干扰。这篇文章就是这次超级多智能体全流程实战的完整复盘,从环境搭建到协议细节,从Skills编写到常见坑位,按21章的实操路线给你捋一遍。不管你是刚开始接触多智能体架构的学习者,还是已经在自研框架的技术负责人,都值得花二十分钟读一遍,尤其是我踩过的那几个坑,几乎每一条都能帮你省下半天调试时间。
项目和代码本身我已经整理成私有仓库,但这篇文章里的思路、配置片段、常见问题排查表,完全可以脱离我的具体项目独立使用。你不需要先跑通我的代码,按顺序读下去,在每个环节对照自己的工程环境做调整,就能搭出一套画像完整的多智能体系统。
1. 项目整体设计拆解:四个组件各司其职
1.1 为什么一定要用多智能体架构
先想一个问题:你写一个单智能体应用,把需求、工具、知识库全塞给一个大模型,让它一口气完成任务,不是更简单吗?
在很多场景里确实如此。但一旦任务变成“跨系统、多角色、长链路”,单一智能体会暴露三个硬伤:上下文太长导致前面做的决策被后面忽略;工具调用失败后不知道找谁补位;业务方要求拆分权限时,一个Agent没法做到“不同的角色看到不同的能力和数据边界”。
多智能体架构真正解决的不是“多个模型跑得更快”,而是把一个大任务拆成多个有明确职责的子任务,每个子任务由独立智能体负责,它们之间通过协议协作。这样做带来的好处很实在:每个上下文窗口只承载一个专业角色,理解更准;单个智能体挂了不会导致全链路崩溃;权限可以按角色隔离,安全审计也更清晰。
1.2 DeepAgents、MCP、A2A、Skills的职责边界
这套体系里我最常被问的一句话是:DeepAgents和MCP到底什么关系?和Skills又有什么区别?我用一个生活类比解释:
DeepAgents就像项目经理,负责拆任务、派活、盯着进度。MCP是工具箱界的标准接口协议,让项目经理能打开任意工具箱,取出扳手或螺丝刀。A2A是公司内部的对讲机频道,保证多个项目经理之间喊话不串台。Skills则是老师傅沉淀下来的作业指导书,里面写着“遇到这种接口该怎么调、这种页面该怎么搭”。
放在技术视角里,四者的边界是这样的:
- DeepAgents负责的是编排层:接收任务,规划步骤,生成子任务,调度各个子智能体,收集结果并汇总输出。
- MCP负责的是工具层:定义一套标准化方式,把外部能力(文件系统、数据库、设计工具、测试工具)暴露给智能体调用。
- A2A负责的是通信层:定义Agent之间的消息格式、任务状态流转、元数据发现,让不同框架写的Agent也能互相协作。
- Skills负责的是方法层:把“怎么把一件事做对”的提示词、示例、代码片段、校验流程组合成可复用的技能包。
很多人误以为这四个东西是并列可替换的选项,实际不是,它们是四个不同层面的基础设施。正确姿势是全部搭配使用:DeepAgents控制全局流程,流程中的每一步需要工具时走MCP,子智能体之间需要同步进度时走A2A,而每一步具体怎么执行则从Skills仓库里检索对应技能。
1.3 同类框架选型:为什么我选了DeepAgents
在确定DeepAgents之前,我把CrewAI、AutoGen、LangGraph、AgentScope 2.0都做过一轮验证。CrewAI角色扮演很爽,但任务拆分粒度不够细,复杂流程容易卡在循环里。AutoGen的对话式多Agent很有意思,可靠性文档不友好,长期运行维护成本高。LangGraph胜在状态机可控,但编码量大,适合有专门团队的场景。
DeepAgents最突出的特点是它的Harness机制,我理解它更像一个可编程的“管理者大脑”,对任务树的支持非常清晰,子任务之间可以并行、串行、条件分支,而且自带技能检索接口。实际用下来,它对Skills的召回率明显高于我当时用LangGraph手搓的方案,这对后续搭建大量业务技能非常关键。
2. 环境准备与MCP生态接入
2.1 部署架构:Host、Client、Server三层模型
我记得自己第一次接触MCP文档时,看到Host、Client、Server三个词晕了半天。后来发现用“宿主应用、内嵌客户端、外部工具服务”来理解就通透了。
Host是运行大模型应用的主进程,比如Claude Desktop、IDE插件或你现在写的Python服务。Client是Host内部维持连接的一个模块,遵循MCP协议和Server通信。Server则是独立的工具进程或远端服务,它负责把真实能力暴露出去,比如读写数据库、操作浏览器、调用设计软件。
我这里用的结构是:DeepAgents运行在Python服务里,通过MCP Client连接若干MCP Server。其中一个Server以子进程方式启动(走stdio),比如文件系统操作;另一个Server部署在一台单独机器上(走HTTP+SSE),比如Figma MCP。这样本地工具和远程工具都能统一纳入同一个框架。
配置上,我给每个MCP Server分了独立的命名空间,避免工具名冲突。举个实际例子:文件系统Server有read_file,Figma Server也有类似语义的方法,如果不做命名隔离,模型一旦混淆就会反复失败。我的做法是在DeepAgents的工具注册表里加上命名空间的prefix,比如common_fs_read、figma_read_file,模型在planning阶段就会更精确地选择工具。
2.2 快速配置一个MCP Server
最简单的方式是直接用FastMCP库。我建议至少掌握Python版FastMCP,因为它写工具函数就像写普通Python函数一样,加一个装饰器就暴露成MCP工具。下面是一个真实可跑的最小示例:
from fastmcp import FastMCP mcp = FastMCP("data_toolkit") @mcp.tool def query_user_metric(metric_name: str, days: int = 30) -> dict: """查询用户指标,支持pv、uv、retention等维度""" # 模拟查询,实际项目里这里对应BI数据库 mock_data = { "pv": 102400, "uv": 8600, "retention": 0.38 } return {"metric": metric_name, "days": days, "value": mock_data.get(metric_name, 0)} if __name__ == "__main__": mcp.run(transport="stdio")这个Server启动后,你可以拿MCP官方提供的调试客户端去验证一下,也可以直接在自己的Agent里连接。我一般先用mcp-inspector这个可视化工具测试,确认工具能正常返回结果,再接入项目。这个小习惯帮我省去了很多“到底是我代码问题还是模型调用问题”的排查时间。
如果你需要远程暴露服务,把最后一行的transport改成streamable-http,并在服务前加一层鉴权就行。这里要注意:公网开放时务必校验鉴权头,MCP本身只负责协议,不负责传输安全。
2.3 热门MCP Server盘点与选择建议
我盘点一下这轮实战中用过、以及社区里讨论热度最高的几类MCP Server,它们分别覆盖不同业务场景:
- Figma MCP:把设计稿信息拉取进Agent,适合做设计转代码,能直接读取图层结构、导出SVG资源,是前端智能化流水线里最实用的一环。
- 蓝湖MCP:国内团队常用,主要拉取蓝湖原型标注和切图,跟Figma MCP定位相似但更接国内设计协作的地气。
- Yakit MCP与BurpSuite MCP:这俩都是安全测试场景的,把扫描器能力暴露给Agent,能让模型自动编排漏扫步骤。
- Blender MCP:为3D建模场景准备的,模型可以通过MCP控制Blender生成或修改网格,适合做AIGC三维资产生产。
- NXOpen MCP:工业软件NX的二次开发接口,封装后Agent能直接驱动CAD建模,偏智能制造领域。
- 文件系统和数据库类:最普适的基础工具,几乎所有建树都需要,我建议在自己Base环境里常备。
选型建议只有一个:不是MCP Server越多越好,每多接一个Server,模型做工具选择的难度就上升一截。我见过有人一次性接五十个工具,结果模型光选工具就占用大量token,最后的输出质量反而下降。第一版只接三个必要Server,跑通后再逐步增加。
2.4 MCP工具和Skills到底怎么区分
这是很多人的疑惑点,包括我自己早期也有误区。简单说:MCP里的“工具”是一个个原子操作,比如读取文件、发送请求、查询数据库;而Skills是一个完成某类任务的完整方法论,里面可能包含多个步骤,也可以调用多个MCP工具。
我举个例子。你写一个“发布公众号文章”的Skill,这个Skill里应该包含:生成标题、写正文、排版、配图、调用发布接口。其中排版和配图可能各自调用不同的MCP工具。换句话说,Skills是更高层的抽象,它包装了流程、提示词和工具调用序列;MCP工具则是底层能力的封装。
在DeepAgents里,我会把Skills存储在独立的技能目录中,每个技能有一个描述文件,里面注明触发条件和使用步骤,这样模型在规划阶段就能判断“当前任务应该加载哪个技能包”。这个设计让系统在新增业务能力时,不需要改Agent的代码,只要新增一个Skill目录即可。
3. 核心实现:手写Skills并接入DeepAgents
3.1 Skills的三种形态
Skills不是一种严格规范的文件格式,所以在不同框架里的形态略有差异,但归纳起来通常有三种:
第一种是纯提示词型,一个Markdown文件,描述任务背景、步骤、注意点和示例。这种适合复杂决策类任务,比如“数学建模竞赛题目分析”,它指导模型如何理解问题、拆解假设、选择模型。
第二种是代码型,Skill里附带可执行的Python或Shell脚本,模型识别到需要执行脚本时,会调用代码解释器或本地运行环境去跑。这类适合数据处理、批量生成、格式转换等确定性操作。
第三种是复合型,提示词+脚本+MCP工具调用的组合,也是我在项目中用最多的一种。比如“前端开发Skill”里既包含页面拆分的提示词,又包含调用Figma MCP读取设计稿的代码片段,还包含最后用代码生成工具产出React组件的步骤。
我强烈建议你在设计Skills时,优先考虑第三种形态,因为它让Agent的“思考”和“动作”都沉淀在技能包里,而不是散落在任务描述里。
3.2 动手写一个“数据报表生成”Skill
我拿一个实际用过的Skill来拆解,目标是根据业务数据自动生成日报。
先建目录结构:
skills/ daily_report/ SKILL.md templates/ daily_template.md scripts/ query_data.pySKILL.md是核心,写清楚触发条件和流程。我的写法参考如下:
--- name: daily_report description: 生成数据日报,适用于每日运营数据复盘场景 trigger: 当用户需要查看/生成日报、昨日数据、运营指标汇总时触发 dependencies: - mcp:database - mcp:file_system --- # Daily Report Skill ## 步骤 1. 通过database MCP查询指定日期范围的业务表(依次执行query_user_metric、query_order_metric)。 2. 用scripts/query_data.py做数据清洗和口径校验。 3. 读取templates/daily_template.md,将计算结果渲染进模板。 4. 通过file_system MCP输出到指定目录。 ## 注意事项 - 数据为空时不得直接写0,必须标注“无数据”并通知主Agent确认口径。 - 指标口径如果有调整,需要在报告尾部补充说明。这段描述就是Agent执行该任务的方法论。注意我的写法里明确指定了“通过database MCP取数”这一步,这样模型就不会自己瞎编数据来源。
然后是配套的查询脚本,我简化一下核心逻辑:
import json import sys from datetime import date, timedelta def main(): days = int(sys.argv[1]) if len(sys.argv) > 1 else 1 end = date.today() start = end - timedelta(days=days) result = { "start": str(start), "end": str(end), "metrics": [ {"pv": 102400, "uv": 8600, "orders": 732}, {"pv": 115030, "uv": 9100, "orders": 851} ] } print(json.dumps(result, ensure_ascii=False)) if __name__ == "__main__": main()这个脚本其实是个模拟数据版本,真实项目里你可以换成SQL查询。但重点在于:把这类“每次都要重复写的取数逻辑”沉淀成脚本,比让大模型每次现场写要稳定得多。
3.3 Skills在DeepAgents里的挂载与召回
DeepAgents原生支持从一个技能目录加载Skills,我只需要在配置里指定路径即可。下面是我常用的配置片段:
agent: name: operations_agent skill_dirs: - ./skills/daily_report - ./skills/qa_testing - ./skills/design_to_code mcp_servers: - name: database url: http://localhost:8300/mcp - name: file_system transport: stdio command: npx args: ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"]这里最值得留意的部分是skills的目录命名和description编写。DeepAgents的Harness在加载技能时,会依据description做语义对比,如果描述写得太泛,比如“处理数据”,一旦任务涉及“统计”它可能也匹配上,导致技能选择错误。我建议每个技能的description里都包含触发词、排除词,比如“日常报表”技能的排除词是“不适用于活动期间实时大屏数据”。
3.4 参数校验与错误处理的经验
模型调用技能时,经常会出现参数幻觉,比如把一个字符串类型参数填成数字,或者把枚举值写错。我在Skills脚本里统一加了入参校验,校验失败时返回给Agent的不是裸异常,而是一段友好的提示信息。
这里有个教训特别值得说:我之前写一个查询技能,没有校验日期格式,模型传了一个“上周五”这样的自然语言参数,脚本直接抛异常,Agent尝试三次都失败,整条流水线就停了。后来我在Skills的SKILL.md里加入了一行“参数格式要求:日期必须为YYYY-MM-DD格式;如果用户提供的是自然语言日期,请先转换为标准格式再调用”。加了这一行之后,成功率几乎百分之百。这说明Skills设计里,给模型“使用说明”比写更多防御性代码更管用。
另一个经验是:“多步Skills要设置中间检查点”。我的做法是在SKILL.md里明确写下“每完成一步,必须把中间结果摘要写给主Agent确认,再执行下一步”。这虽然多花一些token,但能防止整套流程跑偏后才发现,实际上是节省了重跑成本。
4. A2A协议:让智能体互相喊话
4.1 Agent Card怎么编写
A2A协议解决的核心问题是“智能体如何发现对方、如何建立会话、如何传递任务”。这个发现机制靠的就是Agent Card,它本质是一个JSON文件,放在智能体服务根路径下,别人通过这个文件知道你的Agent叫什么、能干什么、怎么调用。
我分别对照过0.3版本和1.0版本的Agent Card写法。0.3版本相对简陋,核心元数据只有name、description、url、capabilities,capabilities里主要标记是否可以流式响应和是否支持推拉模式。1.0版本在结构上做了较大调整,新增了更明确的认证信息块、细粒度的能力枚举和任务生命周期说明。
下面是一个1.0版本的Agent Card示例:
{ "name": "report_writer_agent", "description": "负责生成日报、周报等周期性业务报告,可对接运营数据平台。", "url": "https://agent.internal.example.com/a2a/report_writer", "version": "1.0.0", "authentication": { "schemes": ["bearer"], "credentials": "env:A2A_REPORT_WRITER_TOKEN" }, "capabilities": { "streaming": true, "pushNotifications": false, "taskManagement": { "supportedTaskTypes": ["generate_report", "check_data_quality"], "maxConcurrentTasks": 5 } }, "skills": [ { "id": "daily_report", "name": "日报生成", "description": "根据运营数据平台输出昨日的日报" } ] }这里有一个关键设计:skills字段在1.0版本里更受重视了,它让调用方Agent在决定是否下发任务时,就能判断对方会不会做这件事。这比先发任务再等报错要高效得多。
4.2 一次完整的A2A任务流转
我以“让报表Agent生成一份昨日数据日报,再让质检Agent检查口径”为例,走一遍完整流程。
第一步,编排Agent向report_writer_agent发送任务请求,请求体里包含taskId和Message数组,Message的content部分里带上具体需求。调用方式就是向Agent Card中的url发起HTTP POST请求。
第二步,报表Agent接收任务后返回status: working,如果它需要更多信息,会返回input-required,同时列出缺失字段。这个机制非常适合“模型自己发现需求并不完整”的场景,不需要外部硬编码校验。
第三步,报表Agent执行完成之后,把结果放在Artifact里,同时把任务状态更新为completed。编排Agent通过SSE流式接收状态变化,可以实时看到任务进度,而不是傻等一个HTTP响应超时。
第四步,编排Agent拿到日报后,再向质检Agent发起另一个任务,请求内容里附上日报原文,让质检Agent用独立的校验规则检查口径是否准确、有没有异常数据点。
这里最值得强调的一点是:A2A的任务和Message是分离的。任务有生命周期,Message只是任务过程中传递的内容。你在设计协议时一定要习惯这个思维,否则很容易把A2A理解成简单的“互相发消息”,那样就浪费了这套协议的工程价值。
4.3 多智能体协调策略:编排者模式 vs 协商者模式
在实际部署中,多智能体的协作模式一般分两类,我建议根据业务场景二选一,不要混着用。
第一类是编排者模式,也叫主管-下属模式。一个主智能体拆解任务,其余智能体只做执行,结果汇总给主智能体。这种模式适合流程清晰、步骤固定的场景,比如报表生成、批量数据处理、自动化测试。优点是可控性强,问题定位简单,缺点是主智能体容易成为瓶颈。
第二类是协商者模式,多个智能体地位平等,通过A2A协议互相提需求、协商结果。这种模式适合开放式研究、复杂决策、方案对比等场景。优点是灵活,能处理突发情况,缺点是需要设计好收敛条件,否则Agent之间会陷入无限讨论的循环。
我的建议是:第一版一律用编排者模式,等业务复杂度逼到必须用协商者模式时再升级。我们团队在一个需求分析项目中尝试过让三个Agent自由讨论,结果它们在一个技术选型上吵了六轮都没有收敛的信号,最后硬编码了一版“如果三分钟内没结果,由主Agent仲裁”的超时机制才解决问题。
4.4 关于多智能体世界模型的思考
最近社区讨论热度很高的是“能预测多智能体交互的世界模型”。我个人的理解是,这种模型尝试预判“当前智能体执行某个动作之后,其他智能体会有什么反应”,从而让编排策略更智能,而不是等A2A消息真正到达后再响应。这个方向对复杂协作系统很有价值,但目前成熟度还不高,我所知的团队都停留在实验阶段。我建议有兴趣的同学可以关注,但在生产项目里先不要依赖它,还是老老实实规则兜底。
5. 全流程实战:21章完整路线与场景落地
5.1 21章路线图是什么样的
这个项目的“21章完整版”,其实是我在设计学习路线时,把整个多智能体全流程拆成了四个阶段,正好对应21个实操环节。我整理成下面的表格,方便你对照自查:
| 阶段 | 章节范围 | 核心主题 | 交付物 |
|---|---|---|---|
| 基础认知 | 第1章至第3章 | 多智能体概念、四个组件关系、框架选型 | 架构设计文档 |
| 环境搭建 | 第4章至第7章 | LLM接入、MCP Server部署、Base Agent运行 | 可运行的Agent服务 |
| 能力构建 | 第8章至第12章 | Skills开发、A2A协议、协作模式 | 三个以上可用Skills |
| 实战落地 | 第13章至第21章 | 业务场景、性能优化、安全与部署 | 完整多智能体应用 |
这张表不是知识目录,而是按我落地项目的顺序排的。每章都对应一个能跑通的小里程碑,而不是单独讲一个知识概念。你在自建学习路线时,我也建议按“每章产出一个可运行片段”来设计,学到概念能立刻跑起来,比刷完十个小时视频再动手有效得多。
5.2 场景一:研发管理助手
第一个实战场景,我搭建的是“研发管理助手”。
需求背景是团队每天有大量重复性信息整理工作:从代码仓库提取提交记录、关联需求单号、生成发布说明、同步到内部协作平台。过去这件事靠研发手工做,耗费时间而且容易漏项。我的方案是用DeepAgents编排三个子智能体:
代码分析智能体负责连接代码仓库MCP Server,拉取当天的提交记录,解析commit message里的需求单号。测试执行智能体负责触发自动化测试,把测试结果汇总成状态标签。报告生成智能体负责调用发布说明Skill,把前两个智能体的输出合并成标准的发布报告,再通过协作平台MCP同步出去。
整个流程中,A2A协议承担的主要是任务交接。代码分析智能体把提交记录传给报告生成智能体时,不通过数据库,而是直接在A2A Message里带一个结构化JSON。这个设计让三个子智能体之间解耦得很干净,任何一个智能体都可以单独替换升级。
实际跑下来的效果是:原来需要人工二三十分钟的发布说明整理工作,Agent全流程大概三分钟以内完成,而且格式统一、没人会忘填需求单号。这不是一个很炫酷的应用,但它确实验证了“多智能体+Skill+工具”这套架构在真实办公场景的性价比。
5.3 场景二:设计稿转前端代码
第二个场景是我个人最喜欢的,也是社区热门关键词里反复出现的“前端开发Skills”和“Figma MCP”。
这个场景的需求是把Figma设计稿直接转成可运行的React页面。过去用零散工具做,经常出现“设计稿标注识别不准”的问题,转出来的页面还原度低,前端还要手工调半天。用这套多智能体体系后,我的流水线设计是这样的:
设计分析智能体通过Figma MCP读取设计稿的图层树,识别页面分区、组件类型、间距和颜色变量。架构智能体根据分析结果,对照工程里的技术规范,确定组件目录结构和状态管理方案。开发智能体加载前端开发Skill,按架构智能体输出的方案逐块生成React组件代码。
我在Skills里配置了一条重要规则:生成组件时必须参考项目现有代码风格,而不是套用通用模板。这条规则是通过在Skill里放一个代码风格示例文件实现的,Agent生成代码前先读示例,风格一致性问题基本杜绝了。
这个场景告诉我一个道理:MCP工具决定Agent能拿到什么数据,Skills决定Agent能把数据用到什么水平,两者缺一不可。只接Figma MCP但Skill里没有设计转代码的步骤规范,模型会读数据但不知道如何系统化地表达成页面。
5.4 场景三:安全测试自动化
第三个场景偏专业:用Yakit MCP和BurpSuite MCP做自动化安全测试。
我的设想是:由主智能体接收一个API域名列表,自动拆分成多个探测任务,分别下发给“接口分析智能体”和“漏洞扫描智能体”。接口分析智能体负责调用Yakit MCP做接口资产测绘和参数提取,把结果转成结构化格式;漏洞扫描智能体再根据这些结构,调用BurpSuite MCP发起针对性扫描。
这个场景的复杂度明显高于前两个,因为安全工具的告警噪声很高,Agent需要筛选“误报”和“可修复项”。我的处理方式是给扫描Skill增加了一个“结果置信度评估”步骤,让智能体对每个告警做复现验证,只有验证通过的才写入报告。这一步虽然增加运行时间,但生成的报告可信度提升了一个层级,甲方拿到报告后可以直接按优先级推进修复。
坦白说,这个场景还不适合完全无人值守,我的经验是“Agent生成测试报告、安全人员做最终复核”是最优配合。不过方向已经验证可行,后续随着A2A任务超时和重试逻辑成熟,无人值守的占比可以逐步提高。
6. 常见问题与排查实录
6.1 MCP连接不上怎么办
我遇到最多的问题是MCP Server启动失败。尤其是通过npx启动Node版server时,经常会因为网络问题拉不到依赖,表现为报错信息指向“找不到模块”。排查思路:先单独在命令行里执行一次启动命令,能跑通再接Agent。
另一个高频问题是stdio传输模式下,Agent主进程没有正确读取Server的stdout输出。我犯过一个错误:在MCP Server代码里加了print()日志做调试,结果这些日志混入协议通道,导致Agent解析JSON-RPC报错。记住,stdio模式下标准输出是协议专用通道,调试日志必须写到标准错误或单独日志文件。
我把排查要点整理成了表格:
| 现象 | 大概率原因 | 解决方式 |
|---|---|---|
| Server启动即退出 | 依赖缺失或命令路径错误 | 命令行单独运行,确认无报错 |
| 能启动但工具列表为空 | Server没有注册工具 | 检查装饰器绑定和import路径 |
| Agent能连上但调用超时 | 工具执行时间过长,超过Agent默认超时 | 调大MCP调用超时参数 |
| 调用返回“参数格式错误” | 模型生成参数和Schema不一致 | 在工具Schema里增加描述和枚举值约束 |
6.2 A2A的Agent Card校验失败
A2A通信中,调用方Agent会先拉取被调方的Agent Card,再根据Card里的url和authentication发起请求。我遇到一个奇怪的问题:两个Agent明明部署在同一套网络里,A2A请求却被拒绝。最后查出来是被调方的Agent Card里的url配置成了内网IP,而调用方Agent运行在别的网段,无法直接访问。解决方案很简单,把Agent Card里的url改成统一的服务网关域名。
随后又出现过一次鉴权失败,原因是被调方的鉴权信息要求Bearer Token,但我在环境变量里配置的Token过期了。这类问题单看日志不明显,因为A2A返回的401提示和普通HTTP 401一样。后来我给自己定了一条规则:所有A2A的报错响应统一携带一个agentErrorCode字段,排查起来清爽很多。
6.3 Skills召回不准确和上下文溢出
DeepAgents的Harness在调度Skills时依赖语义检索,描述写得不好,召回就会出现两种典型问题:召回错误技能、或者召回了技能但关键步骤被遗漏。我在1.0版本时一个大意,把“日报”和“周报”两个技能描述写得过于接近,结果每天上午的任务经常先加载周报模板,生成一份奇怪的日报。
解决办法是重写两个技能的description,明确各自的触发范围和示例口径。比如日报的description里加“仅处理单日数据,周期为昨日00:00至24:00”,周报的则加“处理过去七天数据,包含周同比”。这个修正之后,召回准确率提升明显。
上下文溢出是长链路任务的通病。我有一次让主智能体同时协调五个子智能体,每个子智能体把全量中间结果都塞回主智能体上下文,不到三轮就爆了token上限。后来我调整了策略:子智能体返回的必须是结构化摘要,最长不超过200字,需要完整个案时再由主智能体主动发起数据查询。这个改动不仅解决了溢出,还让整体响应速度提升了一个量级。
6.4 多智能体性能与成本优化
多智能体项目跑起来之后,成本问题会立刻浮出水面。我一个月内的账单有一半是被Agent的“无效重试”吃掉的。常见浪费有三类:模型工具选择错误导致工具空跑、A2A任务超时后无脑重发、Skills流程里重复调用同一个MCP查询。
针对第一类,我在工具Schema里把所有参数描述都写详细,模型选错工具的几率显著下降,token成本也低了。针对第二类,我设置了“最多重试两次,且第二次必须改变策略”的规则,纯重发同一请求只会浪费钱。针对第三类,我给子智能体增加了简单的缓存机制,同一数据窗口内的同一查询直接复用结果。
这套优化在月度账单上的效果非常直接,成本降幅接近四成。我建议每个做多智能体项目的团队,把成本监控做成一个独立Dashboard,而不只是看一眼月度账单,否则到月底看到账单时才发现异常就晚了。
7. 经验总结与扩展建议
7.1 我踩过的最值得说的三个坑
第一个坑是低估了Skills描述的维护成本。Skills体系刚搭好时,我满心以为后续只需不断新增技能就行,实际上已有的技能在业务口径调整后必须同步更新描述和示例,否则Agent就会用过时的步骤处理新问题。我们后来给每个Skill加了一个“版本日志”和“适用范围”字段,每次修改强制更新日志。
第二个坑是A2A任务超时设置得过短。早期我把报表生成任务的超时定为30秒,结果数据量大的时候频繁超时重试。后来根据实际耗时统计,把超时设置为“最大历史耗时的2倍”,再配合重试策略,任务成功率从82%升到了95%以上。
第三个坑是没有提前设计可观测性。分布式多智能体系统最大的调试难点是你无法直接看到“哪个Agent在什么时候做了哪个决策”。我后来在每个Agent服务里加了请求ID贯穿日志,并且把A2A消息流入流出都记录到结构化日志里。没有这套日志,遇到问题就只能靠猜,排查效率极低。
7.2 这套架构的扩展方向
这套体系可以继续扩展的方向非常多。比如DSH和AgentScope 2.0这类框架的演进,核心都在优化智能体间通信与任务调度的效率,你可以把已经沉淀好的Skills和MCP Server平滑迁移过去。也可以尝试把“世界模型”技术引入编排层,让主Agent在决策前先预测一下各子Agent的反应,减少无效调度。
另一个我近期在做的扩展是“多智能体博弈”方向,具体场景是模拟多个利益诉求不同的角色,在谈判或方案评估中相互博弈,最终给出一个相对均衡的决策。这套东西用DeepAgents加A2A协议实现起来非常顺手,后续有机会再单独写一篇文章。
最后再分享一个个人体会:多智能体项目的成败,不取决于模型多强,而取决于工程化细节,包括上下文管理、错误重试、技能沉淀、观测能力。框架只是把路修好,真正把车开稳的,还是你对业务的理解和不断踩坑后积累的规则。
我在实际落地中体会最深的一句话是:任何一段看似固定的流程,都值得被沉淀成一个Skill;任何一次重复的调试,都值得被固化成一条规则。多智能体系统的价值不是“自动做一次任务”,而是把人的经验、判断标准和工作流固化到系统里,让下次执行时“少走弯路”。希望这篇复盘对你搭建自己的多智能体系统有帮助,也欢迎踩坑之后来交流你的故事。