☰
Agent上线即翻车?从Demo到生产的工程改造清单
2026/10/11 6:58:42 网站建设 项目流程

上个月我给一个客户演示 Agent 客服系统,现场效果近乎完美:用户问天气、查订单、改地址、申请退款,Agent 一路顺畅,主持人随机刁钻提问都能接住。客户当场拍板推进度。两周后上线灰度,第一天就翻车——Agent 把两笔订单的地址搞混了,还对着一个投诉用户重复道歉了三次。客户没好意思说重话,但那个眼神我读懂了:这玩意怎么一上生产就稀碎?

这个场景我相信很多做 Agent 项目的同行都不陌生。模型还是同一个模型,为什么 Demo 里光芒四射,生产环境里就原形毕露?我的答案很直接:锅不在模型,在工程。LLM 的能力已经足够撑起绝大多数业务场景,真正让 Agent 项目“上线即翻车”的,是我们把演示当成了交付,把单条路径当成了系统,把“能跑通”当成了“能扛住”。

这篇文章我把自己踩过的坑、拆过的问题、最后沉淀下来的工程改造方法完整梳理一遍。核心思路是:Demo 考验的是模型的“上限”,生产考验的是系统的“下限”。你要是不服这个归因,看完下面的分析再来辩。

1. 先把话说清楚:Demo 惊艳到底惊艳在哪

在甩锅给工程之前,我得先承认一个事实:Demo 阶段的 Agent 确实看着很棒,这种“棒”不是错觉,但它的形成条件很特殊。大多数惊艳的演示,本质上是在三个“温室条件”下完成的,而生产环境恰好把这三个条件全部拿掉了。

**第一个温室条件是输入被精选过。**我们演示时用的用户问题,不管显得多随机,其实都是经过筛选的:有明确意图、没有歧义、信息完整。但生产环境的用户输入是长尾分布,一句话可能带着错别字、口语碎片、情绪化表达,甚至是一段粘贴错误的乱码。我在一个项目中统计过,真实用户问题里大约有三成到四成属于“低质量输入”,这类输入在演示时根本不会出现。

**第二个温室条件是执行路径单一。**演示脚本通常是一条主路径走到底:识别意图、调一个工具、拿到结果、回复用户。但实际业务里,一次用户请求往往需要串联多个工具,中间任何一步都可能返回异常。更麻烦的是,多步操作之间存在依赖关系,A 步骤的结果决定了 B 步骤的参数,B 步骤的参数又决定了 C 步骤的走向,只要中间有一个环节理解偏差,后面全跟着错。

**第三个温室条件是现场有人肉兜底。**演示时讲解者始终在场,一旦 Agent 跑偏,人可以用话术圆回来,或者干脆悄悄切到备选方案。但上线之后,系统面对的是真实用户,没有人能实时干预每一步决策。那种“90% 时间表现优秀,10% 时间需要人工介入”的模式,在演示时是成功的表演,在生产环境就是事故率。

我习惯用一个类比来向同事解释这件事:Demo 像概念车——展示的是设计上限,讲究的是惊艳全场;生产像量产车——考验的是可靠下限,讲究的是十万公里不趴窝。概念车永远不会堵车,量产车要面对早晚高峰、暴雨天气和野蛮驾驶。Agent 项目翻车,不是因为引擎不行,而是我们直接拿概念车上了量产线。

2. 断裂点一:上下文与状态管理——Agent“失忆”的根源

我拆过的最典型的线上事故,就是 Agent 在对话中“失忆”。用户先问了订单配送范围,Agent 回答可以送到某个区域;用户紧接着说“那帮我改到这个地址”,Agent 却反问“请问您要改哪个订单的哪个地址”——明明上一轮已经明确过订单号和地址了。这类问题在演示中极少出现,因为演示脚本里的对话通常不超过三轮,上下文在一个 prompt 里塞得下。

但生产环境的真实对话动不动就是十几轮。问题就出在:Agent 的“记忆”本质上是把聊天记录塞进 prompt 里,而 prompt 有长度上限。

