AI agent Checkpoint 与断点恢复:长任务失败后如何继续而不是从头重跑

HTMLPAGE 团队
21 分钟阅读

长任务型 AI agent 不能每次失败都从头重跑。本文讲清 checkpoint 粒度、恢复边界、恢复前校验、补偿动作和失败复盘。

#AI agent #Checkpoint #断点恢复 #工程实践

AI agent 一旦从“单次回答”走向“多步工作流”,就会遇到一个问题:任务跑到一半失败了,应该怎么恢复?很多系统默认答案是“从头重来”。短流程问题不大,但对长任务、昂贵任务、有人工确认节点的任务,这种做法会把成本、等待时间和副作用同时放大。

Checkpoint 的意义不是让任务永远不失败,而是把失败限制在一个可恢复的范围内。

建议先配合 AI Agent 状态机设计指南AI agent 错误分类与恢复策略AI agent 幂等与去重实践AI Agent Session Replay 调试指南 一起看。

先给结论:不是每一步都值得做 checkpoint

阶段是否建议做 checkpoint原因
输入校验成本低,重跑便宜
检索与上下文整理视情况结果可能依赖时效
长规划结果可复用,重算成本高
写入前审批需要保留人工决策
外部工具写入后需要明确副作用已发生
最终响应可重新组织

Checkpoint 不是越多越好。太细会把系统变成快照存储器,太粗又失去恢复价值。

一、先区分三种恢复目标

恢复并不总是“接着往下跑”。至少有三种目标:

恢复目标适用场景
从最近安全点继续工具超时、worker 中断
从上一个稳定规划重算检索过期、上下文变化
终止自动恢复,转人工写入冲突、审批被拒

如果系统只有一个 resume=true 开关,恢复逻辑大概率会越来越乱。

二、Checkpoint 至少要保存什么

一个可恢复 checkpoint 不能只存“做到第几步”。至少要保留:

{
  "checkpointId": "cp_03",
  "runId": "run_123",
  "state": "waiting_tool_result",
  "stepName": "fetch_customer_profile",
  "schemaVersion": "v2",
  "inputSnapshot": { "customerId": "c_456" },
  "artifactRefs": ["artifact_plan_01", "artifact_evidence_02"],
  "sideEffectStatus": {
    "writePerformed": false,
    "externalMessageSent": false
  },
  "createdAt": "2026-05-07T10:00:00Z"
}

这里最关键的是 sideEffectStatus。如果系统不知道副作用是否已经发生,就无法安全恢复。

再往前走一步,很多团队会发现仅有 snapshot 还不够,因为“恢复是否安全”往往取决于 snapshot 之外的环境条件。一个更稳的 checkpoint 记录,通常还会补上:

  • resumePreconditions: 恢复时必须再次满足的条件
  • leaseEpoch: 当前 worker 所属租约代次
  • replaySafeActions: 允许重复执行的动作列表
  • guardHash: 恢复前需要再次校验的关键上下文摘要

这些字段看起来偏底层,但它们能把“能恢复”与“应该恢复”分开。

三、恢复前一定要做 resume guard

恢复不是读取 checkpoint 就直接继续,而是要先判断当前世界是否还允许继续:

检查项目的
任务是否仍有效用户可能已取消
schemaVersion 是否仍可读避免协议漂移
artifact 是否完整避免基于损坏数据恢复
外部状态是否变化目标对象可能已被他人修改
lease 是否仍归当前 worker防止重复执行

这一步可以叫 resume guard。很多恢复事故都不是 checkpoint 丢了,而是跳过了 guard。

四、恢复状态机最好单独建模,不要散落在 if/else 里

Checkpoint 文章里最容易漏掉的一点是:恢复本身也是一个流程,而不是主流程里的一个布尔分支。一个最小恢复状态机通常至少要有:

状态含义
resume_requested收到恢复请求,尚未开始校验
guard_checking正在验证前置条件
resume_ready可以从安全点继续
resume_blocked条件不满足,需要转人工或重算
resuming已重新拿到 lease,准备进入后续 step
resume_failed恢复过程本身失败

如果这些状态没有显式存在,系统就很难回答两个关键问题:

  • 当前失败是业务步骤失败,还是恢复动作失败
  • 一次 Run 到底经历了几轮恢复尝试

这也是为什么恢复日志最好和普通执行日志分开,因为两者表达的问题不同。

五、写入类步骤要区分“可重放”和“不可重放”

恢复时最危险的是写入和外发:

动作恢复策略
读取资料可重新执行
生成草稿通常可重放,但要幂等
更新状态需要版本检查
发送通知默认不可直接重放
扣减额度必须依赖 actionId 幂等

