跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言Agent Runtime工程化陈堂会可恢复执行

《Agent Runtime 工程化》第八章 Checkpoint、Resume、Rollback

长任务一定会中断。问题是:失败后怎么继续,而不是重来? Agent Runtime 一旦进入真实工程任务,就会遇到长运行:改多个文件、跑多轮测试、安装依赖、查文档、等待用户确认。浏览器刷新、进程崩溃、网络超时、模型失败、用户临时离开,都可能打断 run。如果没有 checkpoint,Agent 只能从头再来;从头再来又可能重复执行副作用。 可恢复执行系统要

站点编辑发布于 2026/8/15更新于 2026/9/325 浏览
《Agent Runtime 工程化》第八章 Checkpoint、Resume、Rollback

《Agent Runtime 工程化:生产级 AI Agent 架构、运行时与工程实践》封面

书名:《Agent Runtime 工程化:生产级 AI Agent 架构、运行时与工程实践》

作者:陈堂会

平台:极客日志(https://zeeklog.com)

X:@Megick_com

联系邮箱:[email protected]

章节:第八章 Checkpoint、Resume、Rollback

第八章 Checkpoint、Resume、Rollback

长任务一定会中断。问题是:失败后怎么继续,而不是重来?

Agent Runtime 一旦进入真实工程任务,就会遇到长运行:改多个文件、跑多轮测试、安装依赖、查文档、等待用户确认。浏览器刷新、进程崩溃、网络超时、模型失败、用户临时离开,都可能打断 run。如果没有 checkpoint,Agent 只能从头再来;从头再来又可能重复执行副作用。

可恢复执行系统要做的事很朴素:把'运行到哪里了'保存下来,而且能验证、能恢复、能回滚。难点也在这里。保存聊天记录不等于保存运行状态,保存文件 diff 也不等于知道哪些工具已经执行。

Checkpoint、恢复与回滚

图 8-1:可恢复执行不是简单保存聊天记录。它必须同时保存对话状态、工具执行状态、文件变更和审批记录。

8.1 checkpoint 保存的是一致性

一个 checkpoint 不只是'某个时刻的数据包'。它保存的是几个系统状态之间的一致性:消息历史、run state、工具账本、文件变更、审批记录、trace 位置。恢复时,这几样必须对得上。

一个 checkpoint 至少包含:

  • session id、run id、step id;
  • message history 或其可重建引用;
  • 当前计划和 stop condition 状态;
  • tool call 计划、执行结果、是否有副作用;
  • 审批记录;
  • 文件系统变更摘要;
  • token/cost/step 预算;
  • provider response id 或 continuation metadata;
  • trace 位置。

示例:

type Checkpoint = {
  id: string;
  runId: string;
  stepId: string;
  createdAt: string;
  messagesRef: string;
  runState: RunStateSnapshot;
  toolLedger: ToolLedgerEntry[];
  fileSnapshot: FileSnapshot;
  approvalsRef: string;
  budget: BudgetState;
  traceRef: string;
};

注意 toolLedger。它记录哪些工具已经执行、是否完成、是否产生副作用、是否可重放。没有 ledger,resume 时很容易重复执行'发邮件''删文件''提交订单'这类不可重复动作。

8.2 tool ledger 是恢复执行的账本

工具账本应在工具执行前后都写入。执行前记录计划,执行后记录结果。这样即使进程崩在中间,恢复时也能判断'这个工具是否可能已经产生副作用'。

type ToolLedgerEntry = {
  callId: string;
  stepId: string;
  toolName: string;
  inputHash: string;
  status: "planned" | "approved" | "started" | "succeeded" | "failed" | "uncertain";
  riskLevel: RiskLevel;
  idempotency: "idempotent" | "conditional" | "non_idempotent";
  replayPolicy: "auto" | "ask" | "never";
  sideEffects: string[];
  startedAt?: string;
  finishedAt?: string;
  resultRef?: string;
};

状态 uncertain 很重要。比如 runtime 发起了外部 API 请求,进程在等待响应时崩溃。恢复时你不知道请求是否成功。此时不能自动重放,只能查询外部系统状态、请求用户确认,或执行补偿逻辑。

对本地文件修改,也要记录 base hash 和 patch hash。这样恢复时才能知道 patch 是否已经应用过,是否被用户手动改动过。

8.3 checkpoint 的保存时机

保存 checkpoint 的时机建议固定下来,不要临时发挥。

时机目的
run 开始建立初始状态
每个 step 请求模型前保存模型输入前状态
工具计划生成后保存待执行意图
高风险工具审批后保存用户决策
工具执行开始时标记可能出现 uncertain
工具执行完成后保存结果和副作用
文件写入后保存 patch、hash 和工作区状态
run 结束保存最终状态

最容易漏的是'工具执行开始时'。如果只在执行后写 checkpoint,进程崩溃就会留下空白。恢复系统必须知道:这个工具到底没开始、开始但未确认完成、还是已经完成。

8.4 patch-based checkpoint

对 coding agent 来说,文件系统状态是第一等公民。最轻量的做法是 patch-based checkpoint:每次写入前后记录 base hash 和 diff。

type FilePatchEntry = {
  path: string;
  beforeHash: string;
  afterHash: string;
  patchRef: string;
  toolCallId: string;
  createdAt: string;
};

优点:

  • 存储小;
  • 容易审计;
  • 适合代码修改;
  • 可与用户 review 流程结合。

缺点:

  • 二进制文件处理麻烦;
  • patch 冲突需要解决;
  • 外部副作用无法覆盖;
  • 工作区已有用户修改时要小心。

Runtime 在写文件前应记录 base hash,写完后记录 diff。回滚时先确认当前文件是否仍然匹配预期;如果用户又改过文件,不要强行覆盖,应转入冲突处理。

8.5 git-based checkpoint

另一种做法是借助 git。每个 step 或关键写入点创建临时 commit、stash、worktree 或 patch 文件。

git-based 的优点是成熟、可审计、适合代码项目。缺点也明显:不能假设所有 workspace 都是 git 仓库,也不能随意污染用户历史。实践中更推荐保存 patch 和 metadata,而不是自动创建用户可见 commit。需要 commit 时,应让用户确认。

一个折中方案是:

  • 检测是否为 git 仓库;
  • 读取当前 HEAD 和 dirty 状态;
  • checkpoint 保存 patch 文件,不自动 commit;
  • 如果用户要求提交,再创建 commit;
  • 回滚前检查 dirty changes 是否包含用户改动。

这里要尊重用户工作区。Agent 写的 diff 和用户原有 diff 要能区分。否则'回滚 Agent 的改动'会误伤用户正在写的代码。

8.6 crash recovery 流程

恢复流程要保守:

  1. 找到最新完整 checkpoint;
  2. 校验 checkpoint 文件完整性;
  3. 校验 workspace 状态;
  4. 恢复 message history 和 run state;
  5. 检查最后一个 tool call 是否已完成;
  6. 对不可重放工具禁止自动重放;
  7. 给模型注入恢复说明;
  8. 从下一个安全 step 继续。

恢复说明不要写成含糊的'继续之前任务'。应该明确告诉模型:

系统从 checkpoint 恢复。
Checkpoint: ckpt_20260814_004
上一次已完成 step_8。
工具 run_command(call_15) 执行 npm test,失败,错误摘要如下……
不要重复执行 apply_patch(call_13) 和 run_command(call_15)。
请根据已有观察规划下一步。

这段恢复说明会进入 Context Builder 的高优先级区域。模型需要知道'继续',而不是从头再来。

8.7 幂等性决定能不能重放

幂等性是恢复执行的核心词。一个工具如果重复执行不会造成额外副作用,就更容易恢复。例如读文件、搜索、纯计算通常幂等。写文件如果基于相同 base hash 应用同一个 patch,也可以设计成条件幂等。发邮件、支付、删除远程资源通常不幂等。

工具定义中应声明:

type ToolDefinition = {
  name: string;
  idempotency: "idempotent" | "conditional" | "non_idempotent";
  replayPolicy: "auto" | "ask" | "never";
};

恢复时可以按这个表处理:

幂等性示例恢复策略
idempotentread_file、search_code可自动重放
conditionalapply_patch、write_file校验 base hash 或 patch hash 后决定
non_idempotentsend_email、create_issue、支付不自动重放

幂等性不是工具名固定属性,也和输入有关。run_command("ls") 幂等,run_command("npm publish") 不幂等。命令工具尤其要在计划阶段重新分类。

8.8 rollback 不是一个 undo 按钮

用户说'回滚'时,可能有三种意思:

  • 回滚文件到某个 checkpoint;
  • 恢复对话状态,让 Agent 回到某个计划阶段;
  • 补偿外部副作用,例如关闭刚创建的 issue。

Runtime 必须区分这三件事。文件 patch 可以回滚,对话状态可以恢复,外部副作用通常只能补偿,不能直接撤销。比如创建了 GitHub issue,可以关闭;发出的邮件不能收回;执行了数据库 migration,可能需要 down migration。

所以 UI 和 API 都应使用具体措辞:

type RecoveryAction =
  | { type: "rollback_files"; checkpointId: string }
  | { type: "restore_session"; checkpointId: string }
  | { type: "compensate_external_action"; ledgerEntryId: string };

不要把一切都叫 undo。模糊的词会带来错误的用户预期,也会让实现偷懒。

8.9 冲突处理要保护用户改动

恢复和回滚时,最棘手的是用户在 Agent 中断后继续改了文件。此时 checkpoint 里的 base hash 和当前文件 hash 不一致。

不要强行覆盖。建议进入冲突状态:

type CheckpointConflict = {
  path: string;
  expectedHash: string;
  actualHash: string;
  agentPatchRef: string;
  resolution: "pending" | "keep_user" | "apply_agent" | "manual_merge";
};

冲突提示应告诉用户三件事:哪个文件冲突,Agent 原本想改什么,当前文件和 checkpoint 不一致。对于代码项目,可以生成三方 diff:base、agent change、current file。

保护用户改动是底线。Agent 的恢复能力不能以覆盖用户工作为代价。

8.10 checkpoint 存储与清理

checkpoint 会增长。长任务如果每步都保存完整消息和文件快照,很快占用大量空间。工程上需要存储策略:

  • 消息历史保存引用,正文可压缩;
  • 工具长输出保存 artifact 引用;
  • 文件变更保存 patch,不重复保存完整文件;
  • 只保留关键 checkpoint,清理中间临时点;
  • 对包含敏感信息的 checkpoint 做加密或脱敏;
  • checkpoint index 单独保存,方便快速查找。

一个目录可以这样设计:

.agent-runtime/
├── checkpoints/
│   ├── ckpt_001.json
│   └── ckpt_002.json
├── artifacts/
│   ├── tool_call_17.stdout.txt
│   └── patch_18.diff
├── ledger.jsonl
└── trace.jsonl

JSONL 适合追加写入。checkpoint JSON 适合快速恢复。artifact 适合保存大输出和 diff。

8.11 本章的实现路径

第一步,为第三章的 run state 增加 checkpoint store。先支持本地文件存储,不急着接数据库。

第二步,每个 step 前保存 pre-checkpoint,每个 step 后保存 post-checkpoint。

第三步,加入 tool ledger。工具执行前写 started,执行后写 succeeded 或 failed;进程崩溃后未完成项按 uncertain 处理。

第四步,为文件写入工具记录 base hash、after hash 和 patch ref。

第五步,实现 resume:读取最新完整 checkpoint,校验 workspace,生成恢复说明,禁止重放不可重复工具。

第六步,实现 rollback_files:只回滚 Agent 自己的 patch,遇到用户修改则进入冲突处理。

第七步,给恢复和回滚加 trace event。后面第九章会用这些事件做可观测分析。

8.12 验收标准

完成本章后,runtime 应能在崩溃后继续,而不是从头再来;能回滚 Agent 的文件改动,而不误伤用户改动;能解释哪些工具已执行、哪些不能重放、为什么从某个 checkpoint 恢复。

建议验收用例:

用例期望结果
Agent 修改文件后进程崩溃重启后识别 patch 已应用,不重复写入
工具执行开始后崩溃ledger 标记 uncertain,不自动重放高风险工具
用户在崩溃后手动改同一文件resume 进入冲突处理
回滚到上一个 checkpoint只撤销 Agent patch,保留用户原有改动
非幂等 MCP 工具已执行resume 时禁止自动重放
恢复后模型继续任务上下文包含 checkpoint、已执行工具和不可重放工具

做到这里,runtime 才从脚本接近系统。它能承认中断会发生,并为中断准备好证据、路径和边界。


系列文章目录

  • 《Agent Runtime 工程化》完整目录
  • 《Agent Runtime 工程化》第一章 Agent Runtime 全景
  • 《Agent Runtime 工程化》第二章 TypeScript / Node Runtime 基础
  • 《Agent Runtime 工程化》第三章 最小 Agent Loop
  • 《Agent Runtime 工程化》第四章 工具系统设计
  • 《Agent Runtime 工程化》第五章 上下文工程
  • 《Agent Runtime 工程化》第六章 MCP 与 Provider 抽象
  • 《Agent Runtime 工程化》第七章 权限与安全边界
  • 《Agent Runtime 工程化》第八章 Checkpoint、Resume、Rollback
  • 《Agent Runtime 工程化》第九章 可观测与 Trace
  • 《Agent Runtime 工程化》第十章 Eval Harness 与 CI 回归
  • 《Agent Runtime 工程化》第十一章 Agent Runtime 进阶学习路线
  • 《Agent Runtime 工程化》第十二章 hermes-agent 产品级实战
  • 《Agent Runtime 工程化》附录

目录

  1. 第八章 Checkpoint、Resume、Rollback
  2. 8.1 checkpoint 保存的是一致性
  3. 8.2 tool ledger 是恢复执行的账本
  4. 8.3 checkpoint 的保存时机
  5. 8.4 patch-based checkpoint
  6. 8.5 git-based checkpoint
  7. 8.6 crash recovery 流程
  8. 8.7 幂等性决定能不能重放
  9. 8.8 rollback 不是一个 undo 按钮
  10. 8.9 冲突处理要保护用户改动
  11. 8.10 checkpoint 存储与清理
  12. 8.11 本章的实现路径
  13. 8.12 验收标准
  14. 系列文章目录

更多推荐文章

查看全部
  • 热门 AI 视频工具盘点:Pika、Runway、Stable Video 等介绍
  • Linux diff 与 patch 命令实战指南
  • Android 11.0 Framework 核心原理与系统启动流程解析
  • AIGC 时代 C++ 突破推理吞吐瓶颈的 3 大核心技术
  • OpenAI 首款 AI 硬件为笔形设备并研发音频模型;Pickle 四摄 AR 眼镜预售遭质疑
  • Python 全栈学习路线指南:入门、爬虫、数据分析与 Web 开发
  • Python+AI 学习路线指南:从入门到实战
  • MySQL 复合查询与子查询详解
  • 大模型应用开发:动手做 AI Agent 技术指南
  • VR、具身智能与人形机器人:构建现实世界的智能接口
  • OpenAI gpt-oss 开源模型本地部署教程
  • C++ 核心基础特性详解:重载、引用、内联、auto 与 nullptr
  • browser-use + web-ui 大模型实现自动操作浏览器
  • AI 大模型在各国政务领域应用深度研究报告
  • OpenAI 发布 49 页报告详解 o1 安全机制
  • OpenClaw 开源桌面 AI Agent 框架功能与架构解析
  • OpenAI 官方 Prompt 工程指南详解:六大核心原则与实战技巧
  • Java JUnit NoSuchMethodError 异常排查与修复方案
  • 大语言模型(LLM)入门教程:从原理到训练微调
  • 3ds Max VR 渲染器局部渲染设置指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online