跳到正文

AGENT PROJECT INTERVIEW · Q07 / 25

Agent 任务中断后怎么恢复?Checkpoint、断点续跑和人工审批怎样设计

系统讲清 Agent Checkpoint 保存什么、如何断点续跑、怎样用幂等避免重复副作用,以及人工审批、版本兼容和故障注入如何设计。

作者与复核:吴师兄内容依据:公开 Agent 教程、项目题资料与工程推导查看关联教程 →查看吴师兄公开作品 →

25 道题目Q07
本页内容19 节

30 秒先说结论

Checkpoint 应保存任务与图版本、当前节点、结构化 State、已提交和待执行动作及外部凭证。恢复先取得单执行者锁,再校验版本、权限和外部状态,从下一项未提交动作继续。写操作依靠幂等键或业务核对防重复,高风险动作生成绑定参数的审批请求,批准后仍重新校验。

面试官问:“Agent 跑到一半进程挂了,或者遇到高风险操作要等人确认,恢复时怎么保证不从头再来,也不会重复执行?”

只报出“LangGraph Checkpoint”远远不够。保存一份状态很容易,真正困难的是:保存的状态能否代表一个一致的执行位置,恢复时使用哪版代码和工具,已经完成的写操作会不会再做一次,审批前后状态有没有被篡改,以及等待几小时后外部数据发生变化该怎么办。

如果现有项目还没有完整实现持久化恢复,也不必编造“已经支持秒级恢复”或“恢复成功率”。这类题完全可以按系统设计题回答:先说明要解决的失败场景,再给出状态模型、暂停协议、幂等边界和验收用例,并明确哪些部分仍需真实实现与压测。

先给出 30 秒回答

Checkpoint 不是简单保存聊天记录,而是保存一个可恢复的执行快照:任务标识、图版本、当前节点、结构化 State、已完成动作、待执行动作和外部副作用凭证。运行时只在定义好的安全点提交快照,恢复时先校验版本、权限和外部状态,再从下一项未提交动作继续。写操作必须有幂等键或业务去重,不能靠“记得执行过”防重复。需要人工审批时,系统生成不可混淆的审批请求并暂停,审批结果作为新事件写入,再重新校验条件后继续。是否设计合格,要通过进程崩溃、重复恢复、过期审批、版本升级和并发点击等故障用例验证。

这段回答的核心是三个边界:Checkpoint 负责记录一致状态,幂等负责防止重复副作用,人工审批负责把高风险决策交还给有权限的人。三者缺一不可。

保存状态不等于可以安全恢复

恢复能力的重点不是“存了”,而是“从哪个一致位置继续,并且不会重复做事”。

先区分三种经常混在一起的需求

失败恢复

进程退出、机器重启、模型接口超时或工具服务暂时不可用后,任务需要从最近的安全位置继续。目标是减少重复计算,同时保证状态一致。

主动暂停

任务可能因为预算、缺少用户信息、达到风险节点而暂停。系统不是发生故障,而是在等待一个明确事件,例如用户补充参数、管理员批准或资源恢复。

人工审批

模型提出了一个有副作用的行动,例如发送外部消息、修改配置或提交业务操作。系统需要把行动内容、原因、影响范围和校验结果交给有权限的人,由人选择批准、拒绝或修改后再继续。

这三类场景都可能使用 Checkpoint,但恢复条件不同。失败恢复关注“上次稳定提交在哪里”;主动暂停关注“等待什么事件”;人工审批还要解决身份、授权、审计和过期问题。只设计一个 status = paused 远远不够。

为什么只保存 Messages 不够

Messages 记录了用户、模型和工具之间的对话,但它通常无法回答下面这些工程问题。

当前图运行到哪个节点?计划中的哪些步骤已经提交?某个工具调用只是模型提出了请求,还是后端已经执行成功?外部接口已经创建了一条记录,但结果回写前进程崩溃,该动作算完成还是未完成?审批请求对应的是哪一版参数?恢复时模型、Prompt 和工具版本是否已经变化?

如果只把 Messages 重新交给模型,让它“根据历史继续”,模型可能重复调用工具,也可能跳过一个实际未完成的步骤。自然语言历史适合帮助模型理解上下文,不适合作为唯一事务记录。

一份可恢复快照至少需要这些信息:

  1. run_idthread_id,确认这是哪次任务运行。
  2. graph_versionstate_version,确认代码能否理解旧快照。
  3. current_nodenext_node,确认恢复入口。
  4. 结构化 State,包括目标、计划、结果和控制字段。
  5. 已提交动作清单,以及每个动作的幂等键和外部凭证。
  6. 待处理事件,例如审批、用户补充或重试时间。
  7. 快照创建者、时间、版本号和完整性校验信息。