凡是副作用对外可见的动作,都应该先判断“上次到底有没有做成”。不要因为“worker 掉线了”就假设动作没发生。

很多实现最后都会补一份 side effect ledger,专门回答“动作有没有发生过、是否完成、幂等键是什么”。例如:

{
  "actionId": "send_email_001",
  "runId": "run_123",
  "stepName": "notify_customer",
  "idempotencyKey": "run_123_notify_customer_v1",
  "status": "committed",
  "externalRef": "provider_msg_789"
}

有了这层记录,恢复动作就不必从 checkpoint 快照里猜“上次大概做到哪了”,而是直接查副作用账本。

六、Checkpoint 粒度怎么定才划算

一个实用标准是:

  • 比一次完整 Run 便宜得多的步骤,不必存 checkpoint
  • 需要人工输入或人工确认的节点,应该存 checkpoint
  • 会产生外部副作用的节点,前后都值得存 checkpoint
  • 纯短时推理步骤,通常只保留 trace,不单独 checkpoint

你可以把 checkpoint 理解成“恢复成本拐点”的记录,而不是每一步的录像。

如果想把粒度讨论得更具体,可以用这张判断表:

判断问题
这一步重跑成本高吗倾向做 checkpoint倾向跳过
这一步会跨人工或跨系统边界吗倾向做 checkpoint继续看下一项
这一步有不可逆副作用吗前后都做 checkpoint可以只保留 trace
这一步输出会被后续多次复用吗倾向做 checkpoint 或 artifact只保留临时状态

这样比“重要步骤就存一下”更容易在团队内达成一致。

七、恢复预算和熔断要先定义,不要无限次自救

如果系统每次失败都自动 resume,看起来很积极,现实里却可能把单次故障放大成资源雪崩。建议至少定义:

规则建议
单次 Run 最大恢复次数2 到 3 次
同一 checkpoint 最大重复恢复次数1 到 2 次
恢复冷却时间指数退避或按错误类别定义
连续 guard 失败处理直接转人工,不再自动尝试

这套预算不是保守,而是为了防止系统在明知上下文已变化的情况下继续硬闯。

八、失败案例:恢复时直接跳过审批,造成重复外发

一个内容发布 Agent 的流程是:生成草稿 -> 人工审批 -> 发送通知 -> 更新状态。某次在“发送通知后、更新状态前” worker 崩了。恢复逻辑看见上一个 checkpoint 在 approved,就重新跑发送通知,结果通知发了两次。

根因有两个:

  • checkpoint 没记录通知是否已发送
  • resume guard 没检查 outbox/messageId

修复后,发送通知前后都写 checkpoint,并把 messageIddeliveryState 存进 side effect ledger。恢复时若发现 already_sent,就跳过发送,只继续更新状态。

九、上线后要看恢复质量指标,而不只是恢复次数

恢复做出来以后,最值得看的不是“系统有没有触发恢复”,而是“恢复到底帮了多少忙,还是制造了更多噪音”。常见指标包括:

指标解释
恢复成功率恢复后能否真正完成 Run
恢复后再次失败率判断 checkpoint 位置是否不合理
guard 拦截率判断恢复尝试是否过于激进
副作用重复拦截数判断 ledger 与幂等设计是否有效
平均恢复耗时判断恢复是否真的节省时间

如果恢复次数很高但恢复成功率很低,这不叫系统健壮,而叫系统在重复试错。

十、恢复系统要有“放弃恢复”的出口

不是所有失败都值得自动恢复。以下场景更适合直接转人工:

  • 外部数据已明显变化
  • 人工审批结论已被修改
  • schema 版本不再兼容
  • 关键 artifact 丢失或损坏
  • 同一 Run 恢复次数超过阈值

恢复系统最危险的不是保守,而是逞强。

十一、Checkpoint Checklist

  • 是否只在真正有恢复价值的节点写 checkpoint
  • checkpoint 是否保存 schemaVersion 和 sideEffectStatus
  • 是否单独建模恢复状态机,而不是散在主流程分支里
  • 恢复前是否执行 resume guard
  • 写入和外发动作是否区分可重放与不可重放
  • 是否有 side effect ledger 或等价账本记录外部副作用
  • 人工审批节点是否可恢复但不重复执行
  • 是否定义恢复预算、冷却时间和熔断规则
  • 同一 Run 是否有恢复次数上限
  • 无法安全恢复时是否明确转人工

结语

AI agent 的断点恢复,不是“失败后继续跑”这么简单,而是“在确认世界没有变、协议没漂、副作用没重复的前提下继续跑”。Checkpoint 真正保护的不是执行进度,而是恢复时的正确性。

延伸阅读: