Agent 状态与持久化执行
Agent 状态是任务执行到某一时刻的全部信息:消息历史、计划与进度、已执行的动作和结果。持久化执行把状态在关键节点保存下来,使进程崩溃、超时或等待人工审批之后,任务能从最近的检查点继续,而不是从头开始或重复已经产生副作用的动作。本文讲检查点、恢复、重试与幂等,以及人工介入的暂停和恢复。
1. 面试核心
先记住这几条,再读正文- 在每个步骤完成后把状态写入持久存储(检查点),恢复时加载最近的检查点继续执行;内存或无持久化的 Redis 中的状态,进程或节点故障后会丢失。卡 · 状态包含什么
- 恢复的难点是有副作用的动作:崩溃可能发生在“已执行、未记录”之间。写操作要带幂等键,恢复时先查询执行结果再决定是否重做。卡 · 恢复时的副作用
- 重试分层:瞬时错误由程序退避重试;需要改变决策的错误交给模型;多次失败进入兜底(降级、转人工、返回部分结果)。
- 人工介入是一种持久化的暂停:在需要审批的节点保存状态并挂起,审批结果到达后从该节点恢复,等待期间不占用进程。卡 · 人工介入
- 完整记录每步的输入、输出和状态,既用于恢复,也用于排错、审计和构建评测集。
2. 状态包含什么
| 内容 | 例子 | 用途 |
|---|---|---|
| 任务标识 | 任务 ID、用户 ID、会话 ID | 定位和隔离 |
| 消息历史 | 模型输入输出、工具调用与结果 | 恢复上下文 |
| 计划与进度 | 待办列表、当前步骤、已完成步骤 | 从中断处继续 |
| 动作记录 | 工具名、参数、幂等键、执行状态、结果 | 判断副作用是否已发生 |
| 状态机状态 | running、waiting_approval、failed、done | 控制流转 |
| 预算 | 已用步数、Token、时间 | 恢复后继续计算上限 |
用有限状态机描述任务生命周期,可以明确每个状态允许的转换,例如 waiting_approval 只能转到 running 或 cancelled,避免并发请求把任务推入不一致状态。
3. 检查点与恢复
步骤1 ──► 检查点1 ──► 步骤2 ──► 检查点2 ──► 步骤3(崩溃)
▲
恢复:加载检查点2,重新执行步骤3
- 何时写:每个节点或每轮循环结束时写;耗时步骤内部可以有中间检查点。
- 写到哪:关系数据库、带持久化的键值存储或对象存储。只在 Redis 内存中保存时,要开启持久化或使用复制,并评估故障时可能丢失的窗口。
- 恢复流程:加载最近的检查点 → 检查最后一个动作的执行状态 → 未完成的动作按幂等规则处理 → 继续循环。
- 框架支持:LangGraph 的 checkpointer 在每个超步后保存图状态,按
thread_id恢复;Temporal 等持久化工作流引擎记录事件历史,故障后通过重放恢复。
3.1 恢复时的副作用
如果崩溃发生在工具调用发出之后、结果写入检查点之前,恢复时无法从检查点判断动作是否已经执行。处理方式:
- 执行前记录意图:先写入“准备执行 X,幂等键 K”,再调用。
- 幂等键:写操作带唯一键,下游服务对重复请求返回第一次的结果。
- 先查询再执行:恢复时用幂等键或业务 ID 查询下游状态,已完成则直接采用结果。
- 补偿:无法幂等的多步操作,失败时执行反向操作(取消订单、退款),类似 Saga。
只读操作可以直接重做。
4. 失败处理
| 错误类型 | 例子 | 处理 |
|---|---|---|
| 瞬时错误 | 超时、429、连接断开 | 程序指数退避重试,有次数上限 |
| 参数或业务错误 | 参数缺失、订单不存在 | 作为工具结果返回模型,让它修正 |
| 权限错误 | 无权访问 | 返回模型,必要时请求用户授权 |
| 持续失败 | 同一错误重复出现、下游不可用 | 熔断,降级到备用工具或模型,或转人工 |
| 模型服务故障 | 模型 API 不可用 | 切换备用模型,或保存状态稍后重试 |
兜底结果要明确告诉用户哪些已完成、哪些未完成,而不是返回模型编造的成功。
5. 人工介入
人工介入(Human-in-the-loop,HITL)常见的位置:
- 执行高风险动作前:删除、转账、发送对外邮件、生产发布,展示动作和参数,由用户批准、修改或拒绝。
- 信息不足时:向用户澄清,而不是猜测。
- 多次失败后:交给人工处理,并附上已执行步骤和错误。
实现上,Agent 到达审批节点时保存状态,任务转为 waiting_approval 并通知审批人,进程释放资源。审批结果通过回调或消息到达后,加载状态,把审批结果(批准、修改后的参数、拒绝原因)写入状态,从该节点继续。审批要有超时策略,并记录审批人和时间。
6 · 面试题卡片
6.1 Agent 执行中断后如何恢复?检查点和快照怎么持久化?
出现公司:药明康德、新旦智能、阿里淘天、字节跳动、美团
考察重点
- 状态内容、检查点时机和持久化存储。
- 恢复流程与副作用判断。
参考回答
状态包括消息历史、计划与进度、动作记录(工具、参数、幂等键、执行状态)、状态机状态和已用预算。每个步骤完成后写检查点到数据库或可靠的持久存储;只放在 Redis 内存中时要开启持久化或复制,否则节点故障会丢失状态。LangGraph 的 checkpointer 在每步后保存图状态,按 thread_id 恢复。
恢复时加载最近检查点,检查最后一个动作的状态:只读动作直接重做;写动作执行前已记录意图和幂等键,恢复时先按幂等键查询下游结果,已完成就采用结果,未完成再执行。持久化的执行记录同时用于排错、审计和构建评测集。
6.2 工具调用失败时如何处理?重试时怎样保证不会重复执行?
出现公司:快手、百度、字节跳动、阿里淘天
考察重点
- 按错误类型分层处理。
- 幂等键、先查询后执行、熔断与兜底。
参考回答
先区分错误类型:超时、限流等瞬时错误由程序指数退避重试,有次数上限;参数错误、业务规则拒绝作为工具结果返回模型,让它修正;同一错误反复出现或下游不可用时熔断,降级到备用工具或模型,或转人工,并告知用户哪些步骤已完成。
防止重复执行:写操作在调用前记录意图并生成幂等键,下游对相同键返回首次结果;超时后不确定是否成功时,先按幂等键或业务 ID 查询状态再决定是否重试;无法幂等的多步操作准备补偿动作。任务状态用状态机管理,状态转换带版本号或条件更新,防止并发重复推进。
6.3 Human-in-the-loop 如何实现?人工介入后任务怎样继续?
出现公司:药明康德、凌脉、阿里淘宝闪购、小红书、百度
考察重点
- 人工介入的位置。
- 基于持久化状态的暂停与恢复。
参考回答
介入点放在高风险动作执行前(删除、支付、对外发送、发布)、信息不足需要澄清时、以及多次失败之后。到达介入点时保存检查点,任务转为等待审批状态并通知审批人,展示待执行的动作、参数和理由,进程随即释放资源。
审批结果通过回调或消息到达后,加载状态,把批准、修改后的参数或拒绝原因写入状态,从该节点继续:批准则执行,修改则用新参数执行,拒绝则作为观测交给模型调整方案。审批设置超时策略,记录审批人和时间用于审计。LangGraph 可以用 interrupt 配合 checkpointer 实现这一流程。