注意“已提交”三个字。模型输出了 tool call,只能说明它想做;后端开始请求,也不能说明外部系统成功;只有执行结果被确认并与本地状态一致提交后,才可以把动作标记为完成。

Checkpoint 应该保存在哪些位置

最容易理解的方案是每个节点之后都保存,但真实系统还要看一致性和成本。保存点最好落在业务语义清楚的边界。

节点执行前

记录即将执行什么,便于崩溃后知道未完成动作。但如果执行后还没保存就崩溃,仍然无法判断外部副作用是否发生。

节点执行后

保存结果和下一节点,恢复时可以跳过已经完成的计算。问题是写操作与快照提交不可能天然原子,仍需幂等键或外部状态查询。

高风险动作前

这是人工审批的自然暂停点。快照应固定动作名、参数摘要、影响对象、发起原因和审批要求。审批人看到的内容必须与后续真正执行的内容一致。

长耗时阶段之间

例如计划完成、资料收集完成、报告草稿完成。阶段级 Checkpoint 能减少大量重复计算,也让人更容易理解恢复位置。

设计时不要追求“保存越多越安全”。过密保存会增加存储和序列化开销,过稀保存又会重复大量工作。正确做法是列出失败成本和副作用边界,为每个阶段选择安全点,再用故障注入验证。

从运行到暂停再恢复的完整协议

暂停和恢复是一套协议,不是把状态字段改成 paused。

一条可靠的恢复链路应该怎么走

第一步:定位唯一运行实例

客户端提交恢复请求时,必须带上稳定任务标识和期望版本。服务端不能只根据用户最后一次对话猜测要恢复哪个任务。一个用户可能同时运行多个 Agent,任务也可能有多个分支。

第二步:加恢复锁

用户重复点击、定时器重试和运维操作可能同时触发恢复。若两个执行器都拿到同一快照并开始运行,就会产生重复调用。恢复前需要租约、分布式锁或状态版本的比较交换,确保同一运行在同一时刻只有一个合法执行者。

第三步:检查兼容性

读取 graph_versionstate_version、Prompt 版本和工具版本。若新代码删除了旧节点或改变了字段含义,不能直接加载后继续。可以提供状态迁移,也可以明确拒绝并转人工。最危险的做法是静默用新逻辑解释旧状态。

第四步:核对外部副作用

对于已经发起但本地没有确认的动作,先用幂等键或业务查询核对外部状态。例如外部系统已创建记录,就补写本地结果;没有创建,才重新执行。不能看到本地 pending 就直接重放。

第五步:重新校验前置条件

暂停期间,权限、库存、文件版本、用户身份或业务规则都可能变化。恢复不是无条件续跑。高风险动作必须重新鉴权,时效性强的数据要重新读取,过期计划要重新评估。

第六步:从下一项未提交动作继续

恢复入口应由快照和业务状态共同决定。已完成节点不重复跑,未提交动作按当前条件执行。每次恢复都写一条事件,记录操作者、使用的快照版本和结果。

为什么幂等是恢复设计的地基

考虑一个典型窗口:Agent 调用外部服务创建记录,外部服务成功返回,但本地进程在保存结果前崩溃。恢复后,本地只看到动作未完成。如果再次调用,就可能创建两条记录。

Checkpoint 无法单独解决这个问题,因为它没有和外部系统共享一个原子事务。工程上常用三种办法。

第一种是幂等键。为一次业务动作生成稳定键,重试时仍使用同一个键,外部服务识别重复请求并返回第一次结果。

第二种是业务查询。外部服务不支持幂等键时,用可唯一定位的业务标识查询动作是否完成,再决定补写还是执行。但查询本身也要考虑延迟和最终一致性。

第三种是本地执行台账。记录准备执行、已发送、已确认、待核对等状态,恢复时按状态机处理,而不是只有成功和失败两个值。

对于不可逆动作,如果无法获得可靠幂等或核对机制,就不应该承诺自动恢复。更安全的方案是暂停并交给人工判断。系统设计的成熟不体现在“任何错误都能自动重试”,而在于知道哪些错误不该自动重试。

人工审批不是弹一个“确定吗”

一个合格的审批请求至少回答五个问题:谁发起、要执行什么、作用于什么对象、为什么需要执行、批准后有什么影响。

审批内容还应绑定动作摘要或哈希。假如审批人看到的是“发送一封通知”,批准后 Agent 又修改了收件人或正文,之前的批准就失效。任何关键参数变化,都应该重新生成审批请求。

