上个月我把一个单体客服 Agent 拆成了四个独立 Agent结果平均单次任务成本下降了 40%端到端成功率从 68% 涨到了 91%。在拆之前我花了两周疯狂调 Prompt、加工具、缩上下文全都白费。那两周让我彻底认清一个事实单体 Agent 最大的问题不是模型不够聪明而是架构扛不住复杂任务。今天这篇内容我想结合这个改造项目的真实过程聊聊单体 Agent 的天花板在哪里以及为什么复杂任务最终都会被推着走向 Multi-Agent。如果你正在单 Agent 里挣扎或者刚接触 Agent 想避坑这篇会比较对胃口。我见过不少团队一开始都是搭单体 Agent 快速上线毕竟单个模型加几个工具就能跑通 Demo很爽。但业务一旦复杂起来上下文爆炸、工具选错、任务中断这些毛病会接踵而至。你以为是模型不行换了更强的模型结果贵了、慢了问题反而更多。这个死循环不是模型背锅而是单体架构本身的瓶颈。我把这个判断标准、设计思路和实测数据完整写出来希望能帮你少走两个月的弯路。1. 单体 Agent 的天花板到底在哪里三个被忽视的架构瓶颈1.1 上下文窗口一个大脑塞不下所有记忆单体 Agent 等于把所有功能塞进一个大模型对话循环里用户请求、历史对话、工具返回、中间推理、环境反馈全部挤在一个长度有限的上下文窗口里。常见的模型上下文从 32k 到 200k听着很大但真实业务里根本不够用。我那个客服 Agent最开始只处理订单查询用户发一句话Agent 调一个 SQL 工具结果返回回复用户一次任务不到 3k token。后来陆续加入商品知识问答、退款工单、投诉记录、物流查询、优惠券计算每次任务至少要经历三轮工具调用每轮调用要附带历史摘要、工具 schema、中间结果单次上下文飙升到 10k 以上。高峰期遇到用户连续追问多个任务的临时结论叠加上下文直奔 50k。这时模型开始忘事偶尔会把上一个人的订单号当成当前用户的SQL 结果里明明有优惠金额却被忽略幻觉率从 3% 涨到 15% 左右。这个现象背后不是模型能力问题而是注意力稀释。上下文越长模型对关键信息的有效注意力越差就像让一个人同时记住十件事最后每件事都会出纰漏。单体 Agent 没有选择只能把全部历史放在一个 context 里哪怕用摘要压缩压缩过程也会丢细节。Multi-Agent 可以做的第一件事就是把上下文按职责切碎订单 Agent 只关心订单表知识 Agent 只关心知识库各自维护短上下文仅在需要传递时同步核心信息。这听起来简单但解决的是单体最根本的容量瓶颈。1.2 工具调用一个大脑控制太多只手单体 Agent 通常要面对十几个甚至几十个工具。模型每轮都要在巨大工具集里做选择。工具数量一多就会出现三类典型问题。第一是工具选择冲突。比如系统里同时有根据商品 ID 查询库存和根据商品 ID 查询价格两个工具schema 又长得像模型经常选错或者选了个万能查询然后传错参数。第二是工具命名污染。几十个工具名不可避免地出现查询更新发送等近似词模型理解成同义导致调用路径混乱。第三是工具失败后的连锁反应。单体 Agent 里一个工具抛错整个 ReAct 循环往往直接中断用户看到的就是Agent execution terminated due to error.。我早期遇到这个错误提示的频率高得吓人而且很难定位因为错误信息被模型重新组织过丢掉了原始异常堆栈。工具调用本质是一个大脑控制太多只手。人脑处理复杂工作会交给不同的人而不是自己同时操作十几个设备。多 Agent 架构的自然解法就是把工具按域分给不同 Worker订单 Agent 只暴露查询订单工具知识 Agent 只暴露检索工具售后 Agent 只暴露工单创建工具。每个子 Agent 的候选工具集从 15 个降到 3 个模型选择和出错率肉眼可见地下降。工具层尽量走 MCPModel Context Protocol这类标准协议MCP 把工具封装成独立服务Worker 通过标准请求调用工具变更不影响 Agent 流程逻辑。我改造时把订单、物流、知识检索分别封装成三个 MCP server每个 Worker 只连自己需要的 server权限隔离也更干净。1.3 评估与维护单体 Agent 越改越难测单体 Agent 还有一个常被忽略的天花板工程可维护性。所有 Prompt、工具、业务逻辑揉在一个系统里排查问题靠从头到尾跑一遍看输出。改一个 prompt 里的措辞可能影响后面所有工具调用流程加了新工具老工具被误用的概率上升想针对某个子问题做回归测试又没法单独触发只能整条链路一起测。做 Agent 评测是更深层的痛点。单体 Agent 没有内部边界测它只能端到端端到端失败根本不知道是意图识别错了、工具选错、参数拼错、还是结果汇总错。评测结果接近黑盒。我后来给单体 Agent 写了十几个测试用例每次改完跑一遍成功率看似没变但上线后仍然各种幺蛾子就是因为测试粒度太粗无法暴露局部回归。Multi-Agent 把系统拆成了若干可独立评估的节点。Planner 的输出可以单独测Order Worker 的工具调用可以单独测Reviewer 的审核意见可以单独测。出了问题能快速圈定模块这是单体在工程层面无法替代的优势。另外多 Agent 系统的每个节点都能输出结构化数据方便做埋点和 trace,这让回归测试不再是看运气而是真正可量化的工程流程。2. 复杂任务为什么需要分工从单体硬扛到多 Agent 协作2.1 专业化分工带来的三大直接收益复杂任务往往有多个子目标、多种领域知识、多步操作。如果分工每个 Agent 的 prompt 可以短而专职责边界清晰上下文更短工具更少输出更稳定。三大收益第一是上下文精简每个 Agent 只看自己需要的数据注意力更集中第二是工具隔离不同 Agent 不会争抢同一个工具第三是职责可治理谁出错找谁。吴恩达在《Agent for Beginners》系列课程里总结过 Agent 设计的关键模式Reflection、Tool Use、Planning、Multi-Agent Collaboration。其中 Multi-Agent 被列为专门的设计模式不是炫技而是因为有些任务靠单 Agent 真的扛不住。比如让一个 Agent 既写代码又做代码审查再部署它的自己写自己审往往效果很差模型会倾向于给自己的代码开绿灯。拆成 Writer 和 Reviewer 两个 Agent 后审查的通过标准可以定义得更严格系统过拟合自己人的风险也小。这个逻辑和团队管理很相似一个人既是运动员又是裁判很难客观拆成两个人各自盯自己的目标整体质量才有保障。更重要的是分工能让每个 Agent 的 Prompt 设计变得极短极聚焦不再需要写一堆你是一个全能助手之类的废话模型反而更容易理解自己的角色。2.2 四种工作流模式对比Pipeline、Orchestrator-Worker、Debate、Hierarchical从我自己的项目实践看多 Agent 常见的协作模式有四种。Pipeline管道模式任务按顺序依次经过多个 Agent前一个结果是后一个输入。适合有明确依赖关系的流程比如信息抽取 Agent - 数据清洗 Agent - 报告生成 Agent。单体实现这段流程时所有环节挤在一个会话里一旦中间环节产生格式错误后面的环节全部继承错误拆开后可以每步做格式校验。Orchestrator-Worker编排-工人模式一个 Planner Agent 负责任务分解和结果汇总多个 Worker Agent 并行处理子任务。适合子任务相对独立、可以并行的场景。我的客服系统用的就是这种模式Planner 先拆单然后把订单查询、物流解析、库存查询并行派发比单体串行调用快了很多。Debate辩论模式)两个或多个 Agent 对同一问题给出答案并互相质疑最后汇总或投票。适合决策、代码审查、内容安全性评估等任务。缺点是多轮对话消耗 token 很大需要严格控制轮次和终止条件。Hierarchical层级模式主 Agent 管理多个子 Agent子 Agent 下面还可以有更细粒度的 Agent形成树状结构。适合企业级、超大型任务比如公司级的 AI 运营中台。我建议绝大多数业务先用 Orchestrator-Worker 模式因为结构清晰、可控、容易调试不需要所有 Agent 互相直接对话。Debate 虽然听起来高级但开销大且需要严格的终止条件否则容易陷入死循环。2.3 什么情况下别上 Multi-Agent避免为拆而拆必须承认不是所有任务都该上 Multi-Agent。我见过团队把一个天气查询 Agent 拆成天气数据获取 Agent和天气回复生成 Agent结果一次请求从 1 次模型调用变成 3 次成本翻倍延迟翻倍效果没有任何提升。这种任务单 Agent 显然更好。什么时候该拆我的判断标准有三条一是任务本身包含多个领域需要不同角色分别处理二是单 Agent 上下文频繁逼近上限摘要、截断、遗忘已影响到准确性三是需要多人协作式质检或反思比如代码审查、方案评审。如果三条都不占别动。另外拆也不是越多越好。每个 Agent 都有模型调用开销和编排调度复杂度。实际项目中3 到 5 个子 Agent 是最顺手的区间超过 8 个协调成本会显著上升系统开始出现三个和尚没水喝的推诿现象。这个问题后面在常见问题章节我会展开讲。3. 落地 Multi-Agent 的核心设计编排、记忆、安全与评测3.1 编排框架怎么选LangGraph、AutoGen、CrewAI、自研对比要做 Multi-Agent第一关是选编排框架。市面上的主流框架各有侧重简单对比下框架状态管理通信方式适合场景上手难度LangGraph图状态 Checkpoint状态共享/黑板复杂流程、需要人类审批、可中断恢复中等AutoGen对话消息列表多 Agent 对话研究原型、辩论模式、角色扮演较低CrewAI任务 Process 流程顺序/层级调度快速搭建业务协作流程低Dify / n8n可视化工作流节点连线低代码、非程序员团队运维低选型逻辑可以这样想如果项目需要很强的可控性有分支、循环、重试、人工审批LangGraph 这类图编排最合适如果只是几个 Agent 按固定顺序协作CrewAI 就够如果团队以产品为主没有专职算法工程师直接上 Dify 或 n8n用可视化配置把 Agent 串起来反而更稳。我这次选的是 LangGraph。原因有三一是它有明确的 State 定义所有 Agent 中间结果都写进一个全局状态天然适合 Orchestrator-Worker 模式并且中间断点可以续跑二是每个节点就是普通 Python 函数调试和单元测试非常友好三是有原生 trace 机制能把一次任务的完整调用链导出排查问题比黑盒强太多。代价是概念多刚上手会有一点学习曲线但值得。3.2 记忆架构工作记忆、长期记忆和共享记忆分离单体 Agent 只有一份会话上下文这既是记忆又是工作区又是临时草稿箱混在一起。Multi-Agent 需要把记忆拆开否则还是那个容量瓶颈。我的做法是分三层工作记忆每个 Worker Agent 在自己 Prompt 里携带的临时信息只覆盖当前任务。例如订单 Worker 只需要当前 order_id 和用户输入不需要知道另一路物流任务的结果。短期协作记忆放在全局 State 里由 Planner 维护用于记录任务清单、已完成步骤、待处理事项。相当于项目看板所有 Agent 都能读但不允许乱写。长期记忆放到向量数据库或普通业务库里由独立的 Memory Agent 统一读写供后续会话和跨用户知识沉淀使用。热词里提到的Agent 存储 working memory就是这个方向。你可以把长期记忆类比成公司知识库Vector DB 是档案柜Memory Agent 是图书管理员短期协作记忆是会议室白板工作记忆是每个人手上的便利贴。各归各位才能避免上下文爆炸。具体落地时我给 Worker 的输入模板里固定了几个字段task_description、relevant_context、tool_results。Planner 在派单时只填必要字段包得越少模型越不容易分心。长期记忆的写入则通过一个专门的总结 Agent在任务结束时从 State 中抽取关键信息再写入向量库这个设计在后来的多轮交互里效果很明显。一次会话结束后用户常问的商品优惠规则被沉淀到知识库下次直接命中不用再重复检索。3.3 通信机制直接调用、消息总线、共享状态各自适合什么多 Agent 之间怎么说话影响整个系统的耦合度。我总结三种方式。直接调用Agent A 直接调用 Agent B 的函数简单直观但 A 的代码里写死了 B 的接口以后改 B 要连带改 A适合 Agent 数量少、关系固定的场景。消息总线Agent 通过队列或事件发布/订阅通信解耦效果好但调试麻烦消息丢失、乱序、重复投递等问题都要额外处理。适合规模大、Agent 会动态增减的场景。共享状态黑板模式所有 Agent 往同一个全局状态读写数据谁需要谁去取实现最灵活。这是 LangGraph 默认的方式也是我推荐大多数项目优先考虑的方式。它避免了消息格式设计的复杂度同时状态快照就是天然的可观测性日志。黑板模式有个要小心的点共享状态的写入权要严格管理。我让每个 Worker 只写自己负责的命名空间比如results.order、results.logisticsPlanner 只读汇总如果所有人都往一个平铺字典里乱写会出现数据互相覆盖而且极难排查。这就是共享但不混乱的纪律问题。3.4 Agent 安全与权限隔离多 Agent 带来的新问题热词里有一大堆 Agent 安全相关的内容比如Agent 安全标签、LLM-based agent memory防御框架。多 Agent 确实会把安全问题放大一个 Agent 被恶意 prompt 注入它调用的工具没有权限限制可能把整个系统拖下水。最常见的攻击方式是用户输入里夹带指令让 Worker 读取不该读的数据或触发危险操作。我的建议是给每个子 Agent 做最小权限设计。工具层面每个 Worker 只挂载自己业务域内的工具且所有工具函数内部做参数白名单校验。系统层面关键操作转账、删除、发消息必须经过一个Guard Agent或人类审批节点。Guard Agent 不负责具体业务只审查工具调用是否合法相当于安全网关。另外记忆注入攻击也值得防范。如果长期记忆里被写入了恶意内容后续会话会持续中毒。我在写 Memory Agent 时增加了写入内容过滤对记忆内容做关键词检查和嵌入相似度检查异常内容直接丢弃避免污染知识库。这些细节不会让文章显得炫酷但生产环境真的能救命。3.5 评测体系多 Agent 系统如何验证与回归测评是 Agent 开发里最容易被轻视的部分但热词里搜得到Agent 评测。单体 Agent 测起来黑盒多 Agent 拆开后反而给了我们局部评测的机会。我建议至少分三层。第一层节点级评测。对 Planner准备 50 条任务描述检查拆分出的子任务是否完整、是否包含必要的依赖关系对 Worker准备每个域的工具调用样本检查工具选择准确率和参数正确率。第二层端到端评测。构造完整的用户会话集跑完整流程统计成功率、平均延迟、平均 token 消耗。第三层回归评测。每次改 Agent Prompt 或工具 schema 后把前两层测试跑一遍对比指标曲线。没有回归评测多 Agent 系统改起来会非常心虚。我在项目里用 Python 脚本把这些评测集固化下来每天跑一次输出一个指标 JSON。这个习惯帮我抓到了很多看似偶发的回归问题比如某次升级模型后Planner 突然总是把订单查询拆成两步导致 Worker 互相等待就是靠回归用例发现的。4. 实操拆解用 LangGraph 把单体客服 Agent 改造成 Multi-Agent4.1 改造前的单体系统长什么样我做的是电商客服 Agent前期是一个单体 ReAct Agent绑定一个函数调用模型挂着一堆工具查订单、查物流、查商品知识、创建工单、查优惠券、计算退款金额。用户提问后Agent 自己决定先调哪个工具、下一步做什么。实际运行中出现几个问题连续对话后上下文太长模型把不同用户的订单搞混工具选择频繁出错查物流和查订单经常互选某个工具网络超时后整个 Agent 直接返回Agent execution terminated due to error.用户只能再问一遍。单看每个问题好像都能通过优化 Prompt 解决但改一个另一个又冒出来典型的按下葫芦浮起瓢。我后来把用户消息和工具输出全部打了日志发现单体系统里一次正常查询平均要经历 4 次模型调用其中至少 1 次是在纠正前面的错误选择。这个浪费在拆成多 Agent 后基本消失了因为 Worker 的选择空间被限制得很小。4.2 改造后的系统拓扑与角色分工最终落地的是 Orchestrator-Worker 一个 Reviewer 的结构Agent职责使用工具记忆范围Planner理解意图拆分任务维护计划状态无只做 LLM 推理短期协作记忆Order Worker查询订单、计算退款订单查询、退款计算当前订单上下文Logistics Worker查询物流信息物流查询当前物流单号KBase Worker知识库检索商品知识检索 RAG当前问题上下文Ticket Worker创建与更新工单工单创建/更新当前工单内容Reviewer检查最终回复的准确性与合规性无LLM 推理当前汇总结果Planner 不调用任何业务工具它只负责读用户消息输出一个 JSON 格式的任务列表然后按依赖关系排队执行。Order 和 Logistics 两个 Worker 互不依赖可以并行KBase 和 Ticket 也可以并行。所有 Worker 结果写入全局 State汇总阶段由一个汇总节点拼装最终答复Reviewer 再对最终答复做一次合规检查不合格就打回重做。这里需要强调每个 Worker 只允许读写自己对应的 namespace从机制上防止越权。4.3 基于 LangGraph 的核心代码骨架我用 LangGraph 实现的核心部分大概长这样去掉业务细节保留模式from typing import TypedDict, List from langgraph.graph import StateGraph, END class WorkState(TypedDict): user_message: str plan: list[dict] # [{agent: order, task: ..., status: pending}] results: dict # 各 worker 写入按 agent 名分 namespace final_reply: str review_pass: bool retry_count: int def planner_node(state: WorkState) - dict: plan llm_plan( state[user_message], available_agents[order, logistics, kbase, ticket] ) return {plan: plan, retry_count: state.get(retry_count, 0)} def dispatch_node(state: WorkState) - dict: # 实际项目里这里会按依赖关系并发执行 results {} for item in state[plan]: agent_func AGENTS[item[agent]] results[item[agent]] agent_func( item[task], state[user_message] ) return {results: results} def reviewer_node(state: WorkState) - dict: reply build_reply(state[results]) is_pass review_reply(reply) return {final_reply: reply, review_pass: is_pass} def should_replan(state: WorkState): # review 不通过的情况下最多重试一次 if not state[review_pass] and state.get(retry_count, 0) 1: return planner return END graph StateGraph(WorkState) graph.add_node(planner, planner_node) graph.add_node(dispatch, dispatch_node) graph.add_node(reviewer, reviewer_node) graph.set_entry_point(planner) graph.add_edge(planner, dispatch) graph.add_edge(dispatch, reviewer) graph.add_conditional_edges( reviewer, should_replan, {planner: planner, END: END} ) app graph.compile()这段代码重点是所有节点接收state并返回局部更新LangGraph 自动合并到全局状态。plan和results形成了整个系统的事实来源。Reviewer 不通过时通过条件边把任务打回 Planner 重新规划但设置了重试上限避免死循环。实际工程里还要接 Checkpoint 持久化把状态存到数据库这样进程崩溃后可以恢复。4.4 改造后的实测数据与调优过程改造后的第一个版本并不顺利。Planner 拆出的任务太碎一个订单和物流一起查的问题被拆成四个子任务产生大量额外模型调用。我后来给 Planner 加了一条指令优先合并并行查询不超过 2 个子任务并在评测用例上做了约束。第二版开始性能出现明显变化指标单体 AgentMulti-Agent单次任务平均上下文 Token12k3.8k端到端成功率68%91%工具调用错误率17%6%平均响应时长14s8s单次任务成本100% 基线约 60%需要说明的是这个成本下降有一部分来自并行执行和 token 减少但多 Agent 本身有额外的 Planner 和 Reviewer 开销。如果子任务串行太多成本可能不降反升。我在调优时用了一个很土但有效的方法在 State 里记录每个 Agent 的 token 消耗拿一次真实请求的数据出来看凡是消耗 top3 的节点逐个优化它的 prompt 或减少传入字段效果立竿见影。另外一个细节是并行度。工作流里 Order 和 Logistics 可以并行但我第一版用 for 循环串行执行白白浪费了并行收益。后来改成ThreadPoolExecutor(max_workers2)并发调用两个 Worker延迟从 14 秒降到 8 秒主要就是并行查询的功劳。如果你的 Agent 不对共享资源写入放心并行工具调用本身是 IO 密集型的很适合并发。5. 常见问题与排查技巧实录5.1 子 Agent 互相推诿任务悬空怎么办多 Agent 系统跑一段时间后最容易遇到的怪现象是一个任务谁都没认领用户等很久没有回复。根因通常是 Planner 拆出的任务描述太模糊Worker 认为自己不该负责这个子问题于是返回无法处理。单体 Agent 不会出现这个问题因为整条链路由一个模型负责至少会给出一个猜测。我的解决办法有两个。第一在 Planner 的输出格式里强制要求每个子任务必须包含expected_agent字段只有能在允许的 agent 列表里找到对应值的任务才会被 dispatch否则直接拒绝并触发重新规划。第二给 Worker 加了一个不确定就输出 UNKNOWN的约定而不是编造答复Planner 看到 UNKNOWN 会重新分配或给用户升级到人工。这样从机制上消灭了悬空而不是靠运气。这两个改动加进去后线上已读不回类投诉基本清零。核心思路就是让每个 Agent 知道自己能做什么、不能做什么并且把不确定当成合法输出而不是逼模型硬答。5.2 多 Agent 反而更贵、更慢怎么控制成本有段时间我被团队抱怨成本翻倍细查日志发现是 Planner 每轮都要重新读取全部历史 State导致上下文膨胀。优化手段包括只给 Planner 传plan和results的最新摘要不传原始工具输出把大段 RAG 检索结果剪到 Top-3对小任务使用更便宜的轻量模型只有复杂规划才调用旗舰模型。效果很显著成本回到可接受范围。另一个成本陷阱是 Reviewer 过多。我之前给每个 Worker 后面都接了一个审查节点等于每次调用都翻倍。后来改成只有最终汇总时做一次 Reviewer 审查子任务级别的质量用更严格的工具 schema 校验来兜底成本直接砍半。所以控制成本的第一步不是换便宜模型而是削减不必要的模型调用。5.3 经常看到 Agent execution terminated due to error怎么排查这个报错在单体系统里特别常见。拆成多 Agent 后每个工具调用失败都会被封装到对应 Worker 的返回值里而不是直接把整个执行链干掉。我在每个 Worker 外面套了异常捕获把异常信息转换成统一的error字段返回给 PlannerPlanner 根据错误类型决定重试、换工具、还是跳过该子任务。同时LangGraph 的 Checkpoint 机制可以保存断点任务失败后从断点恢复而不是从头开始。排查时我先看 trace 链路找出失败节点。如果在 Tool 层看工具 API 返回的原始错误如果在 Worker 层看模型解析工具输出时是否格式不对。大部分execution terminated due to error的根子其实是工具返回的 JSON schema 不符合模型预期而不是网络错误。把工具返回格式统一成纯 JSON 并加上错误码字段这类问题就少了一大半。这个经验来自我反复被同一个报错折磨后的总结比看任何文档都直观。5.4 多 Agent 系统怎么调试和观测单体 Agent 调试靠打印全部上下文多 Agent 必须依靠结构化观测。我用 LangSmith 和自建的日志表记录每次运行的消息 ID、节点名、工具名、token 数、耗时。每个节点都往一个日志队列里写结构化事件最后汇总成一条 tracing 链路。这样线上用户报问题时我能直接按用户会话 ID 捞起整条调用链看到具体哪个 Agent 在什么状态下做了错误决定。还有个观测量是Plan 的正确率。我在评测集里加了一项对每个测试用例人工标记 Planner 的理想拆分方案然后用自动化脚本对比模型实际拆分统计任务数、顺序、字段的符合程度。这个指标比只看端到端成功率敏感得多很多端到端看不出来的退化在 Plan 正确率上会先亮红灯。建议所有多 Agent 系统都把 Plan 正确率纳入日常监控。最后再分享一个体验上的细节。多 Agent 不是拆完就结束它需要持续维护。我的团队现在每两周会复盘一次线上 trace找出虽然成功了但绕了远路的样例比如用户本来只需要查订单Planner 却让 KBase 和 Ticket 也跑了一遍。把这些冗余路径修掉成本能再降一截。在实际维护中我最大的体会是单体 Agent 拼的是模型智商多 Agent 拼的是架构纪律。模型再聪明没有清晰的任务边界、状态管理和安全网关复杂业务迟早会塌。但如果从一开始就把上下文切碎、职责分清、评测固化复杂任务反而比单体更稳、更可维护。这也正是我始终推荐大家认真考虑 Multi-Agent 的原因。