最近一年我大部分精力都放在 Agent 的落地项目上,从零搭过框架,也接手过别人留下的框架,还帮团队拆过好几套跑不动的“重型架构”。如果要我说这一年里对效果提升最大的一次改动是什么,我的答案很直接:把架构删了。
做 Agent 的人很容易陷入一个惯性:任务一复杂,第一反应就是上多层编排、上记忆模块、上多智能体分工。我也不例外。去年上半年,我曾经在一个项目上用了一套看起来很完整的架构,结果每次改需求都要动五六个模块,模型的表现还越来越差。后来我花了差不多两周时间,把那套架构一层层拆掉,最后只留下一个几乎“没有架构”的最小闭环。效果反而全面变好:成功率更高,延迟更低,Token 消耗更少,团队迭代速度也上来了。
这篇文章就围绕“删架构”这件事展开。哪些东西可以删、为什么删了反而更好、什么时候又不能乱删,以及我在实操中踩过的坑。如果你是刚接触 Agent 的新手,这篇文章可以帮你少走一段“过度设计”的弯路;如果你已经做了一段时间 Agent,正被自己搭的框架搞得头大,那这篇文章很可能就是你现在需要的那剂解药。
1. 我最初是怎么把 Agent 做“重”的
1.1 当时那套架构的完整结构
去年年初,我做第一个正式交付的 Agent 项目时,参考了当时社区里流行的一套设计,一共分了五层:
- 调度层:一个中央协调器,负责根据任务类型把请求分发给不同的子智能体。
- 记忆层:短期记忆用对话列表存,长期记忆挂了向量库,还有一层语义缓存。
- 规划层:任务进来先拆解成子任务,生成执行计划,再让执行模块逐一完成。
- 工具层:封装了工具注册、参数校验、重试、超时、权限校验这些逻辑。
- 多智能体协同层:研究员、写作员、审校员等角色各自独立,通过消息队列传递中间结果。
那套系统加上配置文件、prompt 模板、数据库表结构,代码量大概是五六千行。说实话,我当时写的时候是有成就感的,毕竟架构图一画出来,各层之间职责分明,看起来特别“工程化”。
1.2 当时为什么选择这种设计
现在回头想,选择重型架构的原因很现实:
- 社区里的最佳实践、框架默认推荐的都是这类复杂编排,照着做心里踏实。
- 项目规划阶段要给团队展示“工程化能力”,层数越多看起来越专业。
- 大家默认复杂任务必然需要复杂流程,单靠提示词怎么能处理长链路任务。
- 第三个隐藏原因是虚荣心,架构图画得越复杂,越觉得自己在做一件有门槛的事。
但项目跑起来之后,问题开始一个一个显性化。先是响应变慢,然后是 Token 账单吓人,再后来是改需求动辄改十几个文件。真正让我下决心删架构的,是一次性能评估:同一个任务,旧架构跑出来的效果,竟然不如一个只有三层结构的临时 Demo。那次的冲击非常大。
2. 重型架构让效果变差的三个真实原因
2.1 每层抽象都在吃 Token,模型在给流程“打工”
这是一个最基础、也最容易被忽略的问题:大模型每走一步,都要重新读一遍上下文。任务经过调度层、规划层、多智能体层,每个模块都往上下文里塞东西。最后模型看到的上下文里,真正和用户任务相关的信息可能只占三成,剩下全是流程指令、角色设定、中间结果标记。
我举一个真实例子。某文档问答任务,用户只是问“这份文档里有没有提到支付流程”,在旧架构里会走意图识别、任务规划、检索、答案生成、审校五个环节,累计消耗大概 8000 Token,响应要 4 到 6 秒。后来我用最直接的方式重写:给模型一个搜索工具,让它自己翻文档,1200 Token、1 秒出头就能返回正确答案。
这个问题的本质可以类比成一个组织:三个人能干完的活,非要配一个分管副总、两个总监和一个项目经理,每一级都在写汇报材料。模型就是那个真正干活的员工,却被各种流程文档淹没。
Token 不只是成本问题,也是质量问题。模型注意力是有限的,上下文越臃肿,模型越容易漏掉关键信息。就像一个员工的工位堆满了无关纸张,那份真正重要的合同反而找不到了。
2.2 中间信息不落“地”,错误层层放大
重型架构的第二个坑是错误累积。规划层生成一份计划,执行层照着做,审校层再做检查。但问题是,整个链条里每一层处理后的中间结果,都只是内存里的一个对象,没有真实的数据校验。一旦规划层对用户任务的理解出现偏差,后面所有层都会沿着这个偏差往下走。
更麻烦的是,审校层往往只是检查“内部一致性”——前面的结论和后面的结论是否自洽,而不是去验证“结论是否和真实数据相符”。于是系统会非常自信地输出一个结构完整、逻辑自洽、但根上就错的结果。
我印象最深的一次,某数据分析 Agent 在旧架构下跑一个数据复盘任务,规划层把“近三十天”理解成了“近三个月”,后面的检索、计算、报告生成全部基于这个错误的时间范围。审校层把所有结论都复核了一遍,愣是没发现问题,最后交付了一份完全错误的周报。问题不在模型能力,而在链条太长,中间没有任何一步去对照原始需求。
错误累积的数学很直接:假设单步准确率 95%,一个五步的链条,端到端准确率就掉到 77%;如果单步只有 90%,五步之后只剩 59%。而一个单步闭环,哪怕单步准确率只有 88%,它也只需要承担一步的损失。
2.3 找 bug 变成“翻框架源码”,迭代速度被拖垮
重型架构的第三个坑是调试成本。任务出错时,第一件事不是看模型输出,而是查消息队列有没有丢消息、JSON 解析是不是挂了、重试逻辑是不是触发了、调度器是不是把任务分给了错误的子智能体。
有一段时间,团队改一个 prompt 都要半小时才能生效,因为 prompt 藏在某个子智能体的配置文件里,而这个配置文件的加载依赖框架的初始化顺序。我花在“理解框架在干什么”上的时间,比花在“让模型把事做对”上的时间还多。
这其实是很多 Agent 项目悄悄失败的原因:大家以为问题出在模型,实际是出在流程本身。过重的架构就像一层毛玻璃,你想看清模型真实的行为,却被中间那层滤掉了。
3. 删完之后:我最终留下的最小闭环
3.1 核心循环其实只有一条
用代码来描述,整个循环大概是这个样子:
def run_agent(user_task, tools, model_fn, max_steps=8): messages = [{"role": "system", "content": SYSTEM_PROMPT}] messages.append({"role": "user", "content": user_task}) for _ in range(max_steps): response = model_fn(messages) messages.append({"role": "assistant", "content": response}) action = parse_action(response) # 解析结果只有两种:要么调用某个工具,要么给出最终答案 if action["type"] == "final": return action["answer"] tool_result = execute_tool(tools, action["tool"], action["args"]) # 工具返回统一截断,防止上下文被撑爆 messages.append({ "role": "user", "content": f"工具[{action['tool']}]返回:\n{truncate(tool_result, 2000)}" }) return "达到最大步数,返回当前结论"没有规划器、没有记忆模块、没有多智能体消息总线。模型每轮看的是“系统提示词 + 历史对话 + 最新的工具返回”,然后自己决定下一步是继续调工具还是给出答案。
这个循环为什么有效?因为它把决策权完全交给了模型,而不是让一整套流程替模型做决策。模型的上下文里只有真正和任务相关的信息,不会被各种流程脚手架稀释。这不是我拍脑袋想出来的,是拿旧架构和新循环在同一组任务上反复对比之后,数据告诉我的结论。
3.2 没有“记忆模块”之后,我用几条纪律替代它
原来有独立的记忆模块,后来删了。替代它的不是新模块,而是几条非常具体的上下文管理纪律:
- 系统提示词控制在 1000 字以内,只写角色的工作准则和工具清单,不写具体业务细节。
- 每轮工具返回统一截断到 2000 字。超长文档不做全文投递,而是先切片,再用检索工具去查。
- 历史对话超过一定规模(比如累计约 1 万字)时,先把前面的内容压缩成一段摘要,再用摘要替换最旧的部分。摘要的生成也交给同一个模型,用一条固定指令触发。
- 如果用户上传大文件,先做预处理,把文件切成带编号的片段,然后给模型一个索引,让它自己选择查询哪些片段。
这些规则我没有写成类,而是直接写在系统提示词里。好处是逻辑清晰、可解释性强,想改规则只需要改一段文字,不需要改代码、不需要发版。说白了,就是把“架构层”的决策,降维成“数据层”和“提示词层”的决策。
3.3 工具层只保留三个抽象
原来的工具层有注册、校验、重试、超时、权限、日志,总共六个模块。删到最后我只保留了三个:
- 注册表:把工具名、工具描述、执行函数登记进一张表。
- 权限开关:涉及外部写操作或敏感操作的工具,默认要求用户确认,不在模型侧直接执行。
- 错误归一化:工具抛出的异常统一转成一行人类可读的文本,塞回给模型,让模型自己尝试解释或换一种调用方式。
这三个抽象不是给流程用的,是给“模型的输入和输出”用的。它们不参与决策,只负责让模型拿到干净、够用、安全的信息。其余的,比如重试、超时,用简单的装饰器在外层解决,不再单独成模块。工具层变薄之后,新增一个工具的成本从“改六个文件”变成了“写一个函数 + 加一行注册”。
4. 一场真实的对比:某客服分流智能体重构前后
4.1 重构前的多智能体方案
去年下半年,我负责的某客服分流智能体 Demo 进入第二轮迭代。这个项目目标很明确:用户发来一段问题,系统判断意图,决定是直接答复、查订单、还是转人工。
第一版我用的是多智能体方案:一个意图识别智能体、一个情绪识别智能体、一个分流决策智能体,外层再挂一个协调器。每个智能体都有自己的系统提示词,协调器负责把用户消息广播给三个子智能体,等三份结果都回来再汇总决策。加上重试、超时、日志,代码接近六千行。
这个方案跑起来之后问题很明显:三个智能体看到的是同一份用户消息,等于同一份输入被解析了三次;协调器必须等最慢的那个返回才能决策;而且三个智能体输出格式有小差异,协调器经常因为解析其中一个字段失败而整体报错。
4.2 重构后的单智能体方案
重构时我删掉了三个子智能体和协调器,只保留一个智能体,给它注册了三个工具:查订单工具、查常用答复模板工具、发起转人工指令。系统提示词只写了三件事:这个智能体是客服助手、遇到哪些情况用哪个工具、拿不准就转人工。
用户消息进来之后,不经过任何中间模块,直接进入上一节那个最小循环。模型自己会判断:这个问题要不要查订单,要不要翻模板,要不要直接给出答复。只有当它明确判断需要转人工时,才调用转人工工具。
4.3 重构前后的指标对比
| 指标 | 重构前(多智能体) | 重构后(单智能体最小闭环) |
|---|---|---|
| 意图识别准确率 | 91% | 94% |
| 端到端任务成功率 | 83% | 95% |
| 平均响应时长 | 2.8 秒 | 1.2 秒 |
| 单请求平均 Token 消耗 | 5200 | 2100 |
| 核心代码量 | 6000 行 | 1200 行 |
| 新需求从提需求到上线 | 3 天 | 0.5 天 |
注意:准确率数据来自内部评估集,场景有限,不同项目数字会有差异,但“成功率上升、Token 下降、迭代变快”这个趋势是稳定的。
4.4 为什么差距这么大
端到端成功率从 83% 提到 95%,不是因为模型底层能力突然变强,而是失败面变小了。旧方案里有三个子智能体加一个协调器,任何一个环节解析失败、超时、或者子智能体给出的结果被协调器误解,都会变成一次失败。删掉之后,失败的来源就只剩一个:模型在单个环节里判断错了。
Token 消耗减半,是因为同一个任务不再被三个智能体各读一遍,也不再需要协调器在最后把三份结果汇总成一份。响应时长降低,是因为少了两轮调度等待。
最让我意外的是迭代速度的变化。重构之后,要加一类新的用户问题,只需要在工具表里加一个工具,或者在系统提示词里加一条规则,改完立刻可测。而旧架构里,加一个新意图往往需要同步改三个子智能体和协调器,一次需求改动动辄十几个文件。
5. 什么时候别跟风“删架构”
5.1 判断该不该删,先看三条标准
虽然我这一年靠删架构拿到了效果提升,但我并不主张无脑删。删之前先自问三个问题:
第一,你有没有可靠的评估集?如果没有,先建一个。删除架构的理由必须是数据,不是感觉。我重构客服分流项目之前,先拿三个月的历史对话做了标注数据集,用同一套测试集测旧方案和新方案,才有底气往下走。
第二,任务真正需要的操作步数有多少?如果典型任务只需要几步工具调用,简单循环就够;如果任务需要几十步独立操作、每步之间存在必须人工确认的质量节点,那还是要保留一定的流程控制。
第三,任务失败后的代价有多大?涉及支付、合规、健康等高风险场景,强制节点、审批流、可追溯审计是必要的,这些不能因为追求简洁而删掉。
5.2 这四类场景仍然需要结构
根据我的经验,下面四类场景不要轻易把结构全删:
- 长周期任务:比如一个需要跨越多个时段、每完成一步都要存档的调研任务,必须把进度持久化,否则模型一旦超时重启,前面的工作就全丢了。
- 多步安全审批:比如生成对外发布的文案,要求“先写草稿、再走审核、审核通过才允许发送”,这类强制的状态流转不是流程噪音,是合规底线。
- 严格结构化输出:如果模型结果要直接喂给下游业务系统,且字段有强约束,那就需要一个独立的校验层,而不是让模型自由发挥。
- 大规模并行子任务:比如一次要分析一百份文档,单循环逐个跑太慢,需要拆分成并行任务并对结果做汇总。
5.3 保留结构的正确姿势:把流程写进数据和提示词,而不是写进框架代码
如果确实需要结构,我现在的做法是把流程描述成数据。比如一个三步调研工作流,我会定义一份 JSON 格式的工作流配置,包含每步的任务描述、输入输出字段、允许调用的工具范围。模型不直接面对整个流程,它只看当前这一步的指令,执行完把结果按约定格式交回,由外层一个非常薄的调度器把结果填入下一步的输入。
这样做的区别在于:流程仍然存在,但它不是散落在代码里的逻辑,而是可以在评估集上观察、可以随时修改的一份数据。模型永远是“被数据驱动”的,而不是“被一堆类和方法驱动”的。我见过很多团队的 Agent 项目死在反向:把简单任务塞进重型框架,最后连维护框架本身都成了全职工作。
6. 实操中容易踩的坑和排查技巧实录
6.1 常见问题速查表
| 现象 | 大概率原因 | 处理办法 |
|---|---|---|
| 删掉架构后模型频繁漏调用工具 | 工具描述写得太抽象,模型不知道何时该用 | 重写工具描述,增加“适合使用的场景示例”和“不适合使用的场景示例” |
| 多轮对话越聊越偏 | 历史没有裁剪,旧信息干扰新决策 | 设置上下文规模阈值,触发后做滚动摘要 |
| 模型在同一个工具上陷入死循环 | 没有最大步数限制,或工具返回内容一直没变化 | 加最大步数上限;对重复调用去重,把“该工具刚用过且结果未变”提示回传 |
| 简单任务快,复杂任务烂 | 前置的“任务复杂度判断”缺失 | 在循环前加一次轻量分类,复杂任务走保留的轻量工作流 |
| 删得太猛,完全不可观测 | 日志没有留全 | 删除架构前先加结构化日志,至少保留输入、输出、每次工具调用的参数和结果 |
| 模型自己“脑补”了工具结果 | 工具异常被吞掉,没把错误文本回传 | 工具错误统一归一化成文本并回传,让模型看到真实错误再决定下一步 |
6.2 我实践下来的删除顺序
删架构这事,不建议一步到位。我实际操作时按这个顺序走:
- 先冻结工具清单。所有模型可能用到的工具,先统一成同一套函数接口,保证删除过程中模型需要的能力不丢。
- 全量留日志。每一步模型输出、每次工具调用参数、工具返回结果,全部落盘。删完之后出现问题,可以回放定位。
- 新旧并行跑一周。新方案和旧方案同时接一份影子流量,只观察不切换,用评估集对比指标。
- 一次只删一层。先删多智能体协同,观察三天;再删规划层,再观察。不要一次性把五层全部拆掉,否则出了问题根本不知道是哪一层引起的。
- 留好回滚开关。把新方案做成一个可配置开关,出现严重问题时,一键切回旧方案。
- 删除过程中产生的“新需求”先记进 backlog。很多时候,删了一层之后会觉得“这里是不是还缺个模块”,别急着加,先记下来,等评估数据说话。
6.3 我现在的迭代检查清单
现在每逢我自己或者团队成员想往一个 Agent 项目里加新模块,我都会先过一遍这份清单:
- 这个新模块,能让模型直接看到更多真实数据吗?如果只是一层新的流程封装,大概率不必要。
- 它能用评估集证明收益吗?不能证明的抽象,都是潜在的复杂度负债。
- 如果删掉它,最坏情况是什么?写下来,判断能不能接受。
- 它增加了可观测性,还是降低了可观测性?一个让调试变困难的东西,再漂亮也先不碰。
我把这套清单用在自己所有 Agent 项目上之后,最大的感受是:现在改一个 Agent,百分之八十的时间花在调数据、调工具描述、看评估结果上,而不是花在理解“系统为什么这样跑”上。我个人这一年的体会比较朴素——大模型的底层能力已经很能打了,真正拖后腿的往往不是单步能力,而是我们给模型套上的那层壳。删架构不是偷懒,也不是否定工程化,而是把复杂度放回它该在的地方:数据和评估里。如果你手上正有一套跑不动的重型 Agent,我建议你先别急着加更复杂的模块,试试把架构删掉一层,然后让评估集来告诉你答案。