审批结果可以设计成三类:批准当前动作;拒绝并结束或重规划;修改有限字段后重新校验。不要让审批人直接编辑任意 JSON,再绕过 Schema 和权限校验。

系统还要处理过期。等待期间外部状态变化,旧批准不一定仍然有效。审批请求应带有效期和状态版本,恢复时检查前置条件。过期后重新提交,而不是拿一张很久以前的批准继续执行。

最后是审计。至少记录审批人身份、权限来源、看到的动作摘要、决定、时间和恢复后的真实执行结果。人工介入不是安全责任的终点,仍然需要确认系统执行的内容与被批准内容相同。

Checkpoint 数据怎样分层存放

不要把所有内容都塞进一条数据库记录。可以按用途分成三层。

第一层是运行索引:任务状态、当前版本、下一节点、更新时间和锁信息。它需要快速读取,也负责并发控制。

第二层是状态快照:结构化 State、计划和节点结果。可以按版本追加,避免覆盖后无法审计。敏感字段要加密或只保存引用。

第三层是工件与 Trace:长文档、网页、模型原始响应、日志和大体积工具结果。它们放对象存储或专门日志系统,快照里只保留不可混淆的地址和摘要。

这种分层有两个好处。恢复只读取必要状态,不必把全部历史装进内存;审计时又能沿引用找到完整证据。保存策略还要有数据保留期限、用户删除和租户隔离,不能因为“Agent 需要记忆”就永久保留所有内容。

版本升级时怎样处理旧任务

长任务可能跨越一次发布。新版本增加节点、修改 State 字段或更换工具后,旧快照是否还能恢复,必须提前决定。

最稳妥的做法是让运行绑定图版本。旧任务继续由兼容运行器处理,新任务使用新图。若必须迁移,写显式迁移函数,把旧状态转换为新状态,并对关键字段做校验。迁移失败就转人工,不要用默认值掩盖缺失信息。

Prompt 和模型版本也应进入运行元数据。恢复后如果换了模型,行为可能变化。对于一般只读任务,可以接受新模型继续,但要在 Trace 中记录;对于高风险流程,最好固定执行环境或重新走审批。

恢复、重放和补偿不是一回事

面试里如果把三个概念分开,答案会更稳。

恢复是让同一次运行从一致状态继续,目标是不重复已经提交的工作。重放是为了调试或审计,使用历史输入重新走一遍流程,它通常应该在隔离环境中运行,不能触发真实副作用。补偿则是在动作已经发生、无法简单撤销时,用一个新的业务动作纠正影响,例如关闭误创建的草稿或撤回尚未发送的任务。

因此,Trace 回放默认只读,执行器应替换为桩或 Dry-run;恢复可以调用真实工具,但要遵守幂等和当前权限;补偿必须由业务定义,模型不能临时猜一个“相反操作”。没有可靠补偿的高风险动作,应把审批放在执行之前,而不是指望出错后恢复。

对外接口也要表达等待和恢复状态

长任务接口不能只有“处理中”和“完成”。至少要能区分运行中、等待用户信息、等待审批、暂时失败可恢复、终止和完成。客户端查询状态时,应看到需要做什么,而不是反复点击“继续”。

恢复接口要带任务版本或期望状态,服务端使用比较交换避免旧页面覆盖新决定。审批接口要保证一次决定只生效一次,重复请求返回同一结果。任务已经进入下一阶段后,旧的批准或拒绝不能再改变状态。

这些接口语义同样要进入验收:刷新页面后是否仍能找到待办;两个审批人同时操作时谁生效;用户先拒绝、旧页面又提交批准时系统是否阻止;任务完成后再调用恢复是否明确返回已完成,而不是创建第二个执行实例。

不同失败场景对应不同恢复策略

不是所有中断都从同一个位置继续,也不是所有动作都允许自动重放。

怎样验收这套设计,而不是停在架构图

由于这是一道设计题,最重要的是把验收条件说具体。没有真实运行证据时,只定义测试方法,不预填恢复率、延迟或成功率。

进程崩溃测试

在只读节点执行前、执行后、保存前后分别杀掉进程,检查恢复路径是否符合预期,已完成工作是否避免重复,Trace 是否连续。

副作用窗口测试

让外部写操作成功后、结果落库前模拟崩溃。恢复时应通过同一幂等键或业务核对拿到原结果,不能产生第二次副作用。

重复恢复测试

并发发送多个恢复请求,确认只有一个执行器获得运行权,其他请求得到明确状态,而不是各自开始执行。

审批一致性测试

审批请求创建后修改关键参数,系统必须让旧批准失效;无权限用户、过期批准、重复批准和批准后撤销都要有清楚结果。

