直接回答
AI Agent 状态持久化,是让被中断的工作流在不丢失已授权进度、也不重复危险副作用的前提下继续运行。它不只是保存消息,而是定义恢复契约、原子持久化状态转换、隔离非确定性调用、让外部副作用可幂等或可对账、安全迁移旧状态,并用崩溃测试证明恢复行为。
Checkpoint 只保存某个边界上的数据。它不会自动重启 Worker,不保证 Exactly-once,不验证被记住的事实,也不能证明业务动作正确。
状态持久化不等于长期记忆
执行状态和长期记忆跨越的是不同边界。
| 数据类别 | 范围 | 示例 | 权威来源 |
|---|---|---|---|
| Workflow State | 单次运行 | 当前节点、重试次数、待审批 | 工作流运行时 |
| Checkpoint | 可恢复快照 | 接受 Tool Result 后的状态 | 持久化层 |
| Effect Ledger | 外部动作状态 | 支付 API 已接受退款请求 | 应用协议 |
| Long-term Memory | 跨运行 | 已确认偏好或历史情景 | 受治理记忆服务 |
| Business Record | 领域事实 | 订单状态、账户余额 | System of Record |
| Artifact | 大型不可变输出 | 报告、图片、源码归档 | 对象/制品存储 |
| Audit Evidence | 取证证据 | Actor、策略版本、状态转换 | 追加式审计存储 |
不要从 Checkpoint 恢复一条过期订单状态后继续把它当作当前事实。快照可以保存订单 ID 和上次观察到的版本;恢复后必须重新向权威系统核验可变事实。
AI Agent 记忆指南解释什么信息可以成为长期记忆,Agent 记忆与删除权负责保留与删除;本文只讨论执行中断与安全续跑。
先定义恢复契约
只有团队明确“恢复成功”是什么,持久化设计才可测试。
| 契约字段 | 工程问题 |
|---|---|
| Run Identity | 哪个 Tenant、Workflow、Run 和 Release 拥有状态? |
| RPO | 最多允许丢失多少已接受进度? |
| RTO | 多久内必须重新进入可处理状态? |
| Checkpoint Boundary | 哪个转换前后提交状态? |
| Effect Semantics | Tool Call 能否重试、去重、补偿,还是只能对账? |
| Resume Authority | 哪个 Worker 或 Operator 有权恢复? |
| State Compatibility | 哪些代码和 Schema 版本能读取快照? |
| Retention | 何时清理 Checkpoint、History 与 Artifact? |
| Terminal States | 哪些结果必须停止自动恢复? |
“从中断点继续”仍然不够明确。合格契约必须说明:是在不确定副作用之前恢复,还是在已确认副作用之后继续,或进入需要观察和人工处理的对账状态。
把 Agent 建模为版本化状态机
应持久化显式状态与转换,不要序列化整个进程堆。
{
"tenant_id": "tenant_42",
"workflow_id": "refund-review",
"workflow_version": "3.2.0",
"run_id": "run_01J...",
"state_version": 17,
"status": "waiting_for_approval",
"next_transition": "execute_refund",
"input_refs": ["case:8472"],
"completed_steps": ["load_case", "policy_check", "draft_decision"],
"pending_effects": [],
"approval": {
"required_role": "refund_manager",
"request_id": "approval_91"
},
"budgets": {
"steps_remaining": 4,
"cost_remaining": 0.72
},
"checkpoint_schema": 2,
"created_at": "2026-08-09T10:20:00Z"
}
大型输出只存引用,不能在每个快照里重复 Blob。排除凭据和临时 Client Object。应保存解释或复现决定所需的 Policy、Prompt、Model、Tool 和代码 Release ID,但不能假设旧供应商或模型会永久可调用。
每个 Checkpoint 都存在崩溃窗口
外部副作用会形成结果不确定边界。
逐一考虑故障点:
- Intent 提交前崩溃:恢复时看不到已授权副作用,可以重新规划。
- Intent 提交后、Tool Call 前崩溃:恢复时使用同一 Key 执行。
- Tool 已执行、响应返回前崩溃:结果不明确,应按 Key 查询或进入对账。
- 已收到响应、状态提交前崩溃:重试必须返回同一结果或识别既有 Effect。
- 状态提交后崩溃:恢复后进入下一状态,不再重复 Effect。
因此,Checkpoint 无法独自保证 Exactly-once。Durable Execution 产品可以协调 Event History 与重试,但应用层副作用仍需明确协议。
让副作用可幂等或可对账
每个重要 Tool Call 都需要 Effect Protocol。
effect_key = tenant_id + workflow_id + run_id + logical_step
协议至少持久化:
- 稳定 Effect Key;
- 规范化 Request Hash;
- 目标系统与 Operation;
- planned、executing、confirmed、rejected、ambiguous、compensated 状态;
- Provider Receipt 或 Resource ID;
- Attempt Count 与 Last Error;
- 对账和补偿指令。
| 副作用 | 优先策略 |
|---|---|
| 创建支付或退款 | Provider Idempotency Key + Receipt 查询 |
| 发送邮件 | Outbox Row + 发送服务 Message ID |
| 更新自有数据库 | 状态与 Outbox 在同一事务提交 |
| 无去重能力的第三方 API | Read-after-write 对账或人工门禁 |
| 不可逆物理动作 | 前置条件、审批、窄命令、动作后验证 |
不要重试所有异常。认证失败、策略拒绝、无效请求、预算耗尽和不可逆副作用结果不明,通常都应进入不同状态,而非重发请求。
在 Snapshot、Event History 与混合模式之间选择
Snapshot 与 Event History 优化的是不同恢复成本。
| 模型 | 优势 | 成本与风险 |
|---|---|---|
| 最新 Snapshot | 简单、恢复快 | 历史有限;部分写入需要事务保护 |
| 版本化 Snapshot | 支持 Time Travel 与回滚 | 存储增长、Schema 迁移 |
| 追加式 Transition Log | 审计与确定性重建 | 回放成本、事件演进、副作用隔离 |
| Snapshot + Tail Log | 恢复快且保留证据 | 组件更多,需要一致性检查 |
Event Sourcing 不会天然更好。只有编排逻辑能相对于已记录事件确定性执行时,Replay 才成立。模型调用、时钟、随机数、网络响应和 Tool Effect 必须被记录,或隔离到受控 Activity;否则新一轮 Replay 可能走向不同分支。
Temporal 文档通过 Event History 与确定性 Replay 描述 Durable Workflow;LangGraph 把 Checkpoint 定义为线程级 Graph State Snapshot,把 Store 定义为跨线程应用数据。二者是不同契约,不是可以互换的产品标签。
按契约选择存储,而非照抄架构图
Redis + 关系数据库 + 向量数据库不是成熟度模型。
| 要求 | 候选能力 |
|---|---|
| 原子提交 Checkpoint 与 Effect Intent | 事务型关系或文档数据库 |
| 条件状态转换 | Compare-and-swap、Row Version 或事务锁 |
| 大型不可变 Artifact | 带 Checksum 的对象存储 |
| 低时延热读 | 只有数据库不满足 SLO 时才加 Cache |
| 语义候选召回 | Vector Index,可位于主数据库内 |
| 确定性 Event Replay | Durable Workflow / Event History Engine |
| 搜索与取证分析 | 从权威记录派生的 Audit/Event Index |
单一数据库可以是正确起点。当前数据库集成能够同时保存 JSON Checkpoint、Namespace 长期记录与 Vector Index。拆分存储会引入复制延迟、部分失败、权限重复、备份协调和删除传播;只有实测收益超过这些成本时才应加新服务。
WAL 是数据库持久化机制,不是 Agent 架构。PostgreSQL 用 Write-ahead Log 恢复已提交的数据库变化,但它不知道支付 API 是否接受请求,也不知道 Agent 应从哪个语义步骤继续。
控制并发与所有权
除非工作流显式支持并行分支,同一 Run 在任一时刻只能由一个 Owner 推进状态。
使用:
- 基于
state_version的乐观并发控制; - 带 Fencing Token 的 Worker Lease;
- 并行结果的 Branch ID 与确定性 Reducer;
- Effect Key 唯一约束;
- 按 Tenant 与 Run 限定的授权;
- 普通重试不能重新打开的单调终态。
UPDATE agent_runs
SET state = :next_state,
state_version = state_version + 1
WHERE tenant_id = :tenant_id
AND run_id = :run_id
AND state_version = :expected_version
AND status NOT IN ('completed', 'cancelled', 'failed');
更新零行意味着 Worker 已经输掉竞争,或 Run 已关闭。它必须重新读取,不能覆盖较新的状态。
多 Agent 系统也不应共享一个可变 Memory Object。每个分支拥有明确的输入、输出和所有权,通过 Reducer 或能识别冲突写入的 Coordinator 合并。
让旧状态跨 Release 迁移
长任务可能比创建它的代码版本存活更久,因此每个 Checkpoint 都必须保存 Workflow 与 Schema 版本。
发布契约应定义:
- 支持读取哪些旧 Schema;
- 如何通过纯函数、已测试的 Migration 升级;
- Transition 重命名或删除后的兼容规则;
- 引用的 Tool 或 Model 已下线时如何处理;
- 无法安全迁移时进入哪个 Quarantine 状态;
- 新版本写入的 Checkpoint 能否被旧版本回滚读取。
禁止从不可信 Checkpoint 反序列化任意类型。使用受限 Schema,校验字段和大小,必要时验证完整性,并把已存 Model/Tool 文本继续视为不可信数据。
可运行的恢复决策
下面的 Python 标准库代码不执行 Tool,只根据持久化证据决定唯一安全的恢复动作:
from dataclasses import dataclass
from enum import Enum
from typing import Optional
class EffectStatus(str, Enum):
NONE = "none"
PLANNED = "planned"
CONFIRMED = "confirmed"
AMBIGUOUS = "ambiguous"
class RecoveryAction(str, Enum):
EXECUTE = "execute"
ADVANCE = "advance"
RECONCILE = "reconcile"
STOP = "stop"
@dataclass(frozen=True)
class Checkpoint:
status: str
effect_status: EffectStatus
effect_key: Optional[str]
attempts: int
max_attempts: int
def recovery_action(checkpoint: Checkpoint) -> RecoveryAction:
if checkpoint.status in {"completed", "cancelled", "failed"}:
return RecoveryAction.STOP
if checkpoint.effect_status is EffectStatus.CONFIRMED:
return RecoveryAction.ADVANCE
if checkpoint.effect_status is EffectStatus.AMBIGUOUS:
return RecoveryAction.RECONCILE
if checkpoint.attempts >= checkpoint.max_attempts:
return RecoveryAction.STOP
if not checkpoint.effect_key:
return RecoveryAction.STOP
return RecoveryAction.EXECUTE
assert recovery_action(
Checkpoint("running", EffectStatus.PLANNED, "run-7:send", 0, 3)
) is RecoveryAction.EXECUTE
assert recovery_action(
Checkpoint("running", EffectStatus.AMBIGUOUS, "run-7:send", 1, 3)
) is RecoveryAction.RECONCILE
assert recovery_action(
Checkpoint("completed", EffectStatus.CONFIRMED, "run-7:send", 1, 3)
) is RecoveryAction.STOP
关键不是“自动继续”,而是明确拒绝:结果不明时必须对账,不能盲目重试。
把恢复作为产品属性测试
Happy Path 不能证明持久化可靠,应建立故障矩阵。
| 注入位置 | 必须满足的断言 |
|---|---|
| Model Call 前 | 不声称已有进度,Retry Budget 未损坏 |
| Model 响应后、Commit 前 | 可重新计算响应,不重复 Effect |
| Tool Request 前 | Intent 与 Key 可恢复 |
| Tool Effect 后、Receipt 前 | Run 进入 Reconciliation |
| Receipt 后、状态 Commit 前 | 去重后获得同一 Effect ID |
| Checkpoint Write 期间 | 上一个已提交版本仍可读取 |
| Schema Migration 期间 | 成功迁移或进入 Quarantine |
| 等待审批期间 | Worker 丢失后审批身份与状态仍存在 |
| 两个 Worker 同时恢复 | Fencing/Version 只允许一次转换 |
| Cancel 与 Retry 竞争 | Cancel 终态不能被重新打开 |
持续观测:
- 按故障点切分的恢复成功率;
- Recovery Time 与 Progress Loss;
- 重复或未追踪 Effect 数;
- 需要人工处理的 Ambiguous Effect;
- 过期或不兼容 Checkpoint 数;
- Checkpoint 写入时延与大小;
- Replay 长度与 Migration 失败;
- Retention 与 Deletion 完成率。
Agent 重启后即使生成了合理答案,只要重复退款或忽略取消,就属于恢复失败。
框架映射,而不是框架锁定
| 概念 | LangGraph 示例 | Durable Workflow 示例 |
|---|---|---|
| Run Identity | thread_id 与 Checkpoint ID |
Workflow ID 与 Run ID |
| State Persistence | Checkpointer | Event History + Workflow State |
| Cross-run Data | Store | 外部应用 Store |
| Resume | 从持久化 Thread State 调用 | Replay History 后继续 |
| Side Effect | Node/Tool 仍需应用协议 | Managed Activity 仍需业务幂等 |
框架文档会变化。Recovery Contract、State Schema、Effect Key 和 Failure Test 应由应用自己管理,使替换后端不会改变业务语义。
常见失败模式
- 只保存 Message Log:对话存在,Pending Effect 和审批状态丢失。
- Checkpoint-after-effect Gap:外部动作成功,崩溃后又执行一次。
- 整体对象序列化:Secret、Client 和不兼容运行时类型进入存储。
- Snapshot 充当业务事实:恢复的旧数据绕过 System of Record。
- 全局 Session Key:Tenant、用户或并行 Run 相互覆盖。
- Last-write-wins Recovery:旧 Worker 覆盖新 Checkpoint。
- History 无上限:没有 Retention 或 Compaction。
- Replay Drift:新代码以不同方式解释旧 Transition。
- Cache 充当权威存储:Cache Eviction 直接变成数据丢失。
- Vector Store 混淆:把语义检索误认为 Workflow Durability。
生产检查清单
- [ ] 每个 Run 包含 Tenant、Workflow、Release、Run 和 State Version。
- [ ] 终态、预算、审批和 Pending Effect 都是显式字段。
- [ ] Checkpoint 原子提交,并执行条件版本更新。
- [ ] 每个外部 Effect 都可幂等、可补偿或可对账。
- [ ] 恢复后重新核验可变业务事实。
- [ ] State Schema 具备兼容与 Quarantine 路径。
- [ ] 安全校验和反序列化持久化内容。
- [ ] Retention 覆盖 Checkpoint、Log、Artifact、Index 与 Backup。
- [ ] Crash Test 覆盖 Effect 与 Commit 边界两侧。
- [ ] Dashboard 暴露 Ambiguous Effect 与 Stuck Run。
相关资源
- AI Agent 记忆:生产架构、生命周期与评测
- AI Agent 记忆与删除权
- 企业 AI Agent:从试点到受治理生产
- Agent 可观测性:Trace、评测与成本
- Agent 记忆
- Agent Runtime
一手资料
- LangGraph Persistence 文档 — 当前 Thread Checkpoint、Cross-thread Store 与 Retention 边界。
- LangGraph Checkpoint 仓库 — Checkpoint、Pending Write、删除与序列化契约。
- Temporal Workflow Execution — Event History、确定性 Replay 与 Durable Workflow。
- PostgreSQL WAL Reliability — 数据库 Write-ahead Log 能保证什么、不能保证什么。
- AWS:使用 LangGraph 与 DynamoDB 构建 Durable Agent — 另一种 Checkpoint 后端与大 Payload Offload 模式;具体服务能力不构成通用要求。