拿一个我经手过的客服项目举例:系统用的模型上下文窗口是 8K token,一开始我们把全部聊天记录都塞进去。对话超过五轮后,历史记录就开始截断——最先被挤掉的是系统设定的业务规则和工具说明,因为它们在 token 排列中往往靠前。结果就是:Agent 越往后越“笨”,前期承诺过的事情全忘了,甚至开始用错误的规则作答。

更隐蔽的问题在于状态散落。订单状态、用户地址、退款进度这些信息,散落在对话历史的不同位置。Agent 要推理出“当前用户处于什么阶段”,等于要在长文本里做实体抽取和关系推理,这远超它在单轮短对话中的可靠区间。我见过一个案例:Agent 把 A 订单的收货地址填到了 B 订单上,原因就是它在历史消息里抽取“地址”时定位错了对象。

工程上怎么解?核心思路是“把上下文从 prompt 里搬出去,把状态做显式化”。

我实践下来最有用的做法是引入显式状态管理:会话开始时初始化一个状态对象,里面存好用户 ID、当前步骤、已确认信息、待办动作;每一步 Agent 决策之前,先把状态对象的结构化字段注入 prompt,而不是塞全部历史。例如:

  • 用户输入 → 解析意图 → 更新状态对象 → 生成回复 → 状态对象持久化

这样无论对话多少轮,prompt 里的关键信息永远是完整的:系统规则不会被截断,当前状态清晰可读,历史记录只在必要时才作为参考材料引入。我在项目中把字段设计成类似下面的结构:

{ "session_id": "xxx", "current_step": "collecting_address", "confirmed_info": { "order_id": "A123", "delivery_address": "上海市浦东新区…" }, "pending_action": "update_delivery_address", "history_count": 12 }

对话超过一定轮数后,用阶段性总结替代原始历史:每五轮生成一条结构化摘要,比如“用户已确认订单 A123 的地址变更,等待执行”。这样 token 占用稳定,信息不丢。

这里有个实操细节容易被忽略:状态对象的 schema 设计要和业务方一起定,不要自己拍脑袋写。我在某个项目里把状态字段写成了英文驼峰命名,业务方看不懂,后面联调时来回折腾了好几轮。后来统一改成中文字段名 + 英文标识符双轨,问题才消停。这不算技术难题,但确实是工程协作里常见的内耗点。

3. 断裂点二:可观测性缺失——线上问题根本无从查起

Agent 项目有一个和传统后端完全不同的调试难题:**它是非确定性的。**同样的输入,两次运行可能给出不同结果,因为大模型采样过程本身带随机性。这意味着什么?意味着出问题时你没法靠“复现”来定位,你必须完整记录每一次决策的轨迹。

我第一次负责一个 Agent 项目的线上排查时,承接过一个让人崩溃的工单:用户反馈说 Agent 承诺“24 小时内退款”,但三天过去了退款没到账。我拿到线上日志一看,傻眼了——日志里只有一句“调用了退款接口”,参数是什么、返回什么、Agent 为什么做出这个决策、中间经历了哪些思考环节,通通没有。我们对着代码猜了一天,最后没办法,只能让用户重新走了一遍流程才抓到有效数据。从那以后我立了个规矩:Agent 项目没有高质量 trace,等于没有调试能力。

要建可观测性,我建议至少打五类关键节点的日志:

节点记录内容排查时能回答的问题
输入解析原始用户输入、意图识别结果、抽取出的实体意图是不是识别错了?实体有没有抽漏?
推理决策模型完整输出(含思考过程)、置信度Agent 为什么选择某个工具?理由是否充分?
工具调用工具名、入参(完整 JSON)、出参参数对不对?下游返回了什么?
异常处理重试次数、错误类型、降级策略哪一步挂了?有没有按预期自愈?
最终回复给用户看到的完整文案话术是否安全?有没有幻觉内容?