版本兼容测试

用旧图生成快照,再用新版本尝试恢复。兼容时应经过迁移并保留审计;不兼容时应明确拒绝,不能运行到中途才因字段缺失失败。

外部状态变化测试

暂停后修改权限或业务对象状态,再恢复。系统必须重新校验,不能因为之前通过就继续执行。

数据安全测试

确认不同租户无法读取彼此快照,日志与快照不保存不必要的敏感正文,删除与保留策略可以真正执行。

Checkpoint 与人工审批验收清单

没有故障注入、并发和副作用测试,“支持断点续跑”仍然只是一个功能描述。

面试官会怎样连续追问

追问一:每一步都存 Checkpoint 不就行了吗

保存频率不能替代一致性。外部副作用与本地快照之间仍有窗口,而且过密保存会增加开销。应按阶段成本和副作用边界选择安全点,并用幂等和核对机制处理窗口。

追问二:模型工具调用已经写进 Messages,为什么还会重复

Messages 里的 tool call 只是模型请求,不代表后端是否执行成功,也不能证明结果已提交。需要独立执行台账和外部凭证,区分计划、发送、确认和提交。

追问三:恢复时从当前节点还是下一节点开始

不能只看节点名,要看节点提交状态。节点未开始可以从当前节点执行;节点计算完成并提交则从下一节点;外部写操作结果不确定时先核对,不能直接选择重跑或跳过。

追问四:人工批准后为什么还要重新校验

批准针对的是某版动作和当时的前置条件。等待期间权限、对象状态或参数可能改变,所以恢复时要校验版本、权限和外部状态,关键变化需要重新审批。

追问五:Checkpoint 会不会泄露用户数据

会有风险。只保存恢复需要的最小状态,大对象和敏感正文外置,使用租户隔离、访问控制、加密、脱敏日志和保留期限。删除用户数据时要覆盖快照、工件和备份策略。

追问六:你项目里真的做了吗

如果没有,就明确回答目前完成的是设计和验收方案,尚未获得真实恢复指标。可以展示状态 Schema、恢复时序、幂等策略和故障用例,不要把规划中的能力说成已经上线。

面试时怎样讲清安全恢复链路

我不会把 Checkpoint 理解成保存 Messages,而是保存一个一致的执行快照,包括任务和图版本、当前节点、结构化 State、已提交动作、待处理事件以及外部副作用凭证。运行时在阶段完成和高风险动作前设置安全点。恢复先用锁保证单执行者,再检查状态版本、权限和外部业务状态,最后从下一项未提交动作继续。写操作必须使用稳定幂等键或业务核对,因为外部操作成功、本地未落库时可能崩溃,单靠快照无法防重复。人工审批会绑定动作参数摘要、审批人和有效期,批准后仍重新校验,关键参数变化则重新审批。验收时我会注入进程崩溃、并发恢复、重复请求、过期审批、版本升级和外部状态变化。若项目目前没有完整实现,我会把这些作为设计与验收方案,不声称已有恢复率或线上指标。

恢复链路上桌前,核对这六项证据

  1. 快照是否包含执行位置、状态版本和已提交动作,而不只是聊天记录。
  2. 每个写操作是否有幂等键、业务核对或人工出口。
  3. 暂停事件是否写清等待对象、有效期和恢复条件。
  4. 审批内容是否与真正执行的参数绑定,变化后是否失效。
  5. 并发恢复、重复点击和旧版本快照是否有明确处理。
  6. 是否真的做过故障注入;没做过就只讲设计,不报虚构指标。

Checkpoint 最终要把长任务变成一个可以暂停、核对、继续和审计的执行系统,而不只是让 Agent 看起来能“记住进度”。没有幂等、版本和人工审批协议,所谓断点续跑很可能只是把同一个风险再执行一次。

INTERVIEW FOLLOW-UPS

面试官会怎样继续追问?

这些追问会继续检查方案取舍、验证方法和项目事实。
  1. Q01

    只保存 Messages 为什么不能可靠恢复?

  2. Q02

    外部写操作成功但本地未落库时怎样防止重复?

  3. Q03

    人工批准后为什么还要重新校验权限和业务状态?

  4. Q04

    图或 State 升级后,旧 Checkpoint 怎样恢复?

PROJECT CHECK

换成你的项目,这几件事能否说清楚?

  • 定义安全保存点、状态版本和下一执行位置
  • 为每个写操作准备幂等键或外部核对机制
  • 让审批绑定动作参数、身份、版本和有效期
  • 覆盖崩溃、重复恢复、并发审批和版本升级测试
用自己的项目经历练一次