做过多智能体集群的人应该都有同感:单体Agent跑得很欢,一旦凑成集群,立刻变成"三个和尚没水喝"。DeepAgents、MCP、A2A、Skills这四个词,单独看都懂,真正把它们拧成一套能跑的多智能体集群架构,中间踩过的坑、绕过的弯路,网上能对上的完整实战记录其实很少。这篇文章就是把我自己从单体Agent升级到多智能体集群,再用MCP统一工具调用、A2A打通Agent间通信、Skills沉淀可复用能力、DeepAgents负责整体调度的全流程经验整理出来,给正在搭多智能体集群或者准备把协同开发落到实处的同学一份可以直接参考的作业。
1. 为什么单体Agent跑得欢、集群Agent总翻车
1.1 单体能力再强,也有四个天花板
先说清楚一个现实:单体Agent是有明确天花板的。我最早做自动化开发助手时,所有逻辑塞一个Agent里,刚开始确实爽,但随着任务复杂度上来,问题一个一个冒头。
第一个是上下文窗口。一个复杂任务可能涉及需求文档、多个文件、日志输出、历史对话,上下文窗口再大也有极限,塞满了模型就开始"失忆",前面的决定后面就忘了。第二个是工具泛滥。一个Agent挂十几个tool,模型做工具选择时反而会犹豫,甚至拿错工具,工具调用成功率直线下降。第三个是并行瓶颈。串行执行太慢,但单体Agent本身不具备合理的并行能力,所有事情只能排队。第四个是角色混乱。同一个Agent既要写代码又要做复盘还要管部署,"角色洁癖"根本不存在,输出风格和决策逻辑很容易互相污染。
这时候多Agent集群就是必然选择。但问题也随之而来:集群不是把N个Agent堆在一起就完事,它需要一套能让Agent们"各干各的但步调一致"的底层基础设施。
1.2 "三个和尚没水喝":集群失败的常见形态
我见过太多多Agent项目翻车,翻车形态高度一致,基本逃不出下面三类。
第一类是"通信靠粘贴"——Agent A把结果塞进对话历史,Agent B再去读上下文。看起来有协作,实际上所有信息都耦合在一段超长文本里,上下文数量级增长,很快就爆掉。第二类是"工具各自为战"——每个Agent自己挂一套工具配置,同一个数据库操作,Agent A写的连接逻辑和Agent B完全不是一套,权限也乱,出问题根本没法查。第三类是"技能不可复用"——每个Agent都用一大段prompt描述同一件事,比如"代码审查",三个Agent三套说法,改一处要改全部,维护成本爆炸。
后来我意识到,这些问题的本质不是Agent模型不够聪明,而是缺三层东西:统一的工具接入层、标准的Agent通信层、可沉淀的能力封装层。DeepAgents、MCP、A2A、Skills这四个东西,恰好分别补上了调度层、工具层、通信层、能力层。
1.3 我的整体架构选择:四层模型
我最后跑通的架构,可以简化为四层。
底层是MCP,负责把所有外部能力和每Agent能用自己的工具打通——数据库、文件系统、浏览器、代码库、API,全部统一成标准协议。往上一层是Skills,把"怎么做"沉淀成可复用的技能包,相当于给Agent装了一套标准作业手册。再往上是A2A,负责Agent与Agent之间的消息传递、任务分发和结果回执,相当于Agent们的"电话系统"。最顶层是DeepAgents,做任务拆解、路由、调度和容错,相当于整个集群的"项目经理"。
这套分层思路的核心价值在于:每一层都可以独立替换和升级,哪一层出问题,只动那一层,不会牵一发而动全身。
2. MCP把工具链做成"统一插座"
2.1 MCP到底是什么:不是硬件协议
先说一个很多人问过的概念问题:MCP到底是软件协议还是硬件协议?很多人看到MCP会联想到芯片封装里的Multi-Chip Package,容易懵。这里明确一下,AI语境下的MCP,全称是Model Context Protocol,模型上下文协议,是Anthropic牵头搞的一种纯软件协议,作用是让AI模型和外部工具、数据源之间通过统一标准交互。
打个比方,MCP之于AI应用,就像USB-C之于充电设备。以前每个工具都有自己的私有接口,AI要调不同API得写一堆适配代码;有了MCP之后,工具方只需要实现一个MCP Server,AI这边用通用的MCP Client就能接上,协议统一,适配成本大幅下降。MCP里定义了三类原语:tools——可执行的操作,resources——可读取的数据,prompts——可复用的提示模板。实际开发中tools用得最多,resources适合做数据注入,prompts适合把常用交互流程固定下来。
2.2 实际接入:从MCP Server到Client的最小闭环
我当时搭的第一套MCP,是为了让集群里的Agent能统一读写项目代码库和数据库。先写一个极简的MCP Server,用Python的FastMCP库,几行代码就能起一个可用的Server。
from fastmcp import FastMCP mcp = FastMCP("proj-knowledge") @mcp.tool() def query_project_structure(path: str) -> list: """读取项目目录结构,返回文件列表""" import os result = [] for root, dirs, files in os.walk(path): level = root.replace(path, "").count(os.sep) if level > 2: continue result.append({"dir": root, "files": files}) return result if __name__ == "__main__": mcp.run()然后在Agent侧配置MCP Client。现在主流Agent框架都支持在配置文件中声明MCP Server,我可以直接写进一个统一配置文件里,集群内共享。
{ "mcpServers": { "project-knowledge": { "command": "python", "args": ["path/to/project_knowledge_server.py"], "env": { "PROJECT_ROOT": "/workspace/demo" } } } }关键是"集群内共享"这四个字。MCP Server独立于Agent运行,Agent只是Client,这样工具层就从中每Agent各自的私有配置中抽离出来了。换工具、加权限、修Bug,只改Server侧,Agent侧不用动。
2.3 集群共享MCP时的权限分离设计
MCP统一了接入方式,但如果权限没分层,所有Agent拿到所有工具,集群会乱套。我的做法是权限按Agent角色隔离。
规划Agent只读项目结构、需求列表和任务看板;编码Agent能读代码库、写代码文件,但绝对不能动生产数据库;质检Agent能读代码、执行测试、写测试报告,但不能直接改业务代码;部署Agent只在发布阶段被临时授予部署权限,平时默认吊销。
这个权限隔离,我是在MCP Server暴露工具时做角色映射实现的。每Agent都通过同一套MCP端点连接,但认证信息里带有自己的角色声明,Server侧做工具名匹配和权限校验。比如:
AGENT_ROLE = { "coder": {"allowed": ["read_code", "write_code", "search_project"]}, "qa": {"allowed": ["read_code", "run_tests", "write_report"]}, "deployer": {"allowed": ["deploy_service", "rollback_service"]}, } def check_permission(agent_role: str, tool_name: str) -> bool: if agent_role not in AGENT_ROLE: return False return tool_name in AGENT_ROLE[agent_role]另外提醒一句,MCP Server要么不做鉴权,一旦做就要认真做,别把"验证角色名"这种逻辑写在客户端侧,客户端是Agent,Agent的行为不可控,必须服务端兜底。
2.4 MCP的Resource/Tool/Prompt分工和几个典型的坑
MCP里tools、resources、prompts三个原语容易混。我现在的使用口径是:要"AI主动执行的动作"用tools,比如执行SQL、提交文件;要"往上下文里自动注入的静态数据"用resources,比如启动时自动读入项目README;要"把一段高频使用的指令模板固化"用prompts。初始我All in tools,后来发现很多场景其实更适合做resource,比如每个Agent启动时自动加载任务上下文,如果用tool,Agent还得记得去调,用resource就是自动注满。
再说几个在实践中踩过的坑,都是真实教训。
第一,不要把敏感数据塞进MCP响应。MCP Server返回的内容会全部进入模型上下文,日志、密钥、内部IP一旦被返回,就等于暴露给了模型和后续的日志系统。Server侧一定要做字段过滤。第二,外部工具API升级会导致MCP Server悄悄失效,但不是报错,而是返回空列表或者奇怪的字段。我当时对接一个第三方项目管理工具的MCP,对方改了一个返回字段名,Agent写任务日志时连续两天写不进去,查到最后才发现是字段映射变了。所以MCP Server侧要做数据结构校验,宁可报错,不要静默吞掉异常。第三,Agent在调用MCP工具时的工具描述一定要写具体,带清晰的参数示例。同一个tools,描述是"query_database(sql)"和"查询员工表的离职人数,参数sql格式:SELECT count(*) FROM users WHERE status = 'resigned'",后者的成功率要高得多。Agent不是人,它就是靠描述猜意图的。
3. A2A让Agent之间能"说人话"
3.1 A2A要解决的问题:MCP管Agent和工具,A2A管Agent和Agent
MCP解决的是Agent与外部工具的关系,但Agent之间的关系它管不了。A2A,也就是Agent2Agent协议,专门负责Agent之间的通信。
我的理解是:MCP像Agent的"手",负责干活;A2A像Agent的"嘴",负责沟通。一只手不需要和另一只手对话,但两个Agent之间要协作,就得有共同语言。A2A的模型和MCP不太一样,它更偏向传统服务间通信,把每个Agent当作一个网络端点,通过交换Agent Card来发现对方能力,通过发送任务、消息、人工介入请求来完成协作。
有个常见误区是:A2A是不是就替代了MCP?不是。它们是互补的,同层解决不同的连接问题。我搭的集群里,Agent和工具走MCP,Agent和Agent走A2A,两个协议各自独立,也经常在同一进程中共存。
3.2 Agent Card和消息模型:发现、任务、回执的流转
A2A最核心的三个概念是Agent Card、Task和Message。
Agent Card相当于每Agent对外发布的"名片",是一个JSON文档,声明了Agent的标识、支持的技能、通信端点、认证方式,还有一个很关键的属性集表示它需要人类介入还是全自动。调度器想找人干活,先查Agent Card,了解谁会干什么,再决定发给谁。
Task是A2A里的一次工作单元,有状态:pending、working、completed、failed、input-required等。任务创建后,Agent之间通过Message交换中间结果和元信息,Message可以是文本、文件引用、结构化数据。最终结果以Artifact的形式挂在Task上。
实际跑通后你会发现,这套模型和人类的项目协作非常像:Task是任务单,Message是过程中的沟通记录,Artifact是交付物,Agent Card是简历。
3.3 用A2A实现"需求Agent转给编码Agent"
我给一个最简单的A2A协作场景做个拆解,场景是:需求Agent分析完需求文档后,需要把开发任务转给编码Agent。
第一步,需求Agent先通过Agent Card发现编码Agent的能力,确认它支持"implement_feature"这个技能。第二步,需求Agent创建一个Task,task_id标识为T-2025-0214-001,放置到编码Agent的端点,并将需求文档的引用作为Message附加进去。第三步,编码Agent接受任务,将Task状态置为working,同时回一条Message"已收到需求,开始实现,预计XX分钟"。第四步,编码Agent实现完成后,将Task状态置为completed,并提交一个包含代码文件路径、测试结果、变更说明的Artifact。
这里最容易被忽略的是Task状态回执。如果发完任务不管状态,调度层就无法知道任务到底结局如何,要么重复派活,要么永远悬空。所以我在所有Agent端点的消息处理逻辑里强制要求:每次处理完一轮,都回一状态消息并附带上下文摘要。
3.4 真实踩坑:同步调用死锁、超时、重复执行
A2A开发中最折磨我的三个坑,值得单独拿出来说。
一个是同步调用死锁。最初我把Agent间通信写成同步HTTP调用:Agent A等Agent B返回,Agent B又在等Agent A返回,直接绞死。后来全部改成异步消息+轮询Task状态,只有短耗时任务才允许同步等待,凡是跨Agent的长任务,一律异步。
一个是超时设计。不同Agent的处理时长完全不可控,规划Agent可能30秒就返回,编码Agent可能要跑15分钟。我在A2A消息链路里为不同任务类型配置了不同的超时上限,并在超时之后触发"重试一次,再失败则上报调度层"的分支逻辑。没有这套超时策略之前,我见过调度层傻等一个已经死掉的Agent等了20分钟。
还有一个是重复执行。A2A没有原生的消息去重机制,网络超时重发、Agent重启、调度层重试都可能导致同一个Task被重复执行。我在每Agent侧加了task_id幂等表,已经处理过的task_id直接返回旧结果,不重新执行。这个机制看着简单,如果没有,后果很可怕:编码Agent把同一个功能重复提交了三次,代码仓库里出现三份不同实现的同名文件。
4. Skills把流程沉淀成可复用资产
4.1 Skills和普通Prompt的差别:可版本化、有前置条件、有验收标准
回头看我最初的多Agent集群,每个Agent都背着好几千字的prompt,里面包含角色设定、工作流程、工具调用范例、输出规范。这些东西刚写时觉得挺完善,但真用起来就发现问题:三个Agent里的"代码审查流程"是三个人写的三个版本,细节不一样,维护时根本找不到"正版"在哪里。
Skills解决的就是这个问题。它把能力封装成结构化、可版本化、可检索的单元。一个Skill不仅能描述目标,还包含前置条件、具体步骤、执行时机、输出物、验收标准。它更像一本操作手册,而不是一段口号。
我自己的定义是:Skill是"能被调度器自动匹配、能被Agent自动执行的最小能力单元"。普通Prompt是一次性的对话配方,Skill是可装卸的能力插件。
4.2 一个SKILL.md的实际模板和我的写法习惯
我接触的Skills实践,很多是从SKILL.md这种格式出发的。我的写法,用Markdown加YAML frontmatter,把元信息和正文分开。
--- name: code-reviewer description: 对指定代码文件进行静态审查,输出问题清单和严重级别。适用于合入前审查,需要代码可访问且至少能通过语法解析。 version: 1.2.0 requires: - mcp.project-knowledge - mcp.code-search triggers: - 收到PR合入前审查请求 - 检测到新提交且变更量超过100行 steps: - 读取变更文件列表中的全部文件 - 逐个文件做静态扫描,重点检查:空指针、资源泄漏、越界访问、安全性 - 对照项目编码规范检查命名和结构 - 输出审查报告,按阻塞级/建议级分类 acceptance: - 所有阻塞级问题都有文件行号定位 - 报告包含问题描述、影响面、建议修改方式 artifacts: - report_path: /output/review/{task_id}.md --- # 执行说明 审查流程核心原则:宁可漏报,不可误报。无法确定的问题标记为"需确认",不要给出武断结论。有几个写法心得非常值得分享。
description一定不要虚。不要写"帮助agent做代码审查",要写清楚什么条件下用、依赖什么、输出什么。因为调度器是靠description匹配任务的,description模糊,能力就白费。
steps要写到"换个人来也能照做"的程度。写"分析代码质量"不如写"检查每个函数是否处理了None返回值"。你是让Agent照着做,不是在跟它聊理想。
每个Skill必须有acceptance字段。Skill执行完,Agent照着验收标准自检,不满足就补做,这样输出质量才会稳定。之前我把"输出格式预定"写成描述性文字而不是验收清单,结果是十个任务有九种输出格式,后来改成Checklist形式,一次收敛。
4.3 技能库的目录组织与动态加载
多智能体集群里,Skills数量一多,组织方式就成了瓶颈。我目前的目录结构是三层分离:公共库放所有Agent都能用的通用能力,私有库放特定Agent专用技能,临时区放正在调试还没稳定的实验型技能。
skills/ common/ code-reviewer/ test-runner/ changelog-writer/ coder/ refactor-module/ implement-feature/ optimize-query/ qa/ regression-checker/ performance-profiler/ staging/ experimental-migrator/加载逻辑要动态化。Agent启动时不是一个一个把所有Skill都装进上下文,那会直接把上下文撑爆。正确做法是:Agent启动只加载基础技能清单,实际任务到来时,调度器根据任务类型、目标文件、依赖关系去skills目录里做匹配,把需要的Skill临时注入Agent的可用能力池。
这个"按任务调技能"的机制,说实话比把所有技能塞给Agent效果好了不止一个档次。技能越少Agent决策越干净,技能匹配越准Agent执行越靠谱。
4.4 设计Skills的心得:最小可执行、验收Checklist、别写幻想技能
Skills的设计是这里面最考验功力的部分,我整理出三条最值钱的教训。
最小可执行。一个Skill只干一件事,别搞"大而全"的复合技能。我写过一个大Skill叫"完成整个功能模块开发",里面包含需求分析、架构设计、编码、自测、文档编写。结果就是,Agent执行到一半总是偏航,要么在需求分析环节过度展开,要么在自测环节草草了事。后来拆成需求分析师、方案设计、编码实现、自测四个独立Skill,配合A2A流转,效果天差地别。
验收Checklist是质量的闸门。Skill里必须写明"做完这几件事才算完成"。没有验收清单的Skill,Agent做完就交,质量全靠运气。
别写"幻想技能"。所谓幻想技能,就是你写的时候以为模型会,但实际上不会。比如"逐行审查代码并自动修复所有Bug"——听起来是个好技能,实际执行时Agent会假装修复或者只改说明不改逻辑。可靠做法是写成像"识别三段可疑代码并标记,附修改建议,不直接改代码"这样模型真的有能力做到的粒度。宁可技能小一点、考核严一点,也不要技能大而空、输出不可控。
5. DeepAgents把集群编排成"项目制团队"
5.1 分工方式:路由表、角色卡片、职责清单
MCP解决了工具,A2A解决了通信,Skills解决了能力,但还缺一个总调度。我用的DeepAgents,核心是把多智能体当作一个团队来编排。
具体到操作层面,我给集群里的Agent建立了三样东西:路由表、角色卡片、职责清单。
路由表是一个映射关系,维护"任务类型→Agent端点"的对应关系。需求分析类任务丢给需求Agent,编码类任务丢给编码Agent,测试和部署各有各的目的地。路由表不是写死的,Agent的Agent Card如果有更新,路由表同步刷新。
角色卡片不只是"你是编码Agent"这种身份描述,它还包括这个Agent能访问的MCP Server白名单、可加载的Skill列表、允许创建的A2A任务类型、输出文档的格式规范。每Agent的上下文里只需放自己的角色卡片,不需要知道团队里其他Agent的细节。
职责清单比角色卡片更落地,它是"什么情况算我的活、什么情况必须上报"的显式列表。我最开始没有职责清单,结果集群一忙起来,Agent之间就开始互相踢皮球。后来给每Agent都写清楚了三条:"属于自身职责清单的任务必须承接""无法完成的任务必须明确回复failed并说明原因""任何不确定的信息询问调度器,不要自己猜"。
5.2 任务拆解与状态机:todo拆解、完成定义、依赖关系
DeepAgents的核心工作方式是拆解-分派-回收-汇总。一个大任务进来,先拆成多个Todo,每个Todo再带上状态和依赖关系,状态流转我做成了一套简单的状态机:pending → ready → running → completed / failed / blocked。
依赖关系是最容易被忽视的。比如"创建代码文件"和"执行单元测试"两件事,测试永远晚于创建。我一开始没有维护依赖关系图,调度器把无依赖的任务先派了出去,结果测试Agent比编码Agent还先开工,等编码Agent提代码时,测试Agent对着空气执行了一大堆失败用例。
解决方式很简单:每个Todo初始化时就带一个depends_on字段,调度器只在所有前置依赖completed之后才将该Todo置为ready状态。empty dependencies的任务才能被派发。
5.3 协同开发工作流:一次完整任务从分发到合入
我用一次具体的协同开发任务来展示这套体系是怎么转的。
场景:需求Agent收到一条需求"给用户列表页增加导出Excel功能"。第一步,需求Agent拆任务:方案设计与接口梳理、Excel导出逻辑实现、页面导出按钮与联调、测试与回归、文档更新与部署。第二步,需求Agent把"方案设计与接口梳理"作为A2A Task发给自己,做完后,将派生出的"Excel导出逻辑实现"Task通过A2A发送给编码Agent端点。编码Agent收到Task,从Skills公共库里加载excel-export-handler技能,从MCP里读取项目代码结构,开始实现。第三步,编码Agent实现完成后,Task置为completed并附Artifact,同时创建一个新Task"测试与回归"发给QA Agent。QA Agent加载test-runner技能,通过MCP执行测试用例,发现问题则把Task置为failed,附失败日志,并通过A2A把失败的Task重新路由回编码Agent,形成一个"写代码→测试→打回→改代码→再测"的闭环。第四步,测试通过后,部署Agent被调度器唤醒,加载deployer-skill,同时通过MCP临时获取部署权限,执行滚动发布。
整个过程里,DeepAgents调度器不干预Agent和Agent之间怎么聊,只负责维护Todo状态机、路由分发和超时处理。这种"只做项目管理,不做包工头"的定位非常重要,既保证了效率,又不至于因为调度器过度控制压掉Agent们的自主性。
5.4 容错与恢复:Agent掉线、MCP服务失效、任务幂等
集群跑起来之后,拼的不是谁在晴天跑得快,而是谁在故障时扛得住。我把运行期需要提前做好的容错设计列为三块。
Agent掉线。某个Agent的A2A端点无响应时,调度器需要有一个"健康检查"机制。我做一个轮询式的健康状态表,每60秒探测一次各Agent端点的存活响应。一旦发现掉线,调度器将正在处理的Task标记为blocked,并将对应Agent的可派发任务重新路由到备份Agent上——备份Agent不常驻,是调度器的一个临时容器,需要时被调度器启动。
MCP服务失效是另一种常见的灾难模式。某个MCP Server挂了,所有依赖它的Agent都会报错。我的兜底方案是:MCP Server重启后,Server侧自动重建临时索引,凡是依赖它的Agent的任务,在Server恢复之前自动挂起。不要尝试让Agent在Server不可用的时候用"另一条路子"硬来,Agent会发挥创造力用错误的方式完成任务,超惨。
任务幂等。这个在A2A部分已经提过,但在集群级还要做一层:调度器要维护全集群的task_id幂等表。任何Agent上报的已完成Task如果task_id已存在,调度器直接丢弃,避免重复计费和重复入库。加了对重复Task的拦截之后,之前经常出现的"一个Bug被两个Agent同时改"的问题就消掉了。
6. 端到端复盘:一次真实多智能体协同开发跑通后的经验
6.1 整个栈各层到底怎么配合
把四层组装好,整个系统运行时大概是这副模样。
用户给需求Agent提需求,需求Agent只负责理解和拆解,它通过MCP读取项目资料,通过Skills加载需求拆解手册。拆出任务后,需求Agent通过A2A把编码Task发给编码Agent。编码Agent本身不直接绑定任何工具,它启动时通过MCP找到自己能用的工具集合,同时从Skills里加载对应技术栈的开发规范,然后再动手。质检Agent通过A2A接收测试任务,通过MCP读取代码库,通过Skills加载测试执行流程,测完把结果回传。最后,DeepAgents调度器在总控台上展示所有Task的状态流转,哪个Agent正在干什么、哪些Task卡住了、哪条依赖链路最长,一屏全部可见。
在这个体系里,四层各有各的作用,缺一层都玩不转:没有MCP,工具接入就是一团乱麻;没有A2A,Agent之间就只能靠上下文传递;没有Skills,每个Agent都得背几大段提示词;没有DeepAgents,整个集群就像一艘没有船长的船。
6.2 性能与成本观察:Token消耗和并行度怎么控
踩完各种坑之后,集群终于跑起来了,接下来面对的是成本和性能问题。
我观察到的第一个现象是:引入MCP和Skills之后,单任务的Token消耗不降反升,因为MCP响应、技能清单、验收自检都是额外的token开销。但总成本其实下降了,原因是返工次数大幅减少——以前单体Agent做炸了重新改要花大量token,现在质检Agent在前置环节就把问题拦住了,返工少了很多。
第二个现象是并行度不是越高越好。我最初试过同时跑五个Agent并行执行不同模块,结果:两个Agent同时改同一个配置文件,互相覆盖;多个Agent同时查询同一个数据库表,导致锁等待。后来我把共享资源的写操作串行化,读操作放开并行,并行度控制在2到3个,整体吞吐反而提升了。
第三个现象是日志系统必须一开始就建。多Agent集群出问题时,排查难度比单体高一个量级。我现在所有Agent的A2A消息进出、MCP调用、Skill加载都会同步落一份结构化日志,日志里带task_id和agent_id两个关键维度。没有这两列,集群一乱,根本没法定位到底是谁在哪个环节丢了任务。
6.3 工具选型清单:我的最终组合
最终我稳定使用的组合是这样的:
MCP Server侧,我用FastMCP搭自定义工具,同时也接了几个现成的官方Server,比如文件系统、数据库、浏览器自动化。这里插一句,很多人问浏览器操作类MCP到底怎么选,不同工具的定位差异很大,有的偏自动化测试,粒度细到可以逐像素操作,有的偏信息抓取,粒度高到直接给结论。选之前先想清楚你的Agent是要"帮用户填表单"还是"帮用户查资料",前者选精细的,后者选高层的,别拿细粒度工具干粗活,token烧得心疼。
A2A这块,我自己用的是基于JSON-RPC风格的消息端点,每个Agent都起一个轻量的HTTP接口,Agent Card放在统一的服务注册表里。
Skills这边,用文本格式的SKILL.md方式管理,配合一个简单的技能检索脚本,按任务关键词匹配技能文件。
DeepAgents调度器,我用的是自研的轻量调度器,维护Todo状态机和路由表。它的核心代码大概只有几百行,但承担了整个集群的"大脑"角色。
6.4 给想上多智能体集群的人一句过来人建议
搭建这套集群,我最大的体会是:多智能体开发真正的难点不是模型,是不确定性管理。单体Agent出错可以靠提示词修,集群出错得靠架构设计去兜底。
如果你也准备做多智能体集群,我的建议是:不要一上来就追求豪华阵容。从两个Agent起步,一个负责拆解和规划,一个负责执行,先把MCP工具接入跑通,再引入A2A通信,然后逐步沉淀Skills。每加一层,跑一到两周的稳定期,别贪多。等你能清楚回答"每个Agent此刻在干什么、卡在什么环节、下一步会触发什么动作"这三个问题的时候,再考虑扩到五个、十个Agent。
我最后还想分享一个很小的技巧:把其中一个Agent设定为"观察员",它的任务不参与实际生产,只负责监控集群里其他Agent的状态流转,把异常行为记录下来。就这么一个不起眼的角色,帮我抓到了很多次调度器和A2A的隐性Bug。多智能体集群这东西,系统越复杂,越需要一个不干活只盯场的角色。这个观察员Agent,我至今都留着,它是我这套集群里最值的投资。