ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从单体Agent到多智能体系统:MCP、A2A、Skills与DeepAgents工程实践

从单体Agent到多智能体系统:MCP、A2A、Skills与DeepAgents工程实践 “单体Agent”这个词今年的热度明显开始退潮了。大家发现靠一个超级Agent内部叠几千行工具调用性能和可维护性都会崩——代码膨胀、上下文打架、单点故障修一个bug牵扯全身。真正走向生产环境的多智能体系统核心已经不是“模型有多强”而是工程化地组织一堆智能体工具怎么暴露、智能体之间怎么通信、能力怎么沉淀复用。DeepAgents、MCP、A2A、Skills这四个词放在一起正好串起了这一套逻辑MCP解决“如何接工具”A2A解决“如何对话协作”Skills解决“如何沉淀能力”而DeepAgents解决“如何编排落地”。这篇文章我从工程视角把这条链路完整拆一遍包含方案选型、协议理解、部署排障还有我实际踩过的坑。1. 为什么单体Agent撑不住了从“一把梭”到“组织化”1.1 单体Agent的瓶颈在哪里先聊个很现实的场景。早两个月我在一个项目里把Codex接进业务系统让它同时负责数据库查询、前端页面生成、API文档编写还指望它顺手把测试用例也写了。刚开始是爽的——一个Agent挂上MCP服务器把所有工具都暴露给它prompt里写清楚“你能做什么”它确实能跑通demo。但一旦进入真实业务问题就开始冒头第一是上下文膨胀。Agent的context窗口虽然是模型决定的但实际干活时每多一组工具定义prompt就要多消耗几百到几千token。挂了十五六个MCP服务之后光是工具描述就占了小半个窗口留给真正任务推理的空间被大幅压缩。更麻烦的是工具一多模型在自主决策时经常选错工具尤其在工具名相近、功能重叠时——我曾经见过Agent打算更新数据库记录结果调了删除接口还好有权限拦截兜底。第二是职责耦合。单体Agent里所有业务逻辑都揉在一个决策循环里意图识别、工具选择、参数构造、结果校验、错误恢复全混在一起。日志一旦打起来你根本分不清是哪一环出的问题。一个工具报错Agent会尝试各种奇怪的补偿动作甚至反复重试同一个错误请求最终把token耗光任务以失败告终——而且你还很难复现因为每次决策路径都不一样。第三是扩展成本高。想让单体Agent学会一个新能力你得修改prompt、增加工具注册、考虑新工具会不会跟旧工具冲突、做回归测试。这个改动链路非常长。我在实际维护中就发现当prompt超过一定长度之后每加一段新能力描述模型在旧任务上的表现就会波动像极了一个系统里背着大量祖传代码的老项目——改一处挂三处。1.2 多智能体系统的核心转变从“一个模型干所有事”到“一组Agent分工协作”多智能体架构的核心转变不是“把模型拆成几个”而是把职责拆开把接口标准化。每个Agent只干一类事内部保持简单Agent之间的协作靠协议通信而不是靠一个大prompt互相理解。这么做的收益是实实在在的上下文隔离每个Agent只需要加载跟自己职责相关的工具描述和系统提示context占用大幅减少推理质量也随之稳定。独立迭代代码生成Agent、数据库Agent、测试Agent可以分头升级。升级数据库Agent不影响其他Agent的行为——这在单体Agent里想都不敢想。错误边界清晰Agent A调用Agent B如果B返回的结果格式不对你一眼就能看出是B的问题而不是整个系统“突然变笨了”。能力复用一个写好的数据库Skill可以被多个Agent共享不用每个Agent的prompt里都塞一遍。你不需要一上来就搞几十个Agent。真正合理的起点是3到5个一个入口规划Agent负责拆解任务两个执行Agent分别负责编码和检索再挂一个工具型Agent做代码审查。先把这组角色用DeepAgents编排起来跑通链路再慢慢扩展。上来就搞十几个Agent的团队最后大多消耗在了Agent之间的调度通信调试上业务反而没推多少。2. MCP智能体的“手脚”——工具接入的标准协议2.1 MCP解决了什么问题从“每家各写各的插件”到“统一暴露工具”MCPModel Context Protocol这两年能火核心原因是它定了一个“智能体怎么发现和调用工具”的公共标准。之前每个Agent框架都有自己的工具接入方式LangChain的Tool、OpenAI的Function Calling、各种自研插件的JSON schema互相不兼容。你写了一个工具适配LangChain换到别的框架基本要重写。MCP的思路很简单把所有外部能力都封装成MCP服务器暴露统一的工具列表Agent通过MCP协议去发现、调用这些工具。工具本身可以是任意东西——一个数据库连接、一个HTTP API、一个本地脚本、甚至另一个服务。它对模型完全透明模型只需要知道“有哪些工具、工具描述是什么、怎么传参”。相当于以前给Agent装“手脚”每个厂商的接口线序都不同现在MCP就是统一了线序标准任意的“手脚”插上去就能用。2.2 MCP的Server/Client架构和关键概念MCP采用的是Server/Client架构跟传统的客户端-服务器模式很像MCP Server提供工具的一方。它声明自己有哪些tool并接收调用请求、返回结构化结果。可以跑在本地进程里也可以作为远程服务暴露。MCP Client使用工具的一方。Agent运行时作为MCP Client连接Server拉取工具列表发起调用。实际开发中MCP Server常通过Python SDK或者TypeScript SDK实现。以Python为例创建MCP服务器的骨架大概是这样的from mcp.server import Server from mcp.server.stdio import stdio_server app Server(database-tools) app.tool() def query_sql(sql: str) - str: 执行SQL查询并返回结果集。 # 这里写数据库操作逻辑 return str(result) async def main(): async with stdio_server() as (read_stream, write_stream): await app.run(read_stream, write_stream)模型侧看到的tool就是一个带描述的函数。比如上面这个query_sql模型会知道它是“执行SQL查询并返回结果集”需要的参数是一个合法的SQL字符串。这种设计极大降低了模型的工具调用压力——它不用关心SQL是连的MySQL还是PostgreSQL只关心“我传SQL进去拿到结果”。2.3 实操写一个MCP服务并在Agent中接入生产环境里我一般用Streamable HTTP方式部署MCP服务这样能跨机器调用。但本地调试时stdio模式更轻量断点调试也方便。我拿一个“前端设计稿转代码”的场景举例。团队里用Figma管理UI设计稿希望Agent能直接读取设计稿参数、拉取设计标注然后生成前端代码。传统做法是写脚本调用Figma API再把结果贴给Agent。用MCP之后流程就变成了写一个MCP Server封装Figma相关能力拉取画板列表、读取节点属性、导出切图信息。在Agent配置文件里注册这个Server指定transport和URL。启动Agent后它会自动发现这些工具并能在对话中自主决定调用哪个。具体到Codex的场景如果你希望通过代码平台直接读取设计稿而不是手动贴图那MCP Server就是这中间的桥梁。很多团队用这种方式做“设计稿自动生成页面骨架”效果比让Agent凭空发挥稳定得多——至少颜色、间距、字体大小这些视觉参数是从设计稿直接读出来的而不是模型猜的。接MCP时容易忽略的一个细节是工具的限流与鉴权。MCP Server暴露给Agent的能力本质上就是给模型开放了系统权限。我在生产环境里一定会做的三件事一是工具按最小权限设计Agent需要什么就给什么二是所有危险操作删表、改库、发请求加人工确认步骤三是对调用频率做限制防止模型在循环里反复刷同一个接口。2.4 MCP踩坑工具多了反而变笨MCP极大地方便了Agent能力的扩展但也带了一个新问题工具注册多了以后模型反而变傻。我在调试一个接入了十多个MCP服务的Agent时发现模型在工具选择上的失误率明显上升。排查下来原因是工具描述太冗长、功能有重叠模型在决策时被“干扰项”带偏了。解决这件事有几个实操办法工具描述一定要短、准、风格一致。描述里写“查询用户订单返回订单列表”比写“该工具用于查询用户历史订单信息返回订单的完整列表包含订单号、商品名称、金额、状态、创建时间等字段支持按时间范围筛选和分页”要好得多。模型不需要提前知道所有字段它需要的是“这个工具是干什么的”。同名功能合并。多个MCP Server如果都提供类似的搜索接口尽量收拢到一个标准接口或者在prompt里明确优先用哪个。定期整理。Agent上线后我会定期看一次工具调用日志把一周内没被调用过的工具下线。工具列表保持精简推理稳定度会明显改善。还有个实际坑是流程输出。有些MCP工具执行时间长比如跑一个批量任务标准MCP协议下调用是同步等待的遇到长任务容易超时或中断。很多MCP SDK现在支持进度通知和流式输出建议在封装长任务工具时主动用流式返回中间进度不然Agent会以为工具“卡死了”然后触发错误重试。3. A2A智能体之间的“语言”——让Agent学会互相协作3.1 A2A协议的定位不是MCP的替代是MCP之上的协作层很多朋友会把A2A和MCP搞混这里我需要明确摆出我的理解MCP解决的是“Agent调用工具”的问题A2A解决的是“Agent调用Agent”的问题。打个比方。MCP是Agent的手脚——大脑通过它去操作外部工具A2A是Agent的口和耳——让不同的Agent互相说话、分工、汇报进度。两者不是替代关系是互补关系。A2AAgent-to-Agent协议的核心是定义Agent之间通信的消息格式和能力协商机制。它的设计目标很明确一个Agent能向另一个Agent发布任务把问题说清楚并约定返回结果的格式。被请求的Agent可以声明自己的能力范围并决定是否接受任务。任务执行过程中双发可以交换进度更新和中间结果。支持长任务——被请求的Agent可以先接受任务然后事后异步返回最终结果。这跟团队里两个人协作很像你不需要把对方的代码全部看懂你只需要知道“他能做数据分析”然后你把数据给他说清楚要什么格式的结果他会给你返回中间他可能会问你几个问题等你回答。3.2 A2A与MCP联动的“社区实操”消息格式与跨Agent调用在社区里A2A最常见的落地方式是用它把MCP Server也“Agent化”暴露出来。也就是说一个Agent可以通过A2A协议去“请求”另一个Agent执行任务而那个Agent底层照样通过MCP调用自己的工具。这个过程的消息流大致是Agent A (规划角色) │ │ A2A: 发送任务请求 生成一个用户列表页面列表数据来自订单库 ▼ Agent B (前端开发Agent) │ │ 收到任务查看自己挂载的MCP工具 ▼ MCP Server: 读取页面模板 MCP Server: 查询订单库表结构 MCP Server: 生成页面代码 │ │ A2A: 返回结果和状态 ▼ Agent A 汇总返回给用户这套流程在工程上有几个好处Agent B对自己负责的模块拥有完全的控制权它内部的工具选择、参数构造、错误处理不需要暴露给Agent A。Agent A只需要知道“把这件事交给B我等结果就行”。如果Agent B挂了Agent A可以换一个备用Agent或者把错误信息返回给用户而不是让用户面对一堆“工具调用失败”的底层日志。所有Agent的通信消息都有统一的schema可以打到日志系统里做审计和追溯。最简单的A2A消息体结构一般包括任务ID、发起者、接收者、任务类型、任务描述、期望的响应格式。广义上这可以非常轻量——如果你不想引入重型框架直接用JSON消息配合消息队列也能实现类似效果。但如果你需要Agent之间动态协商能力、需要跨Agent的流式输出、需要标准的任务接收/拒绝逻辑那A2A协议的完整实现会更省事。3.3 A2A生产落地的关键考量同步还是异步要不要引入任务队列A2A在实操里最容易踩的坑是同步等待。很多人第一个版本会把Agent A直接同步调用Agent B的HTTP接口等B跑完再继续。这在两个Agent都在本地并且任务很短时没问题但一旦B是个慢Agent比如要跑几步工具调用链A就卡住了整个编排链路都被锁死。我的建议是Agent之间的调用一律按异步设计。A发出任务后立刻返回“已受理”B执行完再把结果推回来。中间需要一个轻量的任务状态存储可以是Redis也可以是数据库表。考虑到现在很多MCP工具已经支持进度上报A可以订阅B的进度事件给用户展示“当前第几步了”。如果Agent数量超过5个我建议引入一个任务队列层所有Agent间请求先入队再被消费。这跟削峰填谷是一个道理能明显降低突发尖峰下的系统卡顿。队列组件不一定要上重型MQ——Redis Stream在绝大多数场景下都足够用了。还有一点A2A请求一定要设超时和重试上限。我见过循环调用Agent A反复请求Agent BB因为某种原因每次都返回异常A不做判断就一直重试最终把B的资源耗干。解决方法是调用前先做能力契约检查B声明自己的能力范围失败了就把错误信息标记为“不可恢复”而不是无脑重试。4. Skills把“经验”工程化——让Agent越用越强4.1 Skills和MCP的边界MCP是接口Skills是方法论聊到Skills有个特别容易混淆的问题“Skills不就是一组prompt吗跟MCP有什么区别”我的理解是MCP暴露的是工具接口Skills沉淀的是“怎么用这些工具完成一类任务”的完整方法论。举个例子。你有MCP工具数据库查询、文件读写、代码执行。但“把一个Python脚本封装成命令行工具然后写个README放到指定目录”这件事模型不是天生就会的。你可能试了很多次发现最靠谱的流程是先看项目结构规范 → 再了解原有代码风格 → 生成脚本 → 自动跑一遍测试 → 写README。这一套“步骤规则常见坑”的集合就是一个Skill。Skills的载体不神秘本质上是结构化的说明文件markdown或YAML告诉Agent遇到某类任务时应该走什么流程、注意什么事项、用什么工具、输出什么格式。代码平台上流行的Agent Skills很多就是这种“找个目标 → 读文档 → 生成代码 → 自测 → 修复”的SOP文档化。4.2 自己开发一个Skill从“能跑”到“可信赖”关于“开发一个可用的Skill”我的实操建议是分四步走第一步梳理任务细节。把一个任务完整跑通几次记录下每一步可能的失败点。比如开发一个“从Excel表生成数据看板”的Skill我需要记录读取Excel时要注意哪些数据格式、生成看板用哪种图表库、颜色怎么匹配品牌规范、产出物放到哪个目录。第二步写成规范文档。用清晰的分步描述和清单把“默认动作”写清楚。如果这次任务的输出是代码还要在Skill里定义代码风格和自测要求。模型是很依赖prompt规范的——你写得越清晰它执行越稳定。第三步绑定MCP工具。Skill里引用的工具要能跟MCP Server对应上。我在实际项目里的做法是在Skill文档里明确标注“本步骤调用query_sql工具参数SQL”这样Agent拿到Skill后可以自动匹配已注册的MCP工具。第四步测试与迭代。用不同难度的样例去测这个Skill看看模型是否按预期走流程。发现哪里卡住了就在Skill文档里补充一句“遇到XX情况时应该YY”。Skills真正有价值的地方在于它是可以积累的资产。今天你踩了一个坑明天把这个坑写进Skill后天团队所有Agent就都不会再踩了。这比每个人工改prompt高效得多——相当于把你的个人经验逐步编译进了Agent的“操作手册”里。4.3 如何管理和分发Skills仓库化、版本化Skills的管理是生产中容易被忽视的一环。我见过最典型的反面例子所有Skill都存在各自Agent的prompt里改一版复制一版最后哪个Agent在用哪个版本都说不清。现在社区里比较流行的做法是把Skills当作代码来管理。放到Git仓库用目录组织每个Skill是一个子目录包含说明文档和示例。整个仓库可以跟Agent框架集成Agent启动时从仓库拉取最新版本。这样既能做版本控制又能做变更评审。你想想一个倾向性的规则变化比如“所有生成的代码风格改为TypeScript优先”如果能通过改一个仓库目录、PR合并、然后所有Agent自动更新工程效率是完全不一样的。5. 把它们拼接起来DeepAgents编排的实践链路5.1 一个三Agent协作案例从任务拆解到代码产出聊完三个核心组件我来结合DeepAgents的编排思路完整看一遍它们是怎么协作的。假设用户提了一个需求“把订单表按月份做销售统计并生成一个可视化报表页面”。第一步入口Agent拆解任务。入口Agent收到需求把它拆成子任务先查数据库有没有订单表、统计每个月的销售额、设计一个图表页面、把页面跟后端接口对接。它判断这个任务需要两种角色一个会写SQL、懂数据分析的Agent一个会写前端页面的Agent。第二步通过A2A分发任务。入口Agent通过A2A协议给数据Agent发消息“查订单表结构统计2024年度每月销售额返回JSON数组字段包括month和total_amount”。数据Agent接收到任务后通过自己的MCP工具数据库查询执行任务完成后通过A2A把结果JSON返回给入口Agent。第三步并行下发前端任务。入口Agent把统计JSON传给前端Agent让它生成页面。前端Agent内部会先去匹配Skills——读一下“前端图表页开发规范”这个Skill确认图表组件库、代码风格、页面结构然后调用MCP工具生成页面代码写到指定目录。第四步汇总与自检。入口Agent收到前端Agent的完成消息后会调用一个代码审查工具也可能是审查Agent检查页面代码质量和接口联调情况。全部通过后把结果汇总反馈给用户。这个过程看起来简单但每个环节都已标准化——MCP提供数据工具和代码生成能力Skills保证前端Agent知道“怎么写才算符合规范”A2A让Agent们能清晰分工而DeepAgents负责把整条链路编排起来管理任务状态和进度。5.2 编排时如何管理Agent的状态、记忆和上下文多Agent系统里最常被低估的是状态管理。几个Agent协作时上下文不能全塞在一个地方。我的建议是每个Agent保存自己的独立上下文不共享。入口Agent不需要知道前端Agent内部调了哪些工具只需要存储“它答应帮我生成页面状态是进行中”。共享状态放到外部存储里。比如一个任务发布了任务状态放到Redis支持多Agent读取和更新。长Token文档不要直接塞进Agent的上下文而是放到外部知识库Agent通过检索接口按需获取。这一步非常关键否则多Agent协作时的Token消耗会呈指数级增长成本炸裂。5.3 模式化复用工作流、模板化编排与沉淀多Agent系统真正从“demo”走向“产品”靠的是把编排流水线模板化。以DeepAgents举例实现一个“多Agent协同的电网可靠运行”或“自动化报表生成”类业务核心不是一个模型prompt而是一组可复用的Agent工作流模板任务输入格式、角色定义、契约接口、恢复策略。编排模板一旦定型扩展新业务就变成了“套模板”新增一个业务域定义清楚输入输出和工具依赖其余逻辑全部复用。这套思路跟后端微服务的道理一样——把稳定部分沉淀成平台把变化部分留给业务配置。6. 部署、调试与可观测性多Agent系统走向生产6.1 本地部署与调试技巧多Agent系统本地调试有个很烦的问题链路太长错误分散。Agent A报错了你分不清是它自己的问题还是B返回的数据有问题还是MCP工具超时了。我的调试经验是这样第一每个Agent单独测试。先把Agent B当作独立的单元用固定输入测它的输出质量、工具调用次数、错误恢复行为。确保每个Agent单测稳定之后再连起来测协作链路。我见过太多团队一开始就搞全链路调试发现问题时定位成本极高。第二让Agent打印决策轨迹。不只是记录结果还要记录“它为什么选这个工具”“它根据什么改了参数”。这需要Agent框架支持工具调用日志在DeepAgents这层的设计里建议在关键节点埋点。第三用固定样本做回归。写一组标准任务样例每次改完prompt或Skill后重新跑一遍对比输出是不是稳定。多Agent系统最大的风险是“改了一个配置另一个Agent行为漂移”回归测试能帮你尽早发现这种问题。6.2 日志、追踪与性能监控生产环境的多Agent系统可观测性是大前提。我建议至少做三件事全局任务ID。用户发起一次请求生成一个task_id后续所有Agent调用、MCP工具调用都带上这个ID。排查时按ID拉全链路日志效率会高非常多。关键指标采集。每个Agent的调用次数、单次任务耗时、Token消耗、工具调用失败率。这些数据能帮你判断系统瓶颈——比如“入口Agent的token消耗过高”可能是因为任务拆解粒度不够细。Alert规则。当某个Agent出现连续失败、任务循环或时间超限时及时报警。除了日志还有一个很实际的监控点是费用监控。多Agent协作模式下Token的消耗能力比单体Agent大很多——每个Agent都要消费上下文通信也要消耗Token。我见过一个项目上线一周后账单高达数千美元原因就是Agent之间循环确认消息来回几十轮。如果你不做预算控制这类风险在未来是实实在在的。6.3 安全与权限设计不要开放所有工具给所有Agent最后聊聊安全。多Agent系统里权限如果设计成“所有Agent共享全部MCP工具”那就等于把整个系统后台开放给了一个可能被用户prompt攻击的入口。我在实际设计里至少会做三层控制工具白名单。每个Agent只能调用自己被授权的MCP工具。比如前端Agent只能调代码生成和读取类工具不能调数据库写入类工具。敏感操作审批。涉及删除、修改、发布的工具调用必须经过人工确认节点。隔离环境。代码生成类的Agent在沙箱或容器中执行避免工具调用对宿主机产生直接影响。现在很多团队在MCP Server层做工具级访问控制用API Key区分调用方身份再配合每个Agent的权限策略——原理不复杂但一定要在一开始就设计进去后期补权限结构成本会高很多。7. 落地排障与心得真实场景的几个典型问题7.1 社区的典型问题速查表这些是在实际部署和社区反馈里频率非常高的问题和解决方向建议直接收藏备用问题现象常见原因排查方向Agent选错MCP工具工具描述重叠/过长精简工具描述合并类似功能多Agent协作时任务丢失A2A请求无超时重试机制加任务队列和状态存储Token消耗异常飙升Agent循环重试/上下文重复加载加调用次数上限共享上下文外部化某个Agent执行结果不稳定Skill版本不一致Skill仓库化管控统一分发MCP工具调用超时同步调用长任务改异步模式流式进度不同代码风格Skill里缺少代码规范说明Skill中定义风格要求并绑定示例日志无法串联缺少全局任务ID全链路统一task_id生产环境工具误操作权限控制过宽MCP工具白名单敏感操作审批7.2 从“能跑通”到“能维护”三条核心建议最后基于从单体Agent走向多Agent架构的实操过程我给三条核心建议第一控制Agent数量、足量扩展也要克制。很多人看到多Agent概念就兴奋一上来规划了各种角色。实际跑下来你会发现真正稳定的架构往往只有3到5个核心Agent其他都应该是轻量技能。Agent越多通信和编排成本越高不要为了“多”而“多”。第二把Skill当作工程资产管理。去重、去版本、建仓库、设规则。一个Skill如果有多个主人那就等于没有主人。我遇到过团队里两个Agent对同一个任务处理逻辑不一致最后定位发现是两个版本的Skill文档分发给不同Agent导致的——这种问题仓库化和统一分发能直接消灭。第三永远保留人工兜底。无论DeepAgents编排得多成熟线上系统都要有“人工确认”和“紧急降级”的开关。多Agent系统的输出质量本质上是概率性的生产环境的期望管理很重要——把人工介入的成本降到最低但保留介入通道是工程落地的基本盘。坦白说从单体Agent走向多智能体架构跟当年从单体应用走向微服务有太多相似之处——前期成本更高、调试更麻烦但一旦体系成型无论是扩展新能力、隔离故障还是团队协作分工收益都远超单体。我自己在实际调试初期也被通信丢消息、工具循环调用这些问题折腾过但把MCP、A2A、Skills各层职责理清之后整个系统就变得清晰可控了。
返回列表