实现层面,最有效的办法是给整个请求链路贯穿一个 trace_id,从用户发起请求生成,到每次工具调用、每次内部循环都带上。所有日志统一输出到集中式日志平台,支持按 trace_id 一键拉出全链路。这没什么高深的,但就是特别管用。有一次线上用户反馈 Agent “答非所问”,我拉出 trace 一看:意图识别把“退货”识别成了“换货”,后面所有决策全跟着错。一条日志,十分钟定位,换做以前至少折腾半天。

有一个细节值得单独拿出来说:**工具的入参和出参一定要完完整整落日志,不要嫌数据量大。**尤其是大模型的工具调用经常出现参数幻觉——它可能自信地把一个订单号写成另一个格式。没有完整入参,这类问题基本无解。我在项目里放过一次“低成本尝试”,只记录了工具名和状态码,结果参数错误类问题排查起来等于瞎猜,后来乖乖把完整 JSON 都打了。

另外强烈建议在开发阶段就打开一个“决策回放”页面,把 trace 里的关键节点用可视化方式还原成流程图。demo 阶段这样做看似麻烦,但等到上线后你会感谢这个决定——运营同事也能自己看回放定位问题,不用每次都是研发扑上去查。这个投资回报率极高。

4. 断裂点三:错误恢复与边界处理——生产环境最花钱的环节

如果你问做过生产级 Agent 的人,什么最耗时,十有八九回答不是模型调优,而是错误处理和边界条件。模型的推理能力再强,也架不住外部接口不稳定、网络延迟波动、第三方服务限流。这些在 Demo 里可以当作“不考虑”,生产环境里每一个都是事故源。

我处理过一起典型的连环事故,过程很有代表性:Agent 调用外部订单系统的接口,外部服务偶发超时(大约 5% 概率),超时时 Agent 会重试。如果只是单次重试还好,问题是 Agent 的重试逻辑没有限制——它发现超时后会“认为”操作未成功,于是再次调用,外部服务此时刚好恢复,结果导致重复提交。用户被重复扣了钱,追责追到我们头上。

这里面暴露了两个问题:重试策略缺失、幂等性设计缺失。

工程上必须给所有工具调用加上明确的超时和重试规范:

  • 超时设置:外部 API 连接超时 3 秒,读超时 5 秒,超过就判定失败。
  • 重试策略:最多重试 2 次,退避策略用指数退避 + 随机抖动(比如 1s、2s、4s 基础上加随机数,避免同时重试造成流量尖峰)。
  • 幂等机制:所有写操作必须携带业务侧生成的唯一请求 ID,下游根据 ID 去重。这招能直接避免“重复扣款”这类最严重的后果。
  • 兜底降级:重试仍失败后,Agent 必须停止自动操作,转入人工处理流程或明确告知用户稍后重试,绝不“硬编”一个假成功。

还有一个常被忽视的点:**并发控制。**用过 Agent 的人都知道,模型可以同时发起多个工具调用(并行执行)。这看起来效率高,但如果下游接口只支持每秒 5 个请求,Agent 一次并发开了 10 个,直接把对方的接口打爆。工程上的解法是给每个工具定义速率限制,用信号量控制最大并发数,超额请求排队等待。我给出的初始参数是单工具并发上限 3,给模型加一条指令说明“并行调用时不得超过 3 个工具”,实测稳定后视情况调整。

关键操作的人机协同也是生产环境必须做的一步。我的原则是:凡是涉及资金、隐私、对外承诺的操作,必须加人工确认环节。Agent 可以把流程做到“最后一公里”,但按下确认键的是人。这不是能力不够,是风险兜底。我们项目上线初期设定了 25% 的关键操作需要人工审批,跑了一个月稳定后降到 10%,再往后根据数据调。这张“人工兜底网”虽然牺牲了一点效率,但换来了零重大事故的交付记录,值。

5. 从 Demo 到生产的工程改造实操清单

