AI Agent 生产故障 Runbook:常见故障与应急处置
传统服务的 Runbook 处理的是”数据库挂了""磁盘满了”这类确定性故障。AI Agent 生产环境的故障模式不一样——很多问题不是”报错”,而是”看起来正常运行但在做错事”:工具调用停不下来、上下文越滚越大、模型开始输出看似合理但完全跑偏的操作。这类故障传统监控告警抓不住,需要一份专门的 Runbook。本文整理几类最常见的生产故障,给出识别信号、止血步骤和事后复盘模板。
一、故障速查表
出问题时先按症状定位类型,再翻对应章节:
| 症状 | 对应故障 | 章节 |
|---|---|---|
| 账单突然异常增长 | 成本飙升 / 循环调用 | 二、三 |
| Agent 反复调同一个工具不停 | 工具调用风暴 | 二 |
| 任务跑了很久没有结束信号 | 无限循环 | 三 |
| 数据被删除/修改但没人操作 | 幻觉性破坏操作 | 四 |
| 大量任务卡在同一个队列不动 | 上游依赖阻塞 | 五 |
| 输出质量突然普遍下降 | 上下文污染/模型侧变化 | 六 |
二、工具调用风暴
识别信号:短时间内同一个 session 对同一个工具发起几十上百次调用,日志里同一个函数名反复刷屏。
立即止血:
- 在网关或应用层给单会话设置硬性工具调用次数上限(比如单任务超过 50 次工具调用强制终止),这是最后一道闸门,没有的话先临时加一个:
MAX_TOOL_CALLS_PER_TASK = 50
if task.tool_call_count > MAX_TOOL_CALLS_PER_TASK:
task.abort(reason="tool_call_storm")
alert_oncall(task.id)
- 定位触发风暴的具体任务/用户输入,隔离该 session,避免同类输入继续触发同样行为。
- 检查是不是工具返回结果本身有问题(比如工具报错信息里包含容易被模型误读为”再试一次”的措辞),风暴经常是模型对错误反馈的错误反应造成的,不是模型本身”坏了”。
根因方向:工具的错误提示语义模糊、缺少调用次数上限、system prompt 没有明确”多次失败后停止并汇报”的指令。
三、无限循环 / 任务不收敛
识别信号:任务运行时间远超正常分布(比如平均 2 分钟的任务这次跑了 40 分钟仍未结束),token 消耗持续增长但没有产出。
立即止血:
- 每个任务必须有硬超时,没有配置的话这是最紧急要补的:
import asyncio
try:
result = await asyncio.wait_for(run_agent_task(task), timeout=300)
except asyncio.TimeoutError:
task.mark_failed(reason="timeout")
enqueue_dead_letter(task) # 参考死信队列设计
- 超时任务不要直接丢弃,扔进死信队列供事后分析——循环任务往往能复现,具体设计参考《Agent 失败任务死信队列设计》。
- 查任务的完整轨迹(trace),确认是”卡在同一个状态反复横跳”还是”确实在推进但太慢”,两者处理方式不同:前者要杀,后者可能只是超时阈值设低了。
根因方向:Agent 的终止条件设计不完整(比如只有”任务完成”这一个退出分支,没有”多次尝试仍未达成目标时主动放弃”的分支)。
四、幻觉性破坏操作
这是最危险的一类:Agent 有实际的写权限(改数据库、删文件、发消息),在某次推理里”幻觉”出一个不该执行的破坏性操作,且没有及时被拦截。
识别信号:数据被修改/删除但没有对应的正常业务触发记录;用户反馈”我没做这个操作”。
立即止血:
- 先看有没有开自动批准(Auto-Approve)。如果破坏性操作类别(删除、发送外部消息、资金相关)配置成了自动批准,第一时间收回,改成强制人工确认:
高风险操作分类(必须人工确认,不允许自动批准):
- DELETE / DROP 类数据库操作
- 对外发送消息(邮件、IM、社交媒体)
- 涉及金额的写操作
- 修改权限/账户配置
- 检查该 Agent 是否有操作前快照机制,能否直接回滚。没有快照的写操作,事后只能靠数据库层面的 binlog/审计日志恢复。
- 立即暂停该 Agent 的写权限(保留读权限用于排查),直到确认根因。
根因方向:高风险操作没有强制人工审批闸门。这类操作的审批队列设计可以参考《Agent 人工审批队列设计》——任何有破坏性副作用的操作都不应该允许 Agent 自主执行完成,这不是”配置疏忽”级别的问题,是架构红线。
五、上游依赖阻塞
识别信号:大量任务卡在同一个阶段不动,但没有报错,队列长度持续增长。
立即止血:
- 检查是不是某个外部依赖(模型 API、向量数据库、第三方工具)限流或宕机,Agent 任务卡在等待重试。
- 如果是模型 API 侧限流,检查网关的降级链是否生效——正常情况下应该自动切到备用模型,如果没切,说明降级链配置或触发条件有问题。
- 短期内可以手动暂停接收新任务(而不是让新任务继续堆积进已经阻塞的队列),等依赖恢复后再放量。
根因方向:缺少熔断机制,或者熔断阈值设置不合理(比如要连续失败 100 次才触发,实际场景下早就该触发了)。
六、输出质量突然下降
识别信号:没有代码变更、没有 prompt 变更,但用户反馈输出质量普遍变差,或者人工抽查发现回答开始跑题。
排查顺序:
- 先看是不是上下文污染——多轮对话里累积了错误信息或者过期状态,导致后续推理基于错误前提。检查是否有上下文长度限制触发了不合理的截断(截断掉了关键的 system prompt 而不是历史消息)。
- 再看是不是模型侧变化——如果用的是别人维护的托管模型,供应商可能在后台做了模型版本切换或者权重更新。锁定模型版本号(如果平台支持指定版本而非
latest别名)能排除这个变量。 - 最后看输入分布是否变化——上游业务变化导致输入内容的分布本身偏移了(比如突然大量涌入一种之前没见过的语言或格式),模型表现下降可能是输入侧的问题,不是模型或代码的问题。
七、事后复盘模板
止血完成后,24 小时内补一份结构化复盘,字段不需要多,但要覆盖:
## 故障复盘:<简述>
- 影响时间窗口:
- 影响范围(任务数/用户数/金额):
- 首次发现方式(告警/用户反馈/人工巡检):
- 根本原因:
- 止血动作(时间线):
- 为什么现有防护没拦住:
- 需要补的防护措施(按优先级排列,标注 owner 和截止日期):
“为什么现有防护没拦住”这一行最容易被跳过,但最重要——如果止血靠的是人工发现而不是自动告警,说明监控本身有缺口,这个缺口应该被列为跟根因同等优先级的待办项。