Files
blog/content/posts/preenacted-prompt.md
T

4.1 KiB

title, description, date, draft, tags
title description date draft tags
它预演了一个不存在的提示 执行 Agent 给用户弹了一个格式完全正确的「二选一」确认框,用户认真选了 A,结果工单静默派去了寄修组。排查发现:那个提示从头到尾没被任何脚本生成过——是模型自己脑补的。 2026-09-09T18:50:00+08:00 false
AI Agent
事故复盘
幻觉

事故:一个认真的选择,落进了静默兜底

一张工单,地址在「某县级市」。执行 Agent 弹出一个二选一确认框,格式完全正确,让用户选派单方向。用户认真选了 A。

结果工单静默派去了寄修组——A 选项的映射根本没生效,异地兜底逻辑接管了。

排查时先问了一个更奇怪的问题:这个二选一提示,是谁生成的?

破案:提示是模型脑补的

三份证据,指向同一个结论:

  1. 那条提示对应的对话记录,是纯模型输出——没有任何工具调用
  2. 操作日志里,没有这次拦截的记录
  3. 待确认队列里,也没有这条工单

也就是说:脚本从头到尾没触发过二选一拦截。 那个格式完美的确认框,是模型自己生成的。

它看到了建单输出里的地址「某县级市新开河路」,又记得记忆里有一条「某县级市是二选一城市」的规则,于是自己脑补了一个拦截提示——格式、措辞、选项,全都对,唯独不是真的。

第二层:就算真触发,也匹配不上

继续往下挖,发现就算模型没脑补,真跑脚本也会出问题:

  • 二选一城市的匹配,只查工单的 city 字段
  • 但 工单系统 工单里,city 是「某地级市」,region(区县)才是「某县级市」
  • 配置里的键是「某县级市」→ 查 city=某地级市 永远命中不了 → 拦截从未真实触发

于是用户选的 A,落到 --no-choice 映射时找不到对应项,静默走了异地兜底寄修组。

两层错误叠加:模型预演了一个假提示(认知层),代码的区县匹配又漏了(代码层)。用户从头到尾都在跟一个不存在的对话框互动。

修复:代码 + 铁律

代码层:把二选一判断和选 A 映射的查找链,从「只查 city」扩成四级——city → city_norm → region → region_norm。顺手扫了同型隐患(第三方平台分组也有同样的「某县级市键」问题),一并修了。

认知层:给执行 Agent 立了一条铁律——

执行结果必须来自真实输出。只有工具结果里真实出现了拦截文本,才转述;否则先跑脚本看真实输出,严禁凭记忆预演

这条和之前「输入原文传递」的铁律配成一对:输入不改字,输出不预演。

为什么这比普通 bug 更危险

普通 bug 是「代码错了」,日志里能查到、能复现、能定位。

模型预演是「它看起来完全正确,但从未发生」。用户无从分辨——提示的格式、措辞、选项全都对,谁会怀疑它是假的?

更危险的是它的镜像:假成功。如果模型没派单却回复「已派单」,那就是漏单——比预演提示更隐蔽,因为连一个「看起来不对」的痕迹都没有。

总结

  1. Agent 的输出要能溯源。每一条「执行结果」的表述,都应该对应某一次真实的工具调用结果。凭空生成的、格式再漂亮,也是幻觉
  2. 「看起来对」不等于「真的发生了」。排查时先问:这件事有没有在日志/队列/工具结果里留下痕迹
  3. 配置的键和数据的字段要对齐cityregion 是两个字段,配置里写了「某县级市」却只查 city,等于白写
  4. 软约束的边界要诚实。铁律写在 AGENTS.md 里,依赖模型遵循——如果还出现预演,就得考虑脚本侧预检这种硬约束

上一回它忘了自己是谁,这一回它预演了没发生的事。AI Agent 的坑,一半在代码,一半在「它以为」。


本文已脱敏,不含真实工单号、人名、域名或系统内部标识。