前面讲了原理和断裂点,这章给你一份可以直接照做的改造清单。我每次接手新的 Agent 项目,都会按这条路线推进,顺序很重要,别跳过。

5.1 先把评估集建起来,再谈优化

很多团队评估 Agent 靠“拍脑袋测两个例子”,这是上线翻车的第一大原因。工程改造第一步应该是建立一个可复用的评估集。

我现在建评估集的最低标准是不少于 50 条真实场景问题,覆盖以下类型:

  • 主流程正常提问(15 条左右)
  • 边界条件(信息缺失、地址不详、数量异常)
  • 多轮对话延续(要求 Agent 记住上文信息)
  • 情绪化表达(用户生气、催促、质疑)
  • 工具异常场景(外部接口不可用时 Agent 的应对)

每条用例要有标准答案或关键评判点。比如“用户要求修改地址,但未提供新地址”,预期行为是主动询问而不是乱猜。评估集的用例来源必须是真实用户数据脱敏后的结果,不要自己编——自己编的用例永远是你以为的痛点,不是真实的痛点。

建立评估集之后,每次工程改动都跑一遍回归,对比回答质量、工具调用正确率、回复合规率几个指标。我们项目定了一个量化标准:主流程正确率不低于 90%,边界条件不低于 70%,才允许进灰度。

5.2 把上下文改成显式状态机

这是第二优先级的改造。前期 Demo 版本往往是“把所有历史塞进 prompt”,上线前必须换掉。

具体做法:梳理业务流程的状态流转图,定义每个状态下的可用动作和切换条件。以订单售后场景为例,至少有这些状态:

  • 待确认问题类型
  • 收集订单信息中
  • 确认退款方案中
  • 等待用户确认
  • 退款执行中
  • 完成 / 失败

每轮对话先做状态判定,再生成回复。状态的迁移必须走代码逻辑,不允许模型自己“自由发挥”。我在实践中的体会是:状态机越严格,Agent 越容易被约束在安全范围内,整体可靠性显著提升,代价是灵活性下降,但生产环境里这个代价值得付。

5.3 给工具调用上协议

让大模型调用工具是 Agent 的核心能力,但裸调用等于裸奔。所有工具调用必须有规范:

  • 参数格式用 JSON Schema 校验,模型输出不符合格式时不要直接传给下游,先做格式纠偏。
  • 工具返回要有标准错误码,Agent 能据此区分“参数错误”“服务不可用”“限流中”等不同失败原因。
  • 重试、超时、幂等策略统一封装成调用层,不在 prompt 里用“请你重试一下”这种软性控制。

我见过太多团队把重试逻辑写进 prompt,比如“如果失败请重试”,这完全不可控——模型可能重试三次,也可能重试十次,还可能因为觉得“重试没用”而放弃。把重试逻辑代码化,是生产级 Agent 和玩具级 Agent 的明显分界线。

5.4 把可观测性接到位

第四步是日志与 trace 建设。最低要求是:每次完整的 Agent 执行周期,必须留下包含 trace_id 的结构化日志,至少覆盖本章前面列出的五类节点。

实操顺序:

  1. 先定义一个统一的日志格式规范,字段包括时间戳、trace_id、节点类型、业务字段、耗时。
  2. 在 Agent 框架的钩子函数里埋点(如果有框架的话),没有框架就手动在每个关键调用处打日志。
  3. 接日志采集,支持按 trace_id 检索。
  4. 最好做一个简易的可视化回放页面,这一步能极大提升定位问题的效率。

5.5 上保护与治理

第五步是给系统套“安全网”,包括限流、降级、熔断、人工复核四件事:

  • 限流:token 级限流和接口级限流都要做,防止用户刷爆你的模型预算。
  • 降级:模型服务不可用时自动切换备选模型,或者退化为纯规则回复。
  • 熔断:连续错误率达到阈值(比如 20%)时,自动熔断某个工具调用,避免引爆下游。
  • 人工复核:关键操作人工确认,非关键操作抽样审查。

