回退路径萎缩:你的降级方案在三个月前就失效了
你在九个月前编写的回退路径(fallback path)——那个用于捕获模型超时、切换到更便宜的供应商、并在两者都宕机时返回模板化消息的路径——实际上在过去的十二周里从未在生产环境中运行过。它仅在最初发布时被执行过一次,集成测试仍然能通过,操作指南(runbook)也仍在使用它。但这并不意味着它还能工作。第六周的一次重构改变了上游上下文对象的形状。第九周的一次依赖库升级悄悄移动了一个配置键。代码仍然可以编译。测试仍然能通过,因为它们是针对与代码相同的陈旧 Fixture 编写的。下次当你的主路径出现 504 错误时,你的“优雅降级”将会把一个 NullPointerException 甩在用户脸上,而复盘报告将会指出——这已经是今年第三次了——在上游契约变更后,回退路径从未被重新测试过。
这是 AI 系统韧性工程中一种隐性的失败模式。回退路径是你应用程序中专门为了被忽视而存在的部分。在一百天里,有九十九天生产流量都会绕过它。CI 从不执行它,因为没有任何测试与之关联。负责它的团队在两次事故之间会忘记它的存在。然后在第一百天,当主模型供应商出现区域性故障,你终于需要它时,这段代码却在付费客户面前发生了代码腐烂(bit-rots)。
这种模式在传统的分布式系统中很常见,但在 AI 功能中由于两个原因被放大了。首先,依赖关系更不稳定——全行业 LLM API 的正常运行时间大约在 99.0% 到 99.5% 之间,而一个健康的云控制平面通常能达到 99.97%,因此回退路径被“需要”的频率比典型的 CRUD 服务更高。其次,上游契约更迭更快:提示词会变,模型版本会弃用,工具 Schema 会被重命名,频率限制策略会调整,而每一次变更都有可能使一段整整一个季度都没人读过的代码路径中的假设失效。
为什么测试套件无法捕获这些问题
直觉上的辩解是“我们对回退路径有集成测试”。由于结构性原因,这些测试通常无法捕获萎缩:它们是根据回退路径编写时的世界快照来执行的。如果快照是一个记录主路径失败的 HTTP 录像(cassette),或者是一个具有特定形状的模拟异常(mocked exception),那么测试就将回退路径的行为绑定在了一个僵化的错误契约上。当真实的上游改变了其 503 响应体、重试头(retry-after header)语义,或者是由于工具调用中途截断而导致的部分响应流形状时,记录的测试 Fixture 并不会随之改变。回退测试显示为绿色,但回退功能已经损坏。
更深层次的问题是,回退路径的大多数 Bug 源于“主路径”的演变,而非其自身。当一次重构通过请求上下 文传递一个新字段时,正常路径的代码会读取它;回退路径不会,但它也不会报错——直到某个用户查询进入降级模式,回退路径解引用了一个它预期存在的东西。参与那次重构的工程师中没有一个人在关注回退路径。代码审查者也没有。回退路径不在 Diff 差异中。没有绿灯或红灯,因为没有测试在练习这个接缝。
这与导致死代码积累的动态是一样的,只不过这段代码并不是死的——它是“休眠”的,等待着在某个特定糟糕的日子醒来。这种萎缩是不可见的,直到你需要代码正常工作的那一刻。
回退方案已成为真实的产品表面
还有一个更近期的变化让情况变得更糟:随着 AI 功能成为产品体验的核心,降级模式不再是一个隐藏的技术细节,而是变成了一个“真实的产品表面”。用户能看到它,会截图,会发推。他们会根据主模型宕机时对话窗口中显示的内容来形成对你品牌的看法。
对于一个内部工具来说,显示“发生错误,请重试”的空白屏幕曾经是可以接受的。但对于用户以此构建工作流的旗舰功能来说,这是不可接受的。如果一个用户过去六周每天早上都使用你的 AI 助手来整理收件箱,那么你的降级模式就不再仅仅是一个技术回退——它是你在故障期间发布的产品版本。如果它体验很糟糕,那这就是用户记住的产品版本。
这在产品上的启示是,“优雅降级”需要与正常路径相同的关注:相同的 UX 审查、相同的提示词审查、相同的评估套件以及相同 的运维(on-call)责任。如今,在大多数团队中,降级模式无人负责、无人审查,在发布冲刺期间可能只有三个工程师见过。然后它就被发布出去,积累了一万名用户,而这些用户只有在下一次三小时的停机期间才会看到它。
故障注入纪律的样貌
治疗退化的良药是定期使用。不运行的代码路径会失效;运行的代码路径会得到修复。因此,针对 AI 备用方案的工程规范看起来非常像混沌工程,只是收窄到了模型驱动系统在生产环境中实际会遇到的特定故障模式。
一份实用的清单,大致按投入成本递增排序:
- 以固定频率引入合成故障流量。 选取极小比例的流量(0.5% 或 1%),并将其路由到模拟的上游故障:强制 504 错误、强制限流、或强制返回格式错误的 JSON 响应。备用路径每天都在真实的生产上下文、当下的上游契约以及当前部署的代码中运行。如果它失效了,警报会在流量还小到足以恢复时触发。
- 强制超时日。 选取一个周期性的窗口——比如周三下午,或者 Sprint 的最后一个小时——安排一次混沌演练。此时,较高比例的流量会从主供应商那里收到合成超时。备用路径承担真实负载。值班团队观察的是专为降级体验(degraded UX)设计的仪表盘,而不是针对正常路径(happy path)的。这能捕获那些只有在备用路径处理多样化真实查询、而非合成测试集时才会浮现的退化 Bug。
- 限流混沌演练。 供应商限流是生产中 AI 备用方案被激活的最 常见原因,也是最容易模拟的:在特定窗口内将配置的限额降低 90%,强制系统溢出到备用队列或备用供应商。这不仅验证了备用模型的正确性,还验证了路由逻辑、重试预算、熔断器阈值和队列深度假设——所有这些都会独立于备用 Prompt 发生退化。
- 备用路径评估套件。 正常路径有评估(Eval)套件,备用路径也应该有一个——相同的回归标准、相同的规范查询集、相同的评分细则。备用方案的存在是因为主方案失败了,但这并不意味着用户应该得到更差的答案,可能只是更慢或更简单。如果备用方案的评估分数自上次运行以来下降了 15 分,说明上游的某些底层细节已经发生了变化。
- 契约差异警报。 每当上游供应商的 API 规范、错误封装或模型版本发生变化时,触发一个 CI 信号,标记所有消费该契约的备用路径。这虽然不能捕获所有的退化 Bug,但在依赖版本升级后,它能极大地缩小你需要手动重新测试的范围。
所有这些的核心目的都是一样的:将备用方案从休眠代码转变为每天针对当前现实运行的代码。成本很小——一个百分点的流量、一次自动化演练、一个 CI 钩子。而收益则体现在真正的宕机来袭、降级模式确实奏效的那一天。
组织层面的觉悟
这要求组织层面将“降级体验”视为一个产品,而不仅仅是一个脚注。这意味着几件具体的事情:
PRD 应该描述用户在降级期间看到的内容,而不只是在正常路径上看到的内容。“助手返回有用的答案”是正常路径的规范;相应的降级规范是“当主模型不可用时,助手在三秒内返回一个来自备用模型的、带有清晰标记的、质量略低的答案;如果两者都宕机,则返回模板消息。”两者都值得拥有评估案例,也都值得进行 UX 评审。
值班轮换应负责备用方案。 如今,当备用方案失效时,团队往往是从客户那里得知的。如果备用方案有了负责人,警报会在合成故障流量中触发,团队会在周二上午 11 点通过 Slack 通知得知消息,而不是在周五的复盘会上。
发布清单应包含备用方案演练。 在功能正式发布(GA)之前,团队要在预发布环境中进行一次实际的宕机模拟,持续时间要长于主供应商历史上最长的宕机时间——通常是数小时,而非几分钟。如果团队自己都无法忍受两个小时的降级体验而不感到焦虑,那么用户也无法忍受。
代码库应将备用路径视为一等分支,而不是被遗忘的角落。这意味着当其依赖项发生变化时,它需要接受评审,而不仅仅是在它自己的代码变化时。这意味着备用方案应该出现在部署流水线的冒烟测试中,而不仅仅是集成测试套件中。这意味着备用路径中的 Prompt 应该与主 Prompt 记录在同一个变更日志中,并遵循相同的签收流程。
本周可以做的事
如果一个团队发布了带有备用路径的 AI 功能,且两个月没动过它,那么以下三个具体行动可以快速产生效果。第一,手动对预发布环境中的单个用户会话触发合成超时——看看会发生什么,看看备用方案是否运行,看看在当下的 Prompt 和上下文结构下,降级体验是什么样的。第二,为备用路径编写五个评估案例,并在当前部署的代码上运行;检查分数是否符合团队的预期。第三,在日历上为下周安排一次三十分钟的混沌演练,指定负责人。这种规范的建立,始于在日历上安排的一次演练。
韧性不是系统拥有的一种属性,而是系统经过练习而获得的一种属性。从未运行过的备用代码不是备用方案——它只是一个假设。下一次宕机会告诉你这个假设是否成立,但到那时再发现就太晚了。在 2026 年能够交付可靠 AI 功能的团队,是那些每周都在练习降级模式的团队,而不是那些在发布时写了最复杂备用方案的团队。
- https://github.com/deepankarm/agent-chaos
- https://www.arxiv.org/pdf/2511.07865
- https://fast.io/resources/ai-agent-chaos-engineering/
- https://dev.to/franciscohumarang/why-chaos-engineering-is-the-missing-layer-for-reliable-ai-agents-in-cicd-3mnd
- https://www.boozallen.com/insights/ai-research/ensuring-resilience-in-ai.html
- https://www.getunleash.io/blog/graceful-degradation-featureops-resilience
- https://ilovedevops.substack.com/p/graceful-degradation-when-models
- https://www.infoq.com/presentations/graceful-degradation-chaos-engineering/
- https://www.aiuxdesign.guide/patterns/error-recovery
- https://testrigor.com/blog/what-are-fallbacks-in-ai-apps/
- https://sreschool.com/blog/graceful-degradation/
- https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html
- https://itsoli.ai/when-ai-breaks-building-degradation-strategies-for-mission-critical-systems/
- https://www.buildmvpfast.com/blog/building-with-unreliable-ai-error-handling-fallback-strategies-2026
- https://www.getmaxim.ai/articles/retries-fallbacks-and-circuit-breakers-in-llm-apps-a-production-guide/
- https://towardsdatascience.com/the-next-frontier-of-ai-in-production-is-chaos-engineering/
- https://cloud.google.com/blog/products/devops-sre/using-chaos-engineering-to-test-dr-plans
- https://insightfinder.com/blog/ai-reliability-detect-prevent-failures/
- https://dzone.com/articles/the-hidden-failure-modes-of-ai-systems
