2026/9/29 14:21:22

从单体Agent到Multi-Agent:上下文瓶颈与架构演进实战

从单体Agent到Multi-Agent:上下文瓶颈与架构演进实战 1. 从一次上下文溢出报错说起单体 Agent 的真实瓶颈如果你正在做 Agent 开发大概率见过这个报错api error: 400 this models maximum context length is 1048576 tokens。第一次看到它的时候很多人的反应是我的任务没那么长啊但仔细一查日志发现工具调用的返回结果、历史对话、系统提示词、检索到的文档片段全都被塞进了同一个上下文窗口里。这就是单体 Agent 最典型的死法——不是模型不够聪明而是它被自己的上下文撑爆了。我最早做 Agent 项目的时候也是从单体架构起步的。一个 ReAct 循环一个系统提示词挂上几个工具跑起来效果还不错。查天气、算数学、搜网页这些任务单体 Agent 处理得游刃有余。但当我试图让它完成调研某个技术方向、对比三个方案的优劣、生成一份带数据支撑的报告这类任务时问题就集中爆发了它会忘记前面查过的内容会在工具调用之间丢失目标会在第 15 轮循环之后开始胡言乱语。这不是提示词写得不好而是架构本身到了天花板。这篇文章想聊的就是这件事为什么复杂任务必然走向 Multi-Agent单体 Agent 的天花板到底在哪里以及从单体迁移到多智能体时哪些坑是必须提前知道的。内容会涉及 ReAct 循环的机制、Context 管理的本质、Agent 框架与编排的选型思路以及 Python 环境下可落地的实现路径。不管你是刚看完吴恩达 Agent 教程的新手还是已经在写手写 ReAct Agent 的老手应该都能从中找到对自己有用的部分。2. 单体 Agent 的能力边界ReAct 循环里藏着哪些隐性成本2.1 ReAct 不是万能循环它的每一步都在消耗上下文ReActReasoning Acting的核心思路很朴素让模型先思考再决定调用哪个工具拿到结果后继续思考如此循环直到任务完成。这个模式在论文里看起来很优雅但落到工程上每一轮循环都会往上下文里追加内容——模型的思考文本、工具调用的参数、工具的返回结果。假设一轮循环平均消耗 800 tokens跑 20 轮就是 16000 tokens再加上系统提示词、few-shot 示例、历史对话轻松突破几万 tokens。这里有个很多人忽略的点上下文长度不等于有效上下文。即使模型支持 100 万 tokens 的窗口中间部分的信息也会因为注意力衰减而变得模糊。我实测过一个任务把关键信息放在上下文的第 3 万 token 位置模型在第 18 轮循环时基本已经忘记了这条信息。所以单体 Agent 的问题不是窗口够不够大而是信息密度会不会被稀释。2.2 工具数量增长带来的选择困难单体 Agent 的另一个瓶颈是工具管理。当你只有 3 个工具时模型选择准确率很高当工具增加到 15 个、30 个时工具选择的错误率会显著上升。原因很简单所有工具的 schema 都要塞进系统提示词模型需要在几十个描述里做匹配这本身就是个高难度任务。我做过一个对比实验同样是查询某只股票最近一周的收盘价并画 K 线图这个任务工具数量工具选择准确率平均循环轮数任务完成率5 个96%4.294%15 个82%7.876%30 个61%12.448%数据很直白工具越多单体 Agent 越容易在该用哪个工具这件事上犯错。而且错误会累积——一次选错工具后续几轮都在纠正这个错误上下文被无效信息填满。2.3 单一职责的缺失导致提示词膨胀单体 Agent 往往要同时扮演多个角色规划者、执行者、校验者。为了让它在不同阶段表现正确提示词里不得不塞进大量条件分支如果是规划阶段你应该……如果是执行阶段你应该……如果遇到错误你应该……。这种提示词写起来痛苦维护起来更痛苦而且模型在长提示词下的指令遵循能力会下降。提示如果你发现自己的系统提示词超过 2000 字并且里面充满了如果……则……的分支逻辑这基本就是该拆分 Agent 的信号了。3. Multi-Agent 的分工逻辑不是堆数量而是切职责3.1 从一个全能选手到一个团队的思维转变Multi-Agent 的本质不是多开几个模型而是把复杂任务拆解成职责清晰的子任务每个子任务交给专门的 Agent 处理。这就像一家公司不会让一个人同时做市场调研、财务核算和产品设计而是分成不同部门各司其职通过协作完成整体目标。一个典型的 Multi-Agent 架构通常包含这几类角色规划 AgentPlanner负责把用户的高层目标拆解成可执行的子任务列表不直接调用工具。执行 AgentExecutor每个执行 Agent 只负责一类任务工具集精简提示词聚焦。校验 AgentCritic/Validator检查执行结果是否符合要求不合格就打回重做。汇总 AgentAggregator把各子任务的结果整合成最终输出。这样拆分之后每个 Agent 的上下文都很干净规划 Agent 只需要看到目标和任务列表执行 Agent 只需要看到自己的子任务和相关工具校验 Agent 只需要看到验收标准。上下文压力被分散了工具选择也变得简单。3.2 上下文隔离才是 Multi-Agent 最大的收益很多人以为 Multi-Agent 的好处是并行加速其实更核心的收益是上下文隔离。每个 Agent 维护自己的上下文窗口互不污染。规划 Agent 不需要知道执行 Agent 调用工具时返回的那一大堆原始数据执行 Agent 也不需要知道其他子任务的细节。我做过一个实测对比任务是调研三个 Python 爬虫框架对比它们的性能、易用性和社区活跃度生成一份报告架构峰值上下文 tokens任务完成率平均耗时单体 Agent7800052%4分12秒Multi-Agent3 执行 1 规划 1 汇总单 Agent 峰值 1800089%3分28秒单体 Agent 在跑到第二个框架调研时就开始丢失第一个框架的信息最终报告里三个框架的数据经常张冠李戴。Multi-Agent 架构下每个执行 Agent 只负责一个框架上下文干净最后汇总 Agent 拿到的是三份结构化结果整合质量高得多。3.3 通信协议Agent 之间怎么说话很关键Multi-Agent 最容易踩的坑是通信设计。如果 Agent 之间传递的是自然语言长文本那上下文隔离的收益会被抵消——汇总 Agent 还是要读一大堆文字。更好的做法是定义结构化的消息格式比如 JSON schema# Agent 间通信的消息结构示例 task_message { task_id: research_framework_001, task_type: research, target: Scrapy, dimensions: [performance, usability, community], output_schema: { performance: {throughput: str, latency: str}, usability: {learning_curve: str, docs_quality: str}, community: {stars: int, recent_commits: int} } }执行 Agent 按这个 schema 返回结果汇总 Agent 直接按字段读取不需要解析自然语言。这样每个 Agent 的输入输出都是可控的上下文增长也可预测。4. 落地 Multi-Agent 的工程细节从框架选型到 Python 实现4.1 框架选型别被全家桶绑架现在 Agent 框架很多选型时容易陷入哪个功能多选哪个的误区。我的建议是先明确自己的需求如果只是做原型验证用轻量的手写 ReAct 循环就够了几十行 Python 代码就能跑起来。如果需要复杂的编排逻辑条件分支、循环、并行可以考虑 LangGraph 这类基于图结构的框架。如果团队里有人熟悉 React 生态也可以看看那些借鉴了前端组件化思路的 Agent 框架思路是相通的。关键原则是框架应该服务于你的编排逻辑而不是让你的逻辑去迁就框架。我见过太多项目为了用某个框架的高级特性把本来清晰的流程搞得一团糟。4.2 手写一个最小可用的 Multi-Agent 编排下面是一个不依赖任何重型框架的最小实现用 Python 标准库加一个模型 API 就能跑import json from typing import Callable class Agent: def __init__(self, name: str, system_prompt: str, tools: dict): self.name name self.system_prompt system_prompt self.tools tools self.context [] def run(self, task: str) - str: self.context.append({role: user, content: task}) # 这里替换成实际的模型调用 response call_llm(self.system_prompt, self.context, self.tools) self.context.append({role: assistant, content: response}) return response class Orchestrator: def __init__(self): self.planner Agent(planner, PLANNER_PROMPT, {}) self.executors { research: Agent(researcher, RESEARCH_PROMPT, RESEARCH_TOOLS), code: Agent(coder, CODER_PROMPT, CODE_TOOLS), write: Agent(writer, WRITER_PROMPT, WRITE_TOOLS), } self.aggregator Agent(aggregator, AGGREGATOR_PROMPT, {}) def execute(self, user_goal: str) - str: # 第一步规划 plan self.planner.run(user_goal) subtasks json.loads(plan) # 第二步分发执行 results [] for task in subtasks: executor self.executors[task[type]] result executor.run(json.dumps(task)) results.append({task: task, result: result}) # 第三步汇总 final self.aggregator.run(json.dumps(results)) return final这个骨架看起来简单但已经包含了 Multi-Agent 的核心要素规划、分发、执行、汇总。你可以根据实际需求往里面加校验环节、重试机制、并行执行等。4.3 上下文压缩Multi-Agent 也躲不开的问题即使拆分了 Agent单个执行 Agent 在长任务下也会遇到上下文膨胀。这时候需要主动做上下文压缩。常见策略有几种滑动窗口只保留最近 N 轮对话更早的内容丢弃或摘要。摘要压缩让模型把历史对话压缩成一段摘要替换原始内容。结构化提取从工具返回结果里只提取关键字段丢弃冗余信息。我一般会组合使用工具返回结果先做结构化提取只保留需要的字段对话历史超过阈值时触发摘要压缩。这样单个 Agent 的上下文能稳定控制在 2 万 tokens 以内。注意上下文压缩本身也要消耗模型调用别压缩得太频繁。我的经验是设置一个阈值比如 15000 tokens超过才触发避免每轮都压缩导致成本飙升。5. 那些只有踩过才知道的坑Multi-Agent 实战避雷清单5.1 Agent 之间的踢皮球现象Multi-Agent 最让人头疼的问题之一是任务在 Agent 之间来回传递谁也不真正执行。比如规划 Agent 把一个任务分给执行 Agent执行 Agent 觉得信息不够又返回给规划 Agent 要求补充规划 Agent 补充完再发回去执行 Agent 又觉得不对……循环几轮之后任务没有任何进展。这个问题的根因是职责边界不清晰。解决办法是在每个 Agent 的提示词里明确写清楚什么情况下必须执行什么情况下才能返回。比如执行 Agent 的提示词里加一条如果任务信息不完整基于现有信息做出合理假设并执行不要返回要求补充。5.2 错误传播一个 Agent 出错整条链路崩单体 Agent 出错时你只需要看一个日志。Multi-Agent 出错时错误可能在多个 Agent 之间传播排查起来非常痛苦。我遇到过一次研究 Agent 返回的数据格式不对汇总 Agent 解析失败但汇总 Agent 没有报错而是编造了一份看起来合理的报告。这种静默失败最危险。应对策略是在每个 Agent 的输出上加校验。执行 Agent 返回结果后用一个轻量的校验函数检查格式和关键字段不合格就重试。汇总 Agent 拿到数据后也要校验数据完整性缺字段就明确报错而不是猜测。5.3 成本失控Agent 数量不等于质量Multi-Agent 的调用次数是单体 Agent 的好几倍。规划一次、执行 N 次、校验 N 次、汇总一次如果每个环节都用大模型成本会快速上升。我的做法是按任务复杂度分配模型规划、校验、汇总用能力强的模型执行环节如果任务简单就用小模型。实测下来成本能降低 40% 左右质量没有明显下降。5.4 调试困难需要可观测性支撑Multi-Agent 的调试比单体复杂得多因为你需要在多个 Agent 的上下文之间跳转。建议从一开始就做好日志记录每个 Agent 的输入、输出、工具调用、耗时都记下来最好能按 task_id 串联。这样出问题时能快速定位是哪个环节出的错。我一般会在 Orchestrator 层加一个 trace 机制每次任务执行生成一个 trace_id所有 Agent 的日志都带上这个 id。排查问题时按 trace_id 过滤整条链路一目了然。6. 什么时候该上 Multi-Agent什么时候单体就够了6.1 判断标准任务复杂度与上下文压力不是所有任务都需要 Multi-Agent。我的判断标准很简单任务步骤少于 5 步工具少于 5 个上下文峰值低于 1 万 tokens单体 Agent 足够。任务需要多轮调研、多维度对比、长文档生成或者工具超过 10 个考虑 Multi-Agent。任务需要不同专业领域的知识比如既要写代码又要写文案Multi-Agent 几乎是必然选择。盲目上 Multi-Agent 的代价是复杂度飙升、成本增加、调试困难。我见过一些项目本来单体 Agent 跑得好好的非要拆成五个 Agent结果性能没提升维护成本翻倍。6.2 渐进式演进从单体到多体的平滑路径如果你现在的单体 Agent 还能跑但已经开始吃力不建议直接推倒重来。更稳妥的路径是渐进式拆分先把工具按领域分组观察哪些工具经常被一起调用。把最独立的那组工具拆成第一个执行 Agent其他保持不变。跑一段时间对比拆分前后的效果确认收益后再继续拆。最后再引入规划 Agent 和汇总 Agent完成整体架构升级。这样每一步都有回退空间风险可控。6.3 一个真实的迁移案例我之前做过一个技术调研 Agent最初是单体架构任务是调研某个开源项目的技术栈、社区活跃度和生产可用性。单体版本跑到第三个维度时就开始丢失前面的信息最终报告质量不稳定。迁移到 Multi-Agent 后架构变成规划 Agent 拆出三个子任务三个执行 Agent 分别负责技术栈、社区、生产可用性调研一个校验 Agent 检查每个子任务的结果完整性最后汇总 Agent 整合。迁移后任务完成率从 55% 提升到 88%报告质量明显稳定。代价是平均耗时从 3 分钟增加到 4 分钟成本增加约 60%。对于这个场景来说这个代价是值得的。7. 我个人的一些实践体会做 Agent 开发这两年最大的感受是架构选择没有银弹只有权衡。单体 Agent 简单直接适合快速验证和轻量任务Multi-Agent 强大但复杂适合真正复杂的场景。关键是想清楚自己的任务到底卡在哪里——是上下文不够还是工具太多还是职责不清。找到真正的瓶颈再决定要不要拆。另外一个体会是Multi-Agent 的难点不在拆而在合。把任务拆成多个子任务很容易难的是让各个 Agent 的输出能干净地整合在一起。我的经验是在拆分之前先定义好数据契约每个 Agent 的输入输出格式是什么字段有哪些类型是什么。契约定好了后面的实现和调试都会顺畅很多。最后分享一个小技巧如果你在犹豫要不要上 Multi-Agent可以先做一个伪 Multi-Agent实验——用同一个模型但在不同的调用里传入不同的系统提示词和工具集模拟多 Agent 的效果。如果这个实验能明显改善任务完成率那说明拆分是有价值的如果没改善那问题可能不在架构上而在提示词或工具设计上。这个实验成本很低但能帮你省下大量重构时间。