5.6 灰度发布,别一把梭

最后一步是发布策略。很多人上线 Agent 系统跟上线普通 Web 应用一样直接全量,这是最危险的。我给的建议是:先内部团队试用一周,再开放给 5% 的外部用户跑两周,期间盯紧 trace 日志和用户反馈,稳定后逐步放量 20%、50%、100%。

灰度期间重点关注三件事:一是用户实际输入和评估集的偏差大不大,及时补充评估用例;二是工具调用失败率的基线数据;三是“Agent 给出错误但自信回复”的比例,这类问题在人工复盘时最容易暴露,一旦发现要及时加约束规则。

6. 常见问题排查实录与我的避坑心得

最后分享几个实际排查过的典型案例,附带我的处理思路,希望能帮你少走弯路。

**案例一:Agent 突然开始用“残缺句式”回复用户。**某项目上线第三天,Agent 开始出现半截话回复,例如用户问“我的包裹到哪了”,Agent 回“您的包裹正在”。第一反应是模型抽风,加大 prompt 约束后仍偶发。最终通过 trace 定位到根因:上下文过长导致系统自动截断,模型生成到一半时上下文窗口溢出,输出被强制截断。解法是把所有历史记录改为摘要式存储,控制 prompt 长度稳定在 5K token 以内。这个问题后面再没出现过。

**案例二:工具调用参数格式不稳定,导致下游系统报错。**Agent 调用查单接口时,偶尔会把订单号带上前导空格,或者把参数名从order_id漂移成orderId。排查发现是模型在长对话中受历史消息影响,格式发生了“漂移”。解法是两层:一是在代码层做参数清洗和格式校验,不依赖模型的自觉;二是在工具描述里加上“参数名必须严格使用order_id,禁止使用任何变体”的强约束。

**案例三:Agent 在用户情绪激动时提供了不符合规范的赔付承诺。**这本质上不是 bug,而是业务规则没有被显式约束。我们在 prompt 里加了“赔付规则由系统工具返回为准,不得自行承诺额外金额”,并在工具侧增加了规则查询能力。这也是我在所有项目中坚定不移推动“规则外置”的原因——把业务规则放进工具调用,比放进 prompt 可靠得多。

**案例四:并发高峰期外部接口被限流,Agent 连环失败。**这个前文已经说过,根本原因是没有并发控制和重试退避。修复方案是加了信号量并发限制和指数退避重试,故障率从 15% 降到 0.5% 以下。

排查经验汇总成一张速查表,方便你遇到问题时对照:

故障现象优先怀疑点处理建议
对话久了“变笨”上下文截断检查 token 用量,做状态外置和摘要化
工具参数偶尔错模型格式漂移代码层强校验,工具描述强约束
重复扣款/重复操作缺乏幂等机制引入请求 ID,全链路幂等
高峰时段连环失败并发控制缺失加信号量限流,指数退避重试
无法定位问题原因没有 trace补全链路日志,按 trace_id 检索
承诺超出规则规则在 prompt 里规则外置到工具调用,代码层兜底

最后分享一个我个人的踩坑体会:接手 Agent 项目之后,我最大的变化是心态上的——永远默认“模型会犯错”,然后围绕这个前提设计系统。以前我做传统后端,默认代码是确定性的,逻辑被验证过就可以依赖。但 Agent 不是,它是概率系统,我们要做的不是祈祷它不犯错,而是把错误的影响限制在可控范围。这个转变听起来是心态问题,落到行动上就是工程决策的全面变化:日志怎么打、状态怎么存、重试怎么做、人工兜底放在哪里。

我始终觉得,Agent 项目的核心壁垒不是“谁的模型调得好”,而是“谁的工程能兜住模型的随机性”。Demo 阶段比的确实是模型上限,但生产阶段拼的是工程下限。谁的下限高,谁才能在真实世界里站稳。这篇分享如果能让你的 Agent 项目在上线后少踩几个坑,我就觉得值了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询