做 Agent 越久,我越发现一个反直觉的事实:效果提升最大的改动,往往不是把系统做得更复杂,而是把它删得更薄。最近一年我手上有几个不同类型的 Agent 项目,有做文档问答的,有做材料预审的,还有一个做代码库辅助分析的。集中复盘之后,所有效果明显变好的迭代都有一个共同点——把 Agent 的整体“架构”给删了。
我先解释一下这个“架构”指什么。它不是我早期那种只有一个 Prompt 的裸奔脚本,而是一套标准的多层调度系统:意图识别模块、路由判断、多轮状态机、记忆模块、工具调用编排层、异常恢复模块,甚至还有一条事件总线。听起来五脏俱全,跑起来却经常出问题。真正让我下定决心删掉它的,是一次线上事故:某高并发问答 Agent 在高峰期出现大面积超时,排查下来发现大部分 token 都消耗在无意义的架构环节上,真正用来读取有效资料、组织答案的 token 少得可怜。
后来我用一个非常朴素的方案重写了一版:去掉状态机、去掉事件总线、去掉多级路由,只保留“一个明确的 Prompt + 几个可执行函数 + 一条硬性回退规则”。跑了一周之后,任务成功率不降反升,线上稳定性也明显改善。这篇文章就把我这次“删架构”的完整思考、实操过程、数据对比和踩坑记录写下来,希望能给正在做 Agent 方向的朋友一个参考。
1. Agent 架构为什么会成为“效果拖累”
1.1 三个隐性成本:上下文稀释、决策超载、维护爆炸
复杂架构带来的第一个问题是上下文稀释。
任何架构组件一旦进入 Agent 的上下文,就会占用窗口。比如你用一个状态机来管理流程,状态机的当前状态、已经走过的分支、未来可能走的分支,这些信息没办法完全从上下文里剥离,总有一部分会被模型看到。模型本来应该在“理解用户需求、组织回答内容”上集中注意力,结果它还要分心去理解“当前处于哪个状态”“上一步是否执行成功”。这就像你请了一个人来帮你写方案,但开会时有三十个人轮流找他签字确认需求,真正静下来写方案的时间少得可怜。
第二个问题是决策链路过长。
多层架构意味着用户每一次操作背后,都可能经历完整链路:入口权限校验、意图识别、路由分流、状态读取、工具调用、结果解析、生成回复、状态更新。每一步都是决策点,模型每多加一层判断,就多一次推理损耗。这些中间判断的错误率会以乘法方式累积。做一个粗略的估算:假设每一步单独正确率都是 95%,经过五层之后,整体正确率就只剩 77% 左右。如果中间某些判断本身模糊,比如“用户这句话到底是想查库存还是想下订单”,准确率还会更低。这个问题在模型能力越弱的时候越明显。
第三个问题是维护爆炸。
复杂架构的维护点真的非常多。改某个工具的输出格式,上游路由规则要改,下游状态更新也要改,中间可能还夹着一层缓存和消息。有一阵子我为了给一个 Agent 加一个新意图,需要同时改意图列表、路由表、Prompt 模板和事件定义,前前后后花了将近两天。删掉架构之后再遇到同样需求,基本就是改一段文本描述的事。
1.2 一次线上事故,让我看清架构在“空转”
触发我动手删架构的是一次比较严重的线上故障。
当时某个文档问答 Agent 做了一次功能升级,加了多层路由和状态机,上线之后咨询量稍微上来一点,端到端时延就明显增加,异常率也从原来的 1% 飙到了 12%。查了半天,发现大量超时都集中在“意图路由”这个环节。模型经常在几个意图之间来回摇摆:用户说一句“我想看下之前提交的报表”,它既觉得是查询,又觉得是下载,还觉得是数据分析,结果在路由层反复计算,最终触发了超时。
监控面板上一张图让我印象非常深刻:一条完整请求链路里,超过一半的时间都花在调度和路由上,真正调用知识库检索和回答生成的占比只有四成不到。那一刻我很确定:这个 Agent 不是能力不够,而是被自己的“架构”拖死了。一个用来解决用户问题的系统,结果自己先把一半的算力消耗在了“内部怎么走流程”上,这完全本末倒置。
2. 删掉架构后,我用什么方案替代
2.1 用自然语言流程替代状态机
状态机的本质是把流程显式地固定下来:“先做 A,再做 B,如果 C 则跳到 D”。但模型真正的强项是理解任务目标,而不是精确定位自己在状态迁移表中的坐标。你把状态机描述得再清楚,它也容易在执行和描述之间产生偏差。
我后来的做法很简单:把流程直接写进 Prompt,用自然语言说明步骤、顺序、边界条件,而不是定义一堆状态和迁移。模型拿到这段描述之后,相当于拥有一份“操作说明书”,它会自己判断当前该做什么。这里有一个关键心得:不要试图把每一个分支都写全。你只需要写清楚主线、异常分支和终止条件就够了。
比如之前那个材料预审 Agent,我原来会画出“待初审—待补件—待终审”的状态流转图。现在我的 Prompt 里只写一句话:先判断材料是否齐全,不齐就说明缺什么、怎么补,齐了就给出通过意见。就这么简单,效果比之前的状态机还好。
2.2 函数只做最小原子操作
复杂架构里最容易被过度设计的就是工具层。以前我习惯给每个 Agent 配一层完整的工具调度中间件:工具注册、参数校验、结果缓存、调用限流全部堆在一起。删掉之后,我彻底改变了对工具函数的理解:每个函数只做一件事,且不做任何流程编排。
举个例子,代码库辅助分析 Agent 里,我暴露给模型的函数只有几个:读取指定文件、搜索代码符号、获取文件变更记录、生成测试用例。模型负责决定“现在应该调用哪个”“调用结果要如何使用”,函数本身只保证两件事:输入合法、输出可靠。
这样做带来的直接好处是出错边界变得非常清晰。如果函数输出不对,一定是函数本身的问题;如果步骤不对,基本可以判断是 Prompt 的表达问题。排查问题时不再需要在几十个模块之间来回猜。
2.3 用一条硬性回退规则替代穷举错误处理
以前做异常处理,我会精心设计错误状态图:什么情况重试一次、什么情况降级返回、什么情况通知人工介入。后来发现这些逻辑模型根本记不住,也经常判断错。你在 Prompt 里写一百条“遇到某某错误就执行某某操作”,模型遇到真实场景时大概率只记得住最表面的那几条。
简化之后,我在 Prompt 里只留了一条硬性回退规则:任何一步操作连续两次都执行失败,直接停止尝试,输出“暂时无法完成,请稍后重试或联系人工”。
这条规则看着简单,但你相信我,它能拦下很多失控场景。大多数 Agent 的失败不是“完全不知道怎么做”,而是“在一个错误的分支上反复打转”。给一条强硬的终止指令,反而能把那些原本会无限循环或者空转的情况全部刹住。后期统计时,我发现相当一部分被“救回来”的会话,靠的就是这条规则。
2.4 确定性能力放到系统侧,不塞进上下文
删掉记忆模块之后,我用了一个更原始的方案来处理上下文管理:把所有确定性内容放在系统代码里,例如登录态、数据权限、用户身份、数据库查询结果。模型每次需要时,通过函数调用去实时获取,而不是把所有历史记录、用户都塞进上下文让它自己筛选。
这个调整带来的 token 收益非常明显。那时我测的单会话平均 token,从 8000 多降到了 3000 出头。而且模型不再被无关的历史日志干扰,回答稳定了很多。
很多人把“上下文管理”理解成“把更多东西塞进上下文”,其实是反的。上下文管理的目标是让模型只看它当前这一步该看的东西,而不是把整个项目的历史都摆在它面前。
3. 简化前后实测对比:效果提升到底在哪
3.1 我跟踪的三个指标
这次重构前后,我专门拉了两周数据做对比。主要看三个指标:任务成功率、平均交互轮数、单会话 token 消耗。另外还附带统计了一个人工介入率,用来衡量“需要人工兜底”的比例。
某个材料预审 Agent 的抽样数据如下:
| 指标 | 简化前 | 简化后 | 变化 |
|---|---|---|---|
| 任务成功率 | 63.5% | 81.2% | +17.7% |
| 平均交互轮数 | 5.4 | 3.1 | -42.6% |
| 单会话平均 token | 约 8200 | 约 3400 | -58.5% |
| 人工介入率 | 19% | 8.5% | -10.5% |
不同项目数据会有差异,但趋势是一致的。简单架构下,任务成功率提升、交互轮数下降、token 消耗降低,几乎同时发生。
3.2 为什么“多决策点”会拖垮任务成功率
这里需要说清楚一个概念:Agent 的每一步推理都会引入不确定性,而不确定性会累积。
用前面算过的概率来说:假设模型单步正确率是 90%,两步之后整体成功率大约降到 81%,五步之后就只剩 59%。架构每多加一层判断,实际完成任务的路径就多出几个决策点,每个决策点的错误都会影响最终输出。这不是“可能有点影响”,而是必然影响。
删掉低价值决策点之后,模型的“注意力预算”会全部集中在真正有用的事情上:理解用户意图、搜索相关信息、组织语言输出。这就像一条高速上没有那么多匝道和红绿灯,再慢的车也能稳定跑出速度。
3.3 简化后哪些场景反而需要重新补细节
删除架构不代表所有场景都能直接变好。我在简化过程中发现,有三类细节反而需要额外补上:
第一是安全边界。不要因为简化,就把权限校验和数据隔离也一并删了。Agent 直接访问数据时,必须在函数层或调用层做严格校验。比如用户只能查询自己有权限访问的文档,这个校验不能省。
第二是透明度。简单架构的运行过程是一个黑盒,出了问题很难从头梳理。我会在关键步骤记录日志,比如“调用了哪个函数、返回了什么结果、模型最终生成了什么回复”,保证事后可以还原。
第三是防跑飞机制。简单架构没有状态机约束,模型有可能在某一次输出里“跑偏”。我在 Prompt 里就留了明确规则:如果用户请求超出范围,直接拒绝并说明原因,不要尝试猜测。
4. 实操复盘:我是怎么把 Agent 架构“删干净”的
4.1 先分清“必备件”和“花架子”
不要一上来就删代码,你先盘一遍现有系统里有哪些组件,然后把它们分为两类。
必须保留的,通常是这几类:
- 身份与权限校验:确保用户只能访问自己该访问的数据
- 最小原子函数层:真正会被模型调用的工具
- 日志与追踪:至少能看到每次请求的链路和关键参数
- 限流与配额:防止 Agent 在异常情况下无限消耗 token 或外部接口资源
可以考虑删除的,通常是这些:
- 多级意图路由
- 状态机驱动的流程管理
- 事件总线或消息队列
- 记忆嵌入模块
- 复杂的 Prompt 模板引擎
- 多 Agent 编排层(大多数项目其实用不到)
我的经验是:如果一个组件只是为了让另一层代码“看起来更统一”而存在,那它大概率就是花架子。
4.2 按“删—抽—合”三步改
第一步:删。
把暂时认为不必要的调度代码先注释掉,不是直接删除。注释保留一段时间,方便你在观察期里回滚对比。我当时是把路由判断、状态机、事件总线整体注释掉,然后加了一个开关:按流量比例把部分请求切到新方案上,跑了一个星期才完全切换。
第二步:抽。
把那些真正需要的函数抽成最小单元。比如“获取用户身份”“查询指定数据库”“发送结果给前端”。每个函数保持单一职责,函数内部不要做流程编排。
第三步:合。
把流程描述合并成一段清晰的 Prompt 文案。这是我当时用的一个示例模板,你可以直接改着用:
你是一个材料预审助手,负责帮助用户完成资质申请材料预审。
工作流程:
1. 先接收用户提供的材料清单
2. 核对必填材料是否齐全
3. 如果有缺失,明确告知缺什么、如何补交
4. 如果齐全,输出“材料齐全,可以提交”的结论
硬性规则:
- 每次只指出一个缺失项,不要一次性罗列多个问题
- 如果没有把握判断,明确说“需要人工复核”
- 任何操作连续两次失败,直接提示“暂时无法完成,请稍后重试”
这份 Prompt 不复杂,但已经包含了主线流程、异常分支、终止条件三个关键信息。
4.3 用回归测试验证没有坏副作用
删完架构之后,最担心的是某些边角场景悄悄变差。我建议建立一套回归用例集:至少整理 30—50 条典型输入,覆盖正常需求、边缘情况、故意刁难的输入。
新旧架构分别跑一遍,把输出质量记录下来。如果发现某个场景明显变差,先思考能不能通过改 Prompt 来改善,而不是急着把模块加回来。绝大多数场景都能用一两句 Prompt 约束解决。只有那些需要严格确定性分支的场景,才值得重新考虑引入硬编码逻辑。
我在回归测试里发现过一个问题:原来状态机里有一个“超时自动转人工”的硬逻辑,简化后 Prompt 只写了“连续失败就提示重试”,导致一些超时场景直接被引导到“重试”,而不是“人工介入”。后来我在 Prompt 里补了一句:“如果用户反馈紧急或重复失败超过两次,建议直接联系人工处理”,问题就解决了。
5. 常见问题与排查技巧:简化后容易踩的坑
5.1 效果不升反降?先看这三个原因
有些朋友照着我这种方式改了之后,反馈说效果反而变差了。我总结下来,原因集中在三个地方。
第一,模型本身能力不够。自然语言流程描述看起来简单,但对模型的理解能力要求并不低。如果用的基础模型在长指令理解、任务拆解上本来就吃力,简化后反而会不知道怎么走流程。这种情况建议先换一个更强的模型,再回来看简化效果。
第二,删过头了。有些人一键删除了所有模块,连基本的权限校验、数据隔离、超时限制都没有了。Agent 一旦进入异常状态就可能访问到不该访问的数据,或者反复调用外部接口造成消耗失控。安全边界在任何架构下都不能省。
第三,Prompt 写得不够清楚。自然语言同样有歧义。比如“如果齐全,输出结论”这句话其实不够严谨,正确的是“如果材料清单中的所有必填项都已提供,输出结论”。措辞含糊会在复杂场景中被模型放大。排查时把 Prompt 给另一个人看,如果对方能准确说出接下来每一步该做什么,基本就没问题了。
5.2 多智能体协作场景还能简化吗
很多人一听到“删架构”,第一反应是“那是你的单 Agent 场景才能这样做,多智能体怎么办”。根据我自己的项目经验,多智能体场景反而更能从简化中受益。
大量所谓多智能体设计,其实是“伪多智能体”。你只是把一个大任务拆成几个子任务,然后让不同角色分别处理。这些子任务之间没有真正的竞争或协作关系,只是依赖一个共享结果。这种情况下,复杂的通信协议完全没必要。
我现在的做法是:如果确实需要多个角色协作,就让他们共享一份“任务清单”文件,每个角色只负责更新自己负责的那部分,其他角色读取最新状态即可。这比让他们通过事件总线互相发消息可靠得多。
真正需要多智能体的场景,是两个或者多个角色各自拥有独立的上下文、独立的工具集,并且结果需要汇合。即使这样,我也建议先判断能不能用“串行调用多个单 Agent”的方式解决,而不是同时拉起一堆 Agent 并行跑。
5.3 Prompt 会越来越难维护吗
简化之后,不少人担心业务逻辑全部堆在 Prompt 里,后面会难以维护。
我的经验是:把 Prompt 当代码管理,而不是当聊天内容管理。我会用一个专门目录存放不同版本的 Prompt,每次修改都记录变更原因,和代码一样合入版本控制。真正出现问题时,改动一个 Prompt 字段的影响面是单点的,比改一堆状态机代码要安全很多。
另外,Prompt 里不要写那些“听着很专业”但实际没有信息量的话。比如“请扮演资深专家”这类废话,对任务成功率没有任何帮助。每一句话都应该对应一个具体的业务边界或行为约束。
6. 删架构的适用边界:什么项目适合这样改
6.1 适合删的三种情况
归纳一下我自己的经验,下面三类项目非常适合往简化方向走。
第一类是任务边界明确的场景。比如材料预审、知识库问答、客服信息查询,用户的需求很清晰,流程并不复杂。这种项目用复杂架构纯属自缚手脚。
第二类是模型能力较强的场景。你用的模型越强,就越能直接理解自然语言描述的任务流程,也就越不需要外部架构去强行规划路径。反过来,模型能力弱时,架构反而能起到兜底作用。
第三类是快速迭代的探索型项目。需求变化快,今天加一个意图,明天改一个流程,代码重构频繁。这种场景下,架构层很容易成为“改一次需求要动十处代码”的负担。用简单架构可以让每次迭代成本降到最低。
6.2 不适合删的三种情况
简化不是银弹,有些场景硬要删架构,会带来很大麻烦。
第一类是强合规、强审计场景。比如金融风控、医疗决策、政务审批,系统每一步做过的判断都需要可追溯、可回放。这时候你必须有完整的状态记录和决策链路,不能依赖模型自由发挥。架构在这里不是负担,而是合规要求。
第二类是需要严格分支控制的场景。比如某些流程里,结果必须严格按照规则走:某个条件满足就必须走 A 分支,不满足就走 B 分支,不允许有第三种解释。自然语言描述很难保证 100% 一致,这种场景建议把分支逻辑写在代码里,而不是让模型自己理解。
第三类是团队经验偏传统开发的情况。如果你的团队对模型提示工程不熟,对“用自然语言管理流程”这件事也不太适应,强行简化可能会导致整个迭代过程变得不可控。这时候保留传统架构,至少能让所有人通过代码读懂系统的行为。
6.3 删架构的本质:把设计从代码转移到语言
删架构不等于不做设计。我越来越觉得,这件事情的本质是设计重心的转移:以前你把设计显式地写在代码里,现在你把设计隐式地压在语言里。
模型是执行器,真正要做的,是把业务逻辑压缩成一句句清晰、无歧义的指令。这需要比设计状态机更高的抽象能力。你对自己业务的理解,决定了 Prompt 的质量。所以你删掉的不是一个系统,而是给系统“减机体、增灵魂”。
最近一年,我至少删掉了三个“看起来很专业”的架构层,换来的是更快的迭代速度和更稳定的效果。每次处理新需求,我都会问自己:这里是真的需要一套机制,还是只需要一句话?大部分情况下,答案都是后者。时不时回头看看自己写的 Agent 系统里有哪些组件是“为了存在而存在”,删掉它们,效果大概率会给你惊喜。
568




被折叠的 条评论
为什么被折叠?



