ARTICLE DETAIL

资讯详情

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

多智能体架构实战:MCP、A2A与Skills驱动Agent从单体走向组织

多智能体架构实战:MCP、A2A与Skills驱动Agent从单体走向组织 如果你最近在折腾 AI Agent八成遇到过这样的场景一个单体 Agent 又当规划师又当执行者任务一复杂上下文乱成一团工具调用错得离谱跑一次要半天出了问题还得翻几千行日志。我自己的项目前期就是这样直到把单体 Agent 拆成多智能体组织用 DeepAgents 做编排层用 MCP 管统一工具接入用 A2A 定 Agent 之间的通信规范再用 Skills 沉淀可复用经验整个系统才真正从“能跑”变成“能扛”。这篇不聊“多智能体很酷”这种空话就讲工程逻辑为什么单体不够用MCP、A2A、Skills 各自解决什么问题以及一个三智能体协作系统怎么从零落地。适合后端工程师、AI 应用开发者、架构师以及所有想把 Agent 从 demo 推向生产环境的人。1. 为什么单体 Agent 不够用从个人英雄到组织作战1.1 单体 Agent 的“单线程困境”先说我是怎么走到多智能体这条路上的。最早做自动化代码审查工具我的方案很简单一个 Agent系统提示词写满规则工具列表挂上代码查询、Git 操作、静态检查脚本然后让它一次性完成“读代码 → 找问题 → 改代码 → 跑测试 → 写评审意见”。前几个 demo 场景表现还行一上真实项目就露馅。问题集中在三个地方。第一是上下文被吃光。系统提示词 2000 字工具描述 3000 字任务背景再来 3000 字模型还没开始干活就已经消耗大量 token。代码一长关键逻辑就被截断Agent 开始胡编。第二是工具选择错误率急剧上升。当单个 Agent 手里有十几个工具时LLM 就像进了巨型超市经常拿错东西。我遇到过它想读文件却调用了数据库查询工具想执行测试却去改了配置文件。工具越多这种错误越频繁。第三是故障无法定位。单体 Agent 的每次失败都是一个黑盒你不知道是规划错了、工具错了、还是模型理解错了。任务链路越长失败后重新来过的成本越高上下文再次膨胀进入恶性循环。这不是模型能力不够而是架构设计有问题。一个 Agent 承担了太多角色信息密度太高注意力机制根本处理不过来。类比一下让一个人同时当项目经理、程序员、测试、运维他不一定能力差但一定会在复杂项目里顾此失彼。团队之所以存在不是因为单个人不行而是因为分工之后每个人只用关注一件事。1.2 多智能体的核心命题不是堆 Agent而是定义“组织规则”很多人听到“多智能体”就开始堆 Agent三个不够上十个十个不够搞几百个。结果系统变成一团乱麻Agent 之间互相抢任务没人知道谁该干嘛。我的观点是多智能体架构和公司组织一样核心不是“人多”而是“规则清晰”。一个健康的组织每个人有明确的岗位、汇报关系、协作协议和产出标准。Agent 之间的协作也是同一套逻辑。一个可治理的多智能体系统至少需要四层能力组合编排与治理层DeepAgents决定任务怎么拆、Agent 怎么调度、状态怎么追踪、结果怎么汇总。外部工具接入层MCP让 Agent 以统一方式操作数据库、文件、浏览器、IDE 等外部系统。Agent 通信层A2A定义 Agent 之间如何互相发现、发消息、传结果。经验沉淀层Skills把高频任务的执行手法固化成可复用技能包避免每次重新写 prompt。这套组合拆开看正好对应一家软件公司的结构管理层DeepAgents、基础设施部MCP、部门间协作流程A2A、SOP 文档库Skills。这也是为什么我说“从单体到组织”是必然演进——单个 Agent 能解决“单线程”任务但解决不了“并发、分工、协作、故障隔离”这些组织级问题。1.3 拆解之后的收益并行、隔离与可观测把单体拆成多智能体组织之后我拿到了三个直接收益。一是并行能力。以前一个 Agent 串行处理十个子任务现在可以五个 Agent 同时处理五件独立的事。比如代码审查场景里后端代码交给 Coder A前端代码交给 Coder BReviewer 最后汇总整体耗时从 15 分钟降到 4 分钟。二是故障隔离。某个 Agent 挂了只需要重跑它的子任务不用整个链路回滚。这就像微服务架构里一个服务崩溃不会拖垮整个系统。三是可观测性。每个 Agent 的输入输出、消息流转、状态切换都可以被记录和分析。出了问题你能清清楚楚看到是哪一环出的错而不是盯着一个巨大的黑盒猜。不过这里要提醒一句拆分的粒度不是越细越好。Agent 之间通信有开销每个 Agent 都要消耗 token 做上下文切换。我实操下来的经验是先把一个单体 Agent 的长期任务清单列出来找“上下文冲突最大”的环节去拆而不是一刀切成十几份。2. MCP让 Agent 长出“手”统一工具接入协议2.1 为什么 MCP 成了“Agent 的 USB-C”在很多不同的 Agent 项目里最让人头疼的不是模型写不好而是“工具接不过来”。没有 MCP 之前每个 Agent 都用自定义的 function calling 格式一个系统一套结构。如果你的平台上有 N 个 Agent、要接 M 个外部系统就得写 N×M 个适配器维护成本爆炸。MCPModel Context Protocol解决的就是这个问题。它把工具调用抽成一个统一协议核心模型是 Client-ServerMCP Server负责暴露能力比如“连接 PostgreSQL 数据库”“读取某个目录下的文件”“调用某个内部接口”。MCP Client嵌在 Agent 应用程序里负责通过协议调用这些能力。对 Agent 来说它只需要理解 MCP 的标准格式不需要关心背后是哪种数据库、哪种 API、哪种文件系统。这就像电脑上的 USB-C 接口不管你插的是显示器、硬盘还是手机都是同一个口。我还想强调一点MCP 的价值不仅在于“统一格式”更在于“边界划分”。以前工具逻辑嵌在 Agent 的 prompt 里改工具要和写 Agent 的人开会现在工具独立部署成服务工具团队和 Agent 团队可以并行。这种边界带来的运维便利往往比协议本身更重要。2.2 从 0 写一个 MCP Server工具描述决定 Agent 会不会用这里用一个 FastMCPPython的示例展示 MCP Server 最核心的“工具注册”写法。假设我们做一个项目状态查询服务让 Agent 能查某个任务的状态。from fastmcp import FastMCP mcp FastMCP(project-service) mcp.tool( namequery_task_status, description查询指定任务的当前状态。输入必须包含 task_id返回 JSON 结构包含 status、owner、updated_at 三个字段。 ) def query_task_status(task_id: str) - dict: # 这里模拟数据库查询实际项目请接入真实数据源 data { task_1001: {status: in_progress, owner: coder-agent, updated_at: 2025-06-01T10:00:00Z}, task_1002: {status: waiting_review, owner: planner-agent, updated_at: 2025-06-01T11:30:00Z}, } result data.get(task_id, {status: not_found, owner: None, updated_at: None}) return result if __name__ __main__: mcp.run()这段代码本身不复杂但有几个实操要点值得展开。第一工具的description是 LLM 选择工具的依据。模型不会看代码实现它只看描述来判断“什么时候该调用这个工具”。所以描述里必须写清楚输入要求、返回结构、使用场景。我自己习惯在 description 后面加一句“当用户询问任务进度时使用”效果比泛泛的“查询任务状态”好很多。第二inputSchema要严格。FastMCP 会根据函数签名自动生成 JSON Schema但参数类型和默认值必须明确。如果参数是可选的要在 docstring 里说明如果参数是枚举值最好在类型注释里写清楚取值范围。否则 Agent 可能传一个非法值进来。第三一个工具只做一件事。我见过有人把“查任务改状态发送通知”塞进一个 tool 里图省事结果 Agent 在只有查询需求时把状态改了。原则是查询、写入、通知严格分开每个工具只暴露最小必要能力。2.3 MCP 三层模型Resource / Tool / PromptMCP 不只是工具调用协议它定义了三种能力分别是 Resource、Tool、Prompt我一开始也分不清实践中踩过几次坑之后才理顺。Resource 是“可以被读取的内容”。比如一个配置文件、一个数据库查询结果、一个文档。它的语义是“读”不产生副作用。在 MCP 里Resource 通过 URI 定位Agent 可以把它作为上下文的一部分加载。Tool 是“要执行的动作”。比如发送邮件、创建工单、执行代码。它有副作用需要 Agent 明确决策后才调用。Prompt 是“为特定场景准备的提示模板”。它不算动作更像给 Agent 的“工作指引”或“起手式”比如“根据这段代码生成单元测试”的 prompt 模板。我在设计 API 给 Agent 用的时候建议把三类能力分清楚如果只是给 Agent 提供背景资料用 Resource如果让 Agent 执行操作用 Tool如果想让 Agent 按固定流程做事用 Prompt。分类混乱是 MCP Server 设计最大的坑——我见过很多团队把所有东西都塞进 Tool结果 Agent 一上来就调用一堆产生副作用的操作。2.4 给 Agent 的手上锁安全边界与审计Agent 有了工具就相当于有了“手”但手没有安全意识。这是工程化落地时最容易忽视的问题。我总结了三条必须做的安全边界。第一操作面收敛。MCP Server 里的工具不要直接暴露“执行任意 shell 命令”更不要暴露“读写任意路径”。正确的做法是只暴露白名单操作比如“在 /tmp/project 目录下创建文件”“运行 test 目录下的指定测试脚本”。收敛操作面不是限制能力而是让 Agent 在可控范围内试错。第二数据面脱敏。查询类工具返回的数据可能包含 API key、手机号、内部 IP。在返回给 Agent 之前一定要做脱敏处理。我有一次让 Agent 分析日志结果它把日志里的生产环境数据库地址直接写进了报告里后来加了一道脱敏过滤器才解决。第三审计追踪。所有 MCP 工具调用都要记录日志包含调用时间、调用 Agent、入参、出参、执行结果。代码评审场景里这些日志能帮你快速定位“是谁在什么时候改了哪个文件”。没有审计多智能体系统一旦出事排查成本会高到让人崩溃。好消息是 MCP 的生态已经覆盖了大量常用工具比如数据库客户端、浏览器、IDE、设计工具、甚至游戏引擎和调试器。团队内部也可以把自研系统封装成私域 MCP Server供多个 Agent 共享。协议统一之后“接一个系统”和“接一套系统”的成本差距会越来越小。3. A2A让 Agent 互相“听懂话”打通 Agent 之间通信协议3.1 A2A 的核心对象都在描述“能力”MCP 解决的是“Agent 和工具”之间的问题A2AAgent-to-Agent解决的是“Agent 和 Agent”之间的问题。它们尺寸不同但思路类似用统一协议替代点对点自定义对接。A2A 里最核心的几个对象我用自己的话翻译一下Agent Card相当于 Agent 的“简历”。声明这个 Agent 能做什么、输入输出类型、通信端点。其他 Agent 通过读 Agent Card 判断“这件事该找谁”。Task一次任务单元。由发起方创建包含任务描述和输入数据由执行方处理并返回状态。MessageAgent 之间传递的信息载体。Artifact任务执行的产物比如生成的代码、评审报告、分析结果。这套设计对标的是 OpenAPI 之于 REST API。以前写服务大招是“接口即文档”A2A 把同样的哲学搬到了 Agent 世界每个 Agent 都有一张 Card卡上写清楚了能力边界和调用方式协作方不用猜拿 Card 对齐就能开工。3.2 设计 Agent 协作的三个关键抉择在实际设计多智能体系统时有三个问题必须在早期确定否则后面返工成本很高。第一个同步调用还是异步任务。如果 Agent 之间只是简单问答比如“帮我翻译这句话”同步调用就行。但多数生产任务都是长任务比如“生成一份 500 行代码的模块”就需要异步提交 Task返回 task_id然后通过轮询或回调获取进度。我的经验是凡是可能超过 30 秒的调用一律设计成异步别赌模型推理速度。第二个直接写死地址还是服务发现。小规模系统三个 Agent互相把端点写死在配置里完全没问题。但一旦 Agent 数量增长或者 Agent 被频繁上下线就要引入注册中心。Agent 启动时注册自己的 Agent Card调用方通过能力标签去查找。这个过程类似于微服务里的注册发现只是注册的内容从 API 定义变成了能力声明。第三个任务的最终结果归谁管。A2A 里有一个容易混淆的点——谁创建 Task谁就负责跟踪最终结果。执行方只负责把 Task 状态更新到 completed并返回 Artifact。发起方负责检查 Artifact、处理错误、给用户呈现结果。如果不把这个边界定清楚两个 Agent 会互相等待任务永远无法结束。3.3 暴露一个 A2A Agent 的现实做法暴露一个 A2A Agent本质上就是在一个现有服务上加一组标准 HTTP 端点。我以 FastAPI 为例分享一下最小实现。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class TaskRequest(BaseModel): task_id: str message: str input_data: dict app.get(/a2a/agent_card) def get_agent_card(): return { name: executor-agent, description: 负责执行代码生成任务输入需求描述输出代码文件和测试结果。, capabilities: [code_generation, unit_test], endpoints: { submit_task: /a2a/tasks } } app.post(/a2a/tasks) def submit_task(req: TaskRequest): # 这里将任务写入队列返回 task_id后续通过 GET /a2a/tasks/{task_id} 查询 return {task_id: req.task_id, status: accepted} app.get(/a2a/tasks/{task_id}) def get_task(task_id: str): # 实际实现里这里读取任务状态和结果 return {task_id: task_id, status: completed, artifact: {code: ...}}关键点是 agent_card 里的description要写得像一份清晰的“岗位说明”不要夸大能力。其他 Agent 正是靠这段描述决定“要不要把任务发给这个 Agent”。写得太泛它会收到一批自己干不了的任务写得太窄又没人来找它。关于技术栈我多说一句A2A 是基于 HTTP JSON 的协议所以用什么语言实现都不重要。Java 的 Spring 生态可以加端点C 的服务也可以暴露同样的路径。跨语言、跨团队互操作本来就是 A2A 的卖点不用因为“我们这个服务是 C 老系统”就放弃接入。3.4 没有 A2A 会怎样也许有人会问我的 Agent 之间直接传 JSON 不行吗能行但那是“点对点私聊”。短期没问题长期会有两个痛点。一个是耦合。每个 Agent 都要知道其他 Agent 的具体接口格式改一个 Agent 的输入输出所有协作方都要跟着改。A2A 把接口格式固定下来类似把“各说各话”变成“普通话标准”。另一个是不可观测。点对点调用时消息流转散落在各个 Agent 的代码里无从追踪。A2A 的 Task 模型天然带状态机从 submitted、working、completed 到 failed每一步都有记录。这对排查多智能体问题非常重要——我在生产环境里排查过 Agent 连环调用的死循环最后就是靠 Task 状态日志定位的。4. Skills把经验变成可复用的资产Agent 的兵器库4.1 Skills 和 MCP、Prompt 的区别在哪先把概念理清。MCP 解决“怎么连外部系统”Skills 解决“这个任务应该按什么套路做”。很多团队把技能写进 prompt觉得多写两句就行但我后来发现prompt 是“一次性外套”Skills 是“可复用的装备”。举个例子。代码评审是我最常用的场景我之前在系统 prompt 里写了一大段“请按代码规范、逻辑漏洞、性能问题、安全隐患四个维度审查”。听起来没问题但每次给不同 Agent 配置时都要重写一遍而且很难精细控制。后来我把这段评审逻辑抽成了一个 Skill包含一份 SKILL.md描述评审流程和判断标准、一个脚本执行静态检查、一个模板输出评审报告。Agent 只要声明“我有 code-review 这个技能”就能在对应场景自动加载。这和真正的工程师“拥有一套自己的 code review checklist”是一回事。区别总结成一句话MCP 是工具Skills 是方法论prompt 是临场发挥Skills 是可以沉淀的长期资产。4.2 设计一个好技能包的五个要点技能包本质上是一个目录结构但我见过太多人把技能包写成一坨 prompt效果很差。我根据实际经验总结出五个设计要点。第一命名和描述要像“书名”一样准确。比如“python-code-reviewer”描述写“基于 PEP8 和常见反模式对 Python 代码做静态审查”。不要起“code-check”这种模糊名字。第二写清触发条件和不适用场景。在 SKILL.md 里明确“该技能适用于 Python 项目代码评审不适用于配置文件或文档审查”。这一步能显著降低 Agent 误用技能的概率。第三步骤编排要具体。比如“第一步读目标目录下所有 .py 文件第二步运行 pylint…”。步骤越清晰技能输出越稳定。第四声明依赖。技能依赖的库、命令、环境变量必须在技能包里写清楚。否则换一台机器就失效技能的可移植性就没了。第五约定输出格式。输出是 JSON、Markdown、还是纯文本如果技能是给其他 Agent 消费的输出格式不统一下游解析就会崩溃。一个 SKILL.md 的目录示例大概长这样my-code-review-skill/ ├── SKILL.md # 技能说明 触发条件 操作步骤 ├── scripts/ │ └── run_static_check.py # 静态检查脚本 ├── templates/ │ └── review_report.md.j2 # 评审报告模板 └── requirements.txt # 依赖说明4.3 技能从哪来、怎么管技能有两个来源外部市场和自建仓库。官方技能市场和开源社区里可以看到大量现成技能包覆盖代码生成、文档撰写、数据分析、前端开发等领域。第三方的技能生态也正在成形很多团队把“技能商店”做成内部平台每个团队都贡献自己沉淀的 Best Practice。我会强烈建议每家在做多智能体的团队尽早建立自己的私有技能仓库。因为行业公开技能解决的是通用问题而真正有壁垒的是“你们团队特有的业务流程”。你不想让 Agent 每次重新学习你们的代码规范、部署流程、故障响应 SOP这些都应该做成技能包挂到内部仓库里。技能的管理要像管代码一样严格走评审流程、带版本号、记录更新日志。因为技能的本质是“代码 提示词”一旦被恶意或错误修改可能诱导 Agent 执行危险操作。从不可信来源下载的技能包一定要先人工审查脚本内容再允许 Agent 加载。5. 实操从 0 搭一个三智能体协作系统5.1 场景与角色拓扑设计纸上谈兵这么久来看一个完整可落地的案例。我选择“需求拆解 → 代码生成 → 代码评审”这个链路因为它覆盖了 MCP、A2A、Skills 的典型用法又不会复杂到劝退新手。三个 Agent 的分工如下Planner需求拆解 Agent接收用户需求拆成可执行任务单输出任务描述和验收标准。Coder代码生成 Agent接收任务单通过 MCP 读取代码库文件、生成代码、写入文件并跑测试。Reviewer代码评审 Agent接收 Coder 提交的代码变更用代码评审 Skill 做审查输出问题清单。拓扑不复杂用户请求进入 DeepAgents 编排器编排器先叫 Planner拿到任务单后叫 CoderCoder 完成后把产物通过 A2A 发给 Reviewer最后结果汇总返回用户。这里 A2A 用在 Coder 与 Reviewer 之间MCP 用在 Coder 与代码库、测试环境之间Skills 则挂在 Reviewer 身上。5.2 核心代码MCP 工具 A2A 暴露 编排器先写 Coder 用的 MCP Server提供读取代码文件的工具。from fastmcp import FastMCP mcp FastMCP(codebase-service) mcp.tool( nameread_code_file, description读取指定代码文件内容并返回。输入 file_path 必须是 /workspace 目录下的相对路径。 ) def read_code_file(file_path: str) - str: base_dir /workspace safe_path base_dir / file_path.lstrip(/) # 这里应加路径穿越校验确保 safe_path 在 base_dir 内 with open(safe_path, r, encodingutf-8) as f: return f.read() mcp.tool( namewrite_code_file, description将代码写入指定文件。输入 file_path 为 /workspace 下相对路径content 为完整文件内容。 ) def write_code_file(file_path: str, content: str) - str: base_dir /workspace safe_path base_dir / file_path.lstrip(/) with open(safe_path, w, encodingutf-8) as f: f.write(content) return fwritten {len(content)} bytes to {file_path}这段代码刻意做了路径限制和写操作隔离。因为 Agent 写文件是有副作用的一定不要把根路径或任意路径交给 Agent否则它会“发挥创意”改掉不该改的文件。接着把 Coder 包装成 A2A 服务。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class TaskRequest(BaseModel): task_id: str message: str input_data: dict app.get(/a2a/agent_card) def agent_card(): return { name: coder-agent, description: 接收任务单生成 Python 代码并写入 /workspace可运行 pytest 测试。, capabilities: [python_code_generation, pytest], endpoints: {submit_task: /a2a/tasks} } app.post(/a2a/tasks) def submit_task(req: TaskRequest): # 生产环境应投递到任务队列这里简化直接返回 accepted return {task_id: req.task_id, status: accepted} app.get(/a2a/tasks/{task_id}) def get_task(task_id: str): # 返回任务状态与最终产物 return {task_id: task_id, status: completed, artifact: {files: [src/main.py], tests: 3 passed}}这段代码的关键在于agent_card的声明足够窄它只接收“生成 Python 代码”的任务不会接“运维部署”的活。A2A 协议本身不限制你暴露多少能力但能力边界越清晰编排器做路由时越不容易出错。最后用 DeepAgents 编排器把它们串起来。我习惯用状态机的方式写编排逻辑伪代码如下def run_workflow(user_request): plan planner.process(user_request) # Planner 产出任务单 coder_result coder.submit(plan.task) # Coder 接单执行 review reviewer.review(coder_result.artifact) # Reviewer 用 Skill 审查 return {plan: plan, code: coder_result, review: review}真实生产环境里编排器还要处理超时、重试、并发、状态持久化篇幅有限就不展开全部代码。重点想表达的是DeepAgents 编排层不负责具体业务逻辑它只做“组织协调”。具体怎么写代码、怎么评审都是下面各 Agent 的事情。5.3 参数选择与资源规划关于 Agent 的数量、模型选择、超时、token 预算我给一份实操参数参考都不是拍脑袋是实测过的相对稳妥值。Agent 数量起步建议 3 到 7 个。少于 3 个没必要上多智能体多于 7 个通信开销会超过收益。我见过 20 个 Agent 的系统大部分时间都在互相问“你在干嘛”。每个 Agent 挂载的 MCP 工具数控制在 8 到 10 个以内。工具描述会占用上下文工具越多模型选择错误的概率越高。这个值是日常测试里比较均衡的点。超时设计同步调用 30 秒以内异步任务轮询间隔 10 秒超时整个任务 10 分钟。长任务如果经常超时考虑拆分任务粒度而不是单纯加长超时时间。Token 预算给每个 Agent 单独设 max_tokens不要让一个 Agent 吃光所有资源。代码生成 Agent 通常需要更多输出 token评审 Agent 需要更长的输入窗口按角色分配是更精细的作法。这些参数没有绝对标准但“按角色分 Cluster、按任务分超时、按上下文分工具”这个思路是通用的。拿单体 Agent 时代的“一套参数打天下”来做多智能体后面一定出乱子。6. 现实中的大坑与排障技巧我的实战笔记6.1 高频问题速查表多智能体系统的坑比单体多一个维度因为除了模型和工具还有 Agent 间协作本身的不确定性。我把踩过的坑整理成一张速查表给出排查思路不一定覆盖所有场景但能省下大量排查时间。现象常见根因处理办法Agent 不调用 MCP 工具工具描述模糊模型不知道何时调用重写 description补场景和输入示例工具返回数据但 Agent 读不懂返回结构复杂缺少字段说明简化返回结构或加一层格式化封装A2A 消息互相不理解Agent Card 能力描述过粗收敛 capabilities写明输入输出约定多 Agent 任务状态丢失缺少状态机任务被重复处理统一 Task 状态机持久化状态系统吞吐很低同步调用过多长任务阻塞改异步任务队列化请求上下文爆炸把所有工具和技能全量挂载按需求按需挂载 MCP 和 Skills这里挑一个最容易忽视的讲工具返回结构。FastMCP 默认会把 Python 函数的返回值原样传输如果你返回的是一个嵌套很深的 dictAgent 可能不知道从哪里取关键字段。我在生产里会专门写一层“工具返回格式化”把复杂结果折叠成简洁结构效果立竿见影。另一个高频坑是把 A2A 的 Task 当成“函数调用的包装”同步调用后立即拿结果。结果模型一思考就超时或者任务被重复提交。正确做法是凡是发给 Agent 的任务都默认异步状态机从 submitted 开始一步一步推进到 completed 或 failed。6.2 我亲测有效的多智能体“组织原则”最后分享几条我自己沉淀的工程原则。这些不是教科书理论是三四个项目踩出来的经验。原则一先写“岗位说明书”再写代码。别急着让 Agent 写 prompt。先定义每个 Agent 的岗位说明书负责什么、不负责什么、输入是什么、输出是什么。岗位说明书写清楚了代码只是把它翻译成 A2A 的 Agent Card 而已。原则二每个 Agent 只做一件事宁可重复不要耦合。比如 Coder 就是写代码Reviewer 就是审查哪怕两个 Agent 都要读同一个代码文件也不要让 Reviewer 去“顺带修一下代码”。耦合会让故障边界变模糊。原则三编排器只负责流程不负责业务。DeepAgents 编排层像公司前台它知道“这个需求该找哪个部门”但不会替业务部门做具体决策。一旦编排器开始接业务逻辑它就会变成新的单体 Agent。原则四先 Mock 再真实接入。我犯过的最大错误是流程没跑通就接真实 MCP 工具结果排查问题时分不清是模型问题、工具问题还是编排问题。正确路径是先把所有 MCP 和 A2A 端点 Mock 成假数据跑通整个工作流再一个个替换成真实服务。这样每一步出问题都能定位。原则五审计日志是基础设施不是可选项。所有 Agent 动作、工具调用、消息传递都要落库。多智能体系统一旦出问题没有日志几乎无从查起而日志本身成本很低这笔账一定要算。原则六别为了智能体而智能体。如果两个 Agent 可以解决绝不上五个。很多时候一个 Agent 一组 MCP 工具 一个 Skill 就够用了。多智能体是为了解决“单 Agent 职责过重”的问题不是解决“显得技术先进”的问题。如果真要再补一条迁移经验我建议你从最小治理单元开始改先把一个单体 Agent 拆成“拆任务 执行”两个 Agent加上 A2A 通信跑通后再逐步引入 MCP 和 Skills。这样每一步都可控效果对比也更清晰。架构演进这件事最怕一开始就铺太大摊子。多智能体谈不上是什么银弹真正管用的其实是把组织治理的常识搬到 Agent 世界里。我自己在踩过这些坑之后最深的体会是技术协议的选型只是第一步Agent 之间的“契约设计”才是决定成败的关键。契约清了DeepAgents 的编排、MCP 的工具接入、A2A 的通信、Skills 的能力沉淀都会陆续顺畅起来。
返回列表