开头先泼盆冷水。
我见过太多这样的项目:Demo 演示的时候,Agent 在台上侃侃而谈、把工具调用得行云流水,客户当场拍板。结果一上线,不是答非所问,就是卡在某个工具调用里出不来,要不就是并发一上来直接超时,最后业务方留下一句“这玩意还不如人工”就撤了。我自己的团队也踩过同样的坑。今天这篇东西不聊花哨的 Agent 框架,只聊一个事:为什么企业级 Agent 从 Demo 到生产落地会拉胯,以及我们把“四道坎”一一填平的全过程复盘。如果你正要评估 Agent 项目,或者已经在生产环境里被问题追着跑,这篇内容大概能帮你省下一两个月的试错时间。
1. Demo 惊艳、上线拉胯,到底差在哪
1.1 复盘一个典型的“上线事故”
先还原一个真实场景。三年前我参与一个智能客服改造项目,需求很简单:客户打电话进来,Agent 根据知识库回答售后问题,复杂问题转人工。Demo 阶段我们用的是精心挑选的样例问题,每个答案都逻辑清晰,工具调用准确率看着接近百分百,客户满意度直接拉满。
上线之后第一周问题就爆了。真实用户的问法千奇百怪,一句话里能带三个错别字加两个语气词;知识库里的文档有 PDF、Excel、网页截图,格式不统一;高峰期并发一上来,大模型的响应时间从 Demo 时的 2 秒飙到 15 秒,用户等不及直接挂断。
最离谱的是有一次,用户问“我的订单为什么还没到”,Agent 检索到了运单信息,但把“运输途中”解读成了“已签收”,然后告诉用户“你的快递已经签收了,请查收”。这类问题在 Demo 里永远不会出现,因为演示样例都是标准化的。这里面的核心差异一句话就能概括:Demo 验证的是模型的能力上限,生产考验的是系统的能力下限。
1.2 Demo 与生产的本质差异:三张“伪装”的面孔
我把 Demo 和生产之间的鸿沟归纳成三个层面,每一层都会制造“上线拉胯”的假象。
第一层是数据伪装。Demo 阶段用的知识库和真实生产知识库并不是一回事。演示数据通常经过清洗、去重、格式统一,而生产数据往往充满噪音:过期文档、重复条目、互相矛盾的说法。Agent 的检索环节一旦召回质量不高,后面的推理和生成环节再怎么调都白搭。
第二层是交互伪装。Demo 通常是单轮问答,用户给一个问题,Agent 给一个答案。真实场景是连续对话,用户会打断、会补充条件、会否认之前说过的内容。Agent 需要有状态管理能力,要记得住上下文,还要在用户改变主意时及时更新状态。这一层缺失,上线后就会出现“失忆”表现。
第三层是评估伪装。Demo 靠人工观察和几个样板题验收,而生产需要一套可量化的评估体系。我们用“准确率”看回答,但真实业务更关心“任务完成率”——用户的问题有没有被真正解决,而不只是话术正确。
所以根因其实不在于模型能力,而在于工程化程度。下面四道坎,就是围绕这三层伪装逐一拆解出来的工程解法。
2. 四道坎的第一道:稳定性与可观测性
2.1 根因:概率模型的“灵光一现”与“阴暗面”
大模型本身是概率系统,同一个 prompt 给两次可能得到截然不同的答案。这放在聊天产品里还能接受,放在生产业务里就是灾难。比如 Agent 调用一个接口下单,第一次给参数 A,第二次给参数 B,第三次干脆说“我没听懂你的意思”。这是概率模型的属性,不是 bug,但工程上必须当作 bug 来处理。
我们团队最早的处理方式是“加强 prompt”,反复强调“你必须严格按照流程做”。结果效果有限,模型有时候听话,有时候依然我行我素。后来我们想明白一件事:prompt 能约束行为的“边界”,但约束不了行为的“必然性”。真正要解决的是在架构层面建立确定性。
怎么建立确定性?我们采取了三层策略:流程显式化、输出结构化、状态可恢复。流程显式化是把 Agent 的决策路径从隐式的模型自由发挥变成显式的步骤拆分,比如先“理解意图”再“检索知识”再“生成回复”。输出结构化是强制模型输出 JSON 格式,并对关键字段做运行时校验,不合法就直接让模型重新生成。状态可恢复则是把每一步中间状态都落盘,一旦出错可以从最近的检查点重新执行,而不是从头再来。
2.2 可观测性:Trace、Token、Tool 调用一个都不能少
排查生产问题最大的障碍是 Agent 像一个黑盒,你不知道它内部经历了什么。用户问了一句“我的订单呢”,Agent 内部可能经历了理解意图、判断调用哪个工具、决定参数、生成回答四个步骤,任何一步出错都会影响最终输出,但日志里往往只记录了一个最终的文本回复。
我们花了差不多两周时间建设可观测性体系,核心是三张表:调用链 Trace、Token 消耗、工具调用记录。
Trace 记录一次完整请求的链路,包括模型输入输出、工具调用请求与响应、检索结果、中间状态变化。排查问题的时候,能按 request_id 把整条链回放,这一步是救命级的。Token 消耗记录每个环节花了多少 token,能定位到哪一步在浪费成本。工具调用记录则要关注调用的入参和出参,尤其是出参,很多时候模型给的结论是对的,但工具返回的数据被它解读错了。
选型上,我们初期用过 Langfuse,后面迁移到了自建的监控体系,配合 OpenTelemetry 生态。如果你项目规模不大,直接用 Langfuse 或 Phoenix 这类开源工具也能满足要求,关键是先跑起来,不要在第一天就追求完美。
注意:可观测性不是上线以后才补的。Demo 阶段就埋好 Trace 埋点,能让你在演示环境就发现“这个回答其实是检索错了,不是生成错了”这类问题。
2.3 兜底策略:重试、降级、熔断怎么设计才不闯祸
可观测性负责发现问题,兜底策略负责在问题出现时不影响用户体验。这个领域最容易踩的坑是“乱重试”。
重试要分场景。纯查询类的工具调用,比如查天气、查订单状态,重试是安全的。但有副作用的操作,比如下单、退款、发送通知,重试之前必须想清楚幂等性。你的接口支持幂等吗?不支持的话,Agent 第一次调用超时,你盲目重试了一遍,结果用户被下了两单,这锅算谁的。
我们的做法是给工具调用统一加一层网关层,定义三类语义:
| 操作类型 | 示例 | 重试策略 |
|---|---|---|
| 只读查询 | 查库存、查订单状态 | 超时可重试 1-2 次,间隔递增 |
| 写入操作 | 创建订单、修改资料 | 使用幂等令牌,重试时带上同一令牌 |
| 外部依赖 | 调用第三方 API | 熔断 + 降级,失败后走预设的替代方案 |
降级策略也要提前想好。模型供应商不稳定的情况时有发生,我们的方案是同时接入两家大模型服务商,以一家为主、一家备份。主供应商连续返回异常时,网关自动把流量切换到备份。用户侧无感知,但后台已经完成了故障转移。
另一个容易忽略的点是“模型降级”,即复杂任务用大模型、简单任务用小模型。生产环境里很多请求其实是简单意图,直接用小模型处理能省太多延迟和成本。这也是一个实用技巧,后面讲并发的时候会再展开。
3. 四道坎的第二道:并发与性能
3.1 先算账:Agent 的延迟和 Token 成本怎么估算
“AI Agent 怎么扛并发”是后台问得最多的问题。很多团队一上来就讨论架构选型,我习惯先让大家算一笔账。
先算延迟账。一个 Agent 请求涉及至少两轮模型调用:第一轮理解用户意图和规划步骤,第二轮生成最终回答。中间可能穿插检索和工具调用。假设单轮模型调用耗时 3 秒,两轮就是 6 秒,这还不算网络传输和工具调用时间。每个请求端到端 8 秒是保守估计。
再算成本账。一次简单的客服问答,如果上下文塞得比较大(比如基础 prompt 加历史对话加检索结果),单次消耗 2000 token 很常见。假设供应商价格是输入 0.1 元 / 千 token,输出 0.3 元 / 千 token,一次请求的成本大概 0.3 元左右。一天一万次请求就是 3000 元成本。Demo 阶段你不会注意这个数字,但生产环境这就是硬成本。这个账算完,大家基本就理解为什么“并发扛不住”本质上是个延迟和成本的综合问题了。
优化空间主要在三块:减少无效调用、压缩上下文、并发复用。只要能把这三点做好,并发能力通常能提升一倍以上。
3.2 架构改造:把“笨重”的 Agent 变“轻”
感知型 Agent 结构复杂、上下文重、调用链长,这是并发上不去的直接原因。我们的思路是分而治之,把一个大而全的 Agent 拆成多个轻量级 Agent。
具体做法是引入“意图路由 + 子 Agent”的架构。上层是一个轻量级路由器,负责把用户请求分类,分发给不同的子 Agent 处理。子 Agent 各自只负责一个领域,比如订单查询 Agent、售后政策 Agent、人工坐席接入 Agent。这样每个子 Agent 的系统 prompt 短、工具数量少、上下文轻,单次调用耗时直接减半。
路由层本身也是一个小模型就能解决的,不需要很强的推理能力,一个几百 token 的分发任务,用快模型处理非常便宜。这个时候“模型降级”就发挥作用了。此外,简单问题直接由路由层应答,不进入子 Agent,这又减少了一部分调用。
另一个关键改造是“工具服务化”。不要把工具逻辑塞在 Agent 代码里,而是把工具调用统一封装成独立的微服务,Agent 只负责发指令,微服务负责执行。这样有一个附带收益:工具服务的吞吐能力可以独立扩展,不会被 Agent 的调用频率卡住脖子。
3.3 限流、队列与缓存:扛住高峰的三个抓手
架构调优之外,真正决定系统稳不稳的是流量治理三件套:限流、队列、缓存。
限流参数怎么定?我们按峰值预估的 80% 来限流。比如预估高峰期每秒 20 个请求,那 Agent 入口限流设置为 16 TPS。超出的请求不是直接丢弃,而是进入一个内存队列,按先入先出顺序平滑处理。队列长度要有限制,我们一般设置为 100,超过就直接返回“系统繁忙,请稍后再试”,避免队尾请求等待时间过长。配合上熔断机制,当请求失败率达到 10% 时,网关主动拒绝新请求 30 秒,防止雪崩。
缓存是我们踩过最深的一个坑。第一版我们做过“结果缓存”,把用户的完整问答对缓存下来,命中了直接返回历史回答。后来发现的问题是业务数据一直在变,缓存结果过时,用户查订单状态永远拿到的是旧数据。
第二版改成了“知识点缓存”:大模型生成的答案不做缓存,但工具调用的结果可以按业务纬度缓存一段时间。比如“当前库存量”“物流轨迹”这类高频查询,TTL 设 30 秒,重复问题直接复用工具结果,省掉一次真实调用。语义缓存也值得一提,但对相似问题做归一化处理比较难,我们目前只在低风险场景里用,优先保证准确性。
4. 四道坎的第三道:记忆与状态管理
4.1 记忆的三大坑:爆窗、串线、召回失效
记忆问题在 Demo 里几乎不会暴露,因为演示时对话轮次很少。生产环境用户会连续追问、反复修改需求,这时记忆的坑就全出来了。
第一个坑是上下文爆窗。对话轮次一多,历史记录加检索结果会把模型上下文窗口塞满。第一版方案我们做了“滑动窗口截断”,只保留最近 5 轮对话。效果是上下文不会爆了,但用户在第 3 轮提到的关键业务信息,第 8 轮就用不上了,Agent 开始“失忆”。
第二个坑是会话串线。多轮对话的 session 管理没做好,用户 A 的信息被带进了用户 B 的上下文。这在 Agent 场景不是小事故,尤其是涉及个人信息的时候,属于安全事故级别。
第三个坑是召回失效。我们把历史对话写入向量库做长期记忆,但向量相似度检索并不总是返回你想要的那段历史。用户问“我之前说的那个事怎么样了”,“那个事”在向量库里很容易捞出一堆无关内容。这三个坑叠在一起,会让 Agent 在真实业务里表现得很“弱智”。
4.2 短期记忆与长期记忆的分工
深挖之后发现,记忆问题不能用一个方案通吃。我们把 Agent 记忆拆成三层。
工作记忆对应单次会话内的上下文,存储的是当前对话轮次的关键信息,比如用户刚说的订单号、地址、时间。这层内容用 session 内变量存储,随请求传递,不做持久化。短期记忆对应会话内跨多轮的摘要信息。当一个会话超过 5 轮,我们会用模型对前面的对话做一个结构化摘要,把关键实体、用户意图、待办事项提取出来,替代原始对话文本。摘要的质量直接影响后续对话表现,所以我们迭代了两次提示词方案才稳定下来。
长期记忆则跨会话保留,存储内容分为两种:事实型记忆和偏好型记忆。事实型记忆如用户的姓名、会员等级、订单历史,这些从业务系统同步,不经由对话抽取;偏好型记忆如用户喜欢工作人员礼貌用语、偏好简洁回答等,通过对话分析获得。长期记忆我们存放在向量库,同时设置了记忆刷新机制,当新信息与旧记忆冲突时,以新信息为准并主动更新。
4.3 我用的记忆设计方案
现在的方案沉淀成了一套比较稳定的架构。会话开始的时候,系统先从长期记忆库召回与用户相关的关键信息,作为种子上下文注入。会话进行中,每一轮对话的产出都会同步更新短期记忆摘要;如果会话超过 6 轮,触发一次摘要重算,丢弃原始文本。会话结束后,异步把有价值的信息写回长期记忆库。
这个方案不是一蹴而就的,中间走了很多弯路。最大的教训是,别在“让 Agent 记住所有对话内容”这件事上努力,而要在“记住有用的、忘掉没用的”上下功夫。信息过滤比信息存储重要得多。
具体落地时还要注意时效性。比如用户昨天投诉过物流慢,今天又问了物流,Agent 要能关联上这个背景。但两个月前用户问过一次商品价格,和今天的购买决策就没有强关联,不该作为主要召回内容。给记忆打上时间戳和“衰减因子”能解决一部分问题,我们后期也加了这个机制。
5. 四道坎的第四道:安全、权限与合规
5.1 Agent 安全的核心矛盾:权限“被放大”
Agent 和普通应用最大的安全差异是:它会按照大模型的“理解”去调用工具,而大模型的判断不总是可靠。相当于你把车钥匙交给了自动驾驶系统,但自动驾驶偶尔会看错路标。
早年我们犯过一个错,给 Agent 配置了过高的权限。它要能查订单状态,我就把订单管理系统只读账号给了它。看起来只是只读,但模型只要理解了字段结构,依然可以批量拉取所有客户的敏感信息。因为模型本身不具备业务边界意识,它只会按用户的意图去检索。权限如果没有钳制在最小范围,Agent 就会变成“持枪的秘书”。
5.2 工具网关与最小权限落地
解决权限放大问题的核心是工具网关。每一个被 Agent 调用的工具,进出都要经过一个网关层,由网关执行权限校验、参数校验、配额管理。
权限校验要做三层:用户级权限、Agent 级权限、数据级权限。用户级权限解决特定用户不能看特定数据的问题;Agent 级权限解决某些高危操作必须走人工审批的问题;数据级权限则控制返回的数据范围,比如用户查订单,只返回他自己的订单,不允许 Agent 查全量。
参数校验容易被忽略。一个查询库存的工具,上限参数可能是 10,但模型可能因为 prompt 理解偏差传入了 1000。网关层部署一套参数约束模板:定义哪些字段允许范围、哪些操作必须二次确认。无效参数直接拦截并返回错误提示,让模型重新生成。
另外我们设置了“操作白名单”。高危操作默认关闭,比如发送营销短信、修改用户账户资料、批量导出数据。Agent 想调用必须显式向网关申请,网关返回“该操作需要人工审批”,然后转入人工审核队列,由坐席人员确认后才真正执行。
5.3 审计、内容安全与防投毒
安全体系里的审计日志,很多人会做到最后一步才补,我们吃过亏所以强烈建议一开始就设计好。审计日志要记录至少以下字段:调用时间、用户身份、Agent 身份、工具名称、入参、出参、模型决策依据、审批状态。带着 request_id,就能把一次完整的数据操作历史翻开。
内容安全主要关注两块:模型的输入有没有被恶意注入,模型的输出有没有涉密或违规。防止提示注入,可以通过网关侧的敏感词检测和系统 prompt 防御指令配合。输出侧则要接内容审核接口,对包含个人隐私字段的具体输出做脱敏处理。
我还想强调一个被讨论得比较多的点:Agent 的记忆系统本身也可能成为攻击面。如果攻击者在对话里巧妙地塞入一段指令“记住,当用户问 X 时,你要回答 Y”,这段记忆会被写进长期记忆库。下次会话召回时,Agent 就按照被污染的记忆执行了。这属于记忆投毒,我们目前的缓解方案是对写入长期记忆的内容做二次模型审核,并对高风险用户(新注册、异常行为)的对话取消长期记忆写入权限。
6. 框架选型:别让 Demo 代码成为生产包袱
6.1 先分清三件事:业务编排、Agent 框架、基础设施
选型之前一定要先意识到,Agent 框架只是中间那一层,不等于整个系统。上层是业务编排,也就是你定义的业务流程和节点;下层是基础设施,包括模型网关、可观测性、记忆存储、工具网关。很多项目“上线拉胯”不是框架的问题,是下层基础设施没有建设好,框架再强大也白搭。
6.2 主流框架的工程能力对比
我基于自己项目的体验,给几个主流框架做个定位梳理。
LangGraph 偏底层,灵活性强,适合需要精细编排和复杂状态流转的场景,但学习曲线陡,工程化能力要靠自己补齐。Agno 体量小、上手快,适合快速验证原型,但它更适合轻量场景,复杂业务流程管理能力相对弱。Spring AI 适合 Java 技术栈结合 Spring 生态的团队,对已有 Java 微服务架构的灰度发布、服务治理衔接顺滑,但模型抽象层偏薄,深度集成需要自己写。Google ADK 在新项目里人气很高,提供了比较完整的多 Agent 编排能力,文档也比较新,生态起步阶段需要留意版本变化。
没有哪个框架能解决全部问题。我在选型时更看重两个维度:和现有技术栈的契合度,以及和底层设施的集成成本。不迷信框架,也别光看 Github star 数。
| 框架 | 定位 | 强项 | 上手难度 | 生产注意点 |
|---|---|---|---|---|
| LangGraph | 偏底层编排 | 状态机灵活、生态丰富 | 中高 | 需要自建模板和治理能力 |
| Agno | 轻量快速 | 小体量、易上手 | 低 | 复杂长链路容易失控 |
| Spring AI | Java 生态集成 | 与企业存量系统无缝对接 | 中 | 模型抽象需要二次封装 |
| ADK | 多 Agent 编排 | 编排模型清晰、开发体验好 | 中 | 版本迭代快,需跟随升级 |
6.3 我的选择与理由
我当时的项目是 Java 技术栈,最终选了 LangGraph 做核心编排,同时用 Spring AI 做了模型网关层。原因是团队 Java 熟练、LangGraph 对复杂状态流支持好,Spring AI 则帮我把多家模型供应商的统一接入和路由切换这一层快速打通了。
选型心得就一句话:框架是兵器,关键还要看使用兵器的人和他的战术体系。先搞清楚自己要解决的四道坎分别落在哪一层,再选框架,钱才花在刀刃上。
7. 上线前清单与灰度策略
7.1 四道坎对表的 Checklist
上面四道坎拆解完,最后需要落到一张可执行的清单上。我把自己项目里用的上线前 Checklist 精简了一下:
| 检查项 | 具体指标 | 状态 |
|---|---|---|
| 可观测性 | Trace 覆盖全部请求,工具调用日志可回放 | 必检 |
| 重试与降级 | 有副作用操作具备幂等令牌,模型供应商有备份 | 必检 |
| 并发治理 | 入口限流 + 队列 + 失败熔断已配置 | 必检 |
| 记忆管理 | 会话摘要策略、长期记忆刷新机制已上线 | 必检 |
| 权限控制 | 工具网关启用最小权限,高危操作白名单生效 | 必检 |
| 内容安全 | 输入防注入、输出脱敏、记忆写入审核 | 必检 |
| 评估体系 | 测试集任务成功率达成 85% 以上 | 必检 |
| 审计能力 | 审计日志含操作前后值记录与审批状态 | 必检 |
这个清单每一条都是拿实际问题换回来的。比如“工具调用日志可回放”这条,我们当时调了三天一个诡异 bug,最后发现是模型在调用查询工具时把参数里的日期格式从 YYYY-MM-DD 改成了 MM-DD-YYYY,没有回放日志根本定位不到这个细节。
7.2 灰度发布的实操节奏
上线之前还要设计灰度方案。灰度不是简单开一个百分比开关,很多时候 Agent 升级会扰动存量业务。比如你更新了系统 prompt,原本 95% 的任务成功率可能直接掉到 60%,但你没有任何感知,因为指标没看。
我们的节奏是四步走。第一步是影子模式:新版本 Agent 与旧版本并行处理线上流量,新版本结果只记录不返回,用来对比两个版本的回答质量。第二步是内测模式:邀请内部员工 20 人使用新版本,收集反馈并观察指标。第三步是白名单灰度:开放给 10% 的真实用户,持续 3 天以上,确认业务核心指标稳定后再扩到 50%。第四步是全量切换:切换前把训练集、测试集全部重跑一遍,确认成功率没有回退。
灰度期间尤其要关注负面体验,不要只看平均指标。用户投诉、用户流失率上浮,往往不体现在平均成功率里。
7.3 迭代节奏与评估指标
上线后的迭代,我个人建议以周为单位循环:周一收集线上 Trace 和失败样本,周二归结问题类型,周三到周四优化 prompt 或链路,周五跑回归测试并决定是否灰度。这个节奏比较稳,也方便和业务方同步进展。
评估指标我只盯着三个。任务成功率看问题有没有被解决,占了最大权重;端到端延迟决定用户体验;单次请求成本决定业务能不能跑得下去。延迟和成本要设硬上限,不达标不允许上线。另外要把“用户二次求助率”纳入观察——用户找过 Agent 之后又去找人工客服的比例,这个指标比平均满意度更能反映真实问题解决情况。
最后分享一点真实体会
如果让我用一个比喻总结这几轮踩坑:做 Agent 生产落地,Demo 就像考驾照时候的场地练习,场地路况简单,你知道每个考点在哪里;生产环境是一场真实的城市道路驾驶,有电动车乱窜、有大雨、有修路绕行,你的驾驶技术要对应真实路况去调整成肌肉记忆。Demo 惊艳是入场券,工程解法才是车技本身。
我当时最大的转变是从“想方设法让模型答得更好”变成“老老实实把系统做硬”。你不需要追求 Agent 在每个问题上的完美表现,只需要保证关键任务可靠、故障可恢复、权限不失控、成本可控制。把上面四道坎一坎一坎过完,Agent 才真正从作品变成产品。最后再啰嗦一句:工具网关一定要最先做,重要的事说三遍——最先做、最先做。别问我是怎么知道的。