Agent Runtime 与持久执行 ​

阅读路径:首次建立认知,建议依次阅读《Agent Runtime 与 Durable Execution 到底是什么》、《为什么需要 Durable Execution》、《运行时怎样推动任务向前执行》和《运行时的关键可靠性机制》;做架构选型和采购评审,重点阅读《主流运行时怎样设计》和《企业级运行时怎样设计》;处理线上故障,直接使用《运行时问题怎样治理》的证据与排查路径。

资料时点:文中产品事实核验至 2026-09-13,产品状态以当前官方文档为准;本文基于这些公开实现抽象出的企业架构结论,会明确使用“本文推导”表述。

本篇边界:Harness(执行外壳)推进 Agent 行为,并在模型之外强制执行门禁、验证和循环控制;安全或业务 Policy Owner(策略责任方)定义规则,Policy Service(策略服务)做出或签发授权决策,Harness 只负责消费并强制执行该决策。Runtime(运行时)负责 Run 跨时间、故障和等待的耐久状态与恢复;Execution(执行基础设施)负责真正重建 Browser、Shell、Sandbox 或 VM 并产生现实副作用。Runtime 能恢复任务进度,不能据此假定外部动作没有发生;恢复前必须根据操作账本和外部证据对账。

一、Agent Runtime 与 Durable Execution 到底是什么 ​

1.1 Agent Runtime 与 Durable Execution 分别负责什么 ​

核心结论 ​

Agent Loop(智能体循环)解决:

Agent 下一步做什么。

Harness(执行外壳)解决:

Agent 应该怎样工作,并在模型之外如何被门禁、控制和验证。

Runtime(运行时)解决:

这次 Run(运行实例)怎样可靠地活着。

当一个 Agent 任务只需要几秒钟,而且失败后可以直接重跑时:

text
进程内存保存状态
+
一个普通 while 循环

可能已经够用。

但一旦任务出现:

text
运行几分钟 / 几小时 / 几天
人工审批
异步 Tool
进程重启
Worker(执行进程)迁移
模型限流
外部事件等待
多个并发 Run
副作用不能重复
系统发布升级

问题就发生了质变。

这时需要:

Durable Execution(持久执行):让一个任务在进程崩溃、节点迁移、长时间等待、服务升级之后,仍然能够从正确状态继续运行,而且不重复产生错误副作用。

可以先用一张图建立全局认知:

Agent / Workflow 业务逻辑

Runtime

持久状态

Checkpoint(检查点)/ 事件记录

定时 / 等待 / 外部信号

operation_id / 账本引用

Execution Control Plane
或 Operation Service

队列 / 调度器

执行环境

进程崩溃 / 重启 / 发布 / 超时

恢复 / 重试 / 故障恢复

整篇的核心不是:

text
如何把 Python 对象存数据库

而是:

如何让“状态、控制流、副作用、等待和版本”在跨进程、跨时间、跨故障后仍然保持正确。

Runtime 术语很多,但它们都可以归到“状态、等待、副作用、Ownership(执行所有权)、版本”这几类系统责任。

正文会尽量遵循:

text
先看到真实问题
→ 再理解为什么简单方案失效
→ 最后才引出正式工程术语

例如先理解“Tool(工具调用)已成功但进程崩溃”的故障场景,再引出 Idempotency(幂等);先理解“两个 Worker 同时恢复同一任务”的故障场景,再引出 Lease(租约) 与 Fencing Token(栅栏令牌)。


Runtime 和相邻模块怎样划边界 ​

这一组概念最好一次横向看清。

概念 核心问题 主要职责 什么时候最需要 不主要负责什么
Harness(执行外壳) Agent 怎么干活? 上下文组装、能力暴露、循环控制、门禁执行、验证 需要控制 Agent 行为 业务权限规则的定义与最终授权决策
Policy Owner / Service(策略责任方 / 服务) 这个动作在当前身份和情境下是否允许? 定义规则,做出或签发授权决策 企业身份、数据、安全和业务规则 Agent 循环推进和长任务恢复
Runtime(运行时) Run 怎么可靠地活着? 状态、恢复点、等待、重试调度、并发所有权、恢复 长任务、等待、副作用、恢复 是否应该业务重试、具体 Prompt 和领域 Tool
Execution(执行环境) 动作在哪里发生? Shell、Browser、Sandbox、Container、VM 需要真实执行代码 / 浏览器 / 命令 Run 生命周期
Workflow Engine(工作流引擎) 多步骤流程怎么可靠执行? 流程状态、Timer、Retry、Signal、Durable Step 明确多步骤、等待和长事务 Agent 的推理智能本身

需要特别注意:

text
Runtime
≠
Workflow Engine

但二者经常重叠。

例如:

  • LangGraph 同时承担 Agent Graph Runtime 和 Checkpoint;
  • Temporal / Dapr / Restate 更偏通用 Durable Workflow Runtime;
  • OpenAI Agents SDK RunState 解决特定 Agent Run 的暂停 / 恢复;
  • Microsoft Agent Framework Workflow 同时提供 Agent Workflow、Checkpoint 和 HITL(Human-in-the-loop,人在回路)。

所以本文不会强行给所有产品贴唯一标签,而是分析:

它们分别承担了哪些 Runtime 语义。


Durable Execution 到底持久什么 ​

很多人第一次理解 Durable Execution,会认为:

“定期把 State 存数据库就可以了。”

不够。

一个长 Run 真正需要持久化的至少包括:

类别 典型内容 为什么必须持久
逻辑状态(Logical State) 当前计划、步骤、预算 恢复后知道做到哪
控制状态(Control State) 正在运行 / 等待 / 计划重试 决定下一步
待处理工作(Pending Work) 未完成 Tool、审批、消息 防止请求丢失
副作用引用(Side-effect Reference) 操作 ID、权威账本引用、外部资源 ID 恢复时能查询真实操作状态,防止盲目重试
版本状态(Version State) Agent、Tool、Workflow 版本 避免旧 Run 被新代码错误恢复
产物引用(Artifact Pointer) 文件、结果集、Sandbox 引用 恢复工作环境
时间状态(Timing State) Deadline、定时器、退避时间 支持等待、超时、重试
追踪 / 审计状态 事件、决策、证据 调试和审计

因此更准确的模型是:

text
Durable Runtime
=
可持久的状态
+
可恢复的控制流
+
可持久的等待
+
可追踪的副作用
+
能够感知版本的恢复

1.2 Run、会话与工作流实例怎样区分 ​

这些词在不同产品里经常混用。

本文采用一套工程约定:

概念 本文含义 例子
Run(运行实例) 一次具体任务执行 “修复这一个 Bug”
Session / Thread(会话 / 线程) 多轮交互容器 用户与 Agent 的持续会话
Workflow Instance(工作流实例) 一个工作流定义的某次执行 一次审批流程
Job(任务) 调度系统中的后台执行任务 一次数据处理任务
Turn(对话轮次) 一次用户输入到 Agent 返回或暂停之间的交互边界 用户要求修复 Bug 后的这一轮处理
Step / Task(步骤 / 子任务) Run 内可独立记录结果的逻辑执行单元 “运行测试”
Attempt(尝试) 同一 Step 因重试或 Worker 迁移而产生的一次物理执行 测试 Step 的第二次重试
Operation(外部操作) 对真实外部系统的一次动作 “创建工单”

为什么要区分?

例如:

text
Session
├─ Run 1:定位问题
├─ Run 2:用户补充信息后继续修复
└─ Run 3:最终发布验证

如果 Session 和 Run 混在一起:

  • Budget 难归属;
  • Checkpoint 难定义;
  • Trace 根节点不清晰;
  • Approval 难恢复。

这里还有一个不能省略的关系:

text
Run
└─ Turn 1..n
   └─ Step 1..n
      └─ Attempt 1..n
         └─ Operation 0..n

Runtime 持久化的是 Run 和 Step 的可恢复事实,而不是把某个 Attempt 的进程内存原样保存。同一 Step 可以有多个 Attempt,但它们必须共用同一个逻辑步骤身份,并通过操作账本确认外部动作是否已经发生。否则,“重试 Step”会被错误实现为“再创建一次业务资源”。


1.3 什么情况下才值得引入持久运行时 ​

不是所有 Agent 都应该上 Temporal / Dapr / LangGraph Checkpointer。

可以按复杂度判断:

场景 是否需要 Durable Runtime 推荐
3 秒问答,无 Tool 低 进程内执行即可
30 秒单 Tool Agent 低 简单 Run State
5 分钟 Coding Agent 中 数据库 Checkpoint 可选
30 分钟 Research Agent 中高 持久 Run State
人工审批可能等 2 天 高 持久等待 + Resume
跨多个系统有副作用 高 操作账本 + 幂等 / 补偿
数千并发长 Run 高 调度 + 租约 + 背压
一失败可以从头重跑 低 不要过度工程

表中的秒数、分钟、等待天数和并发量只是用于对比失败成本的示意场景,不是可直接套用的通用阈值。真正的硬触发条件是外部写入无法安全重做、审批或信号必须跨进程存活、合规要求可审计恢复等风险语义;任务时长和并发量是辅助评估成本的连续变量。

可以粗略记成:

text
Runtime 复杂度
≈
任务持续时间
×
副作用风险
×
恢复价值
×
并发规模

可以进一步分成四档:

层级 Runtime 形态 适用
L0 进程内状态 秒级、失败可重跑
L1 数据库持久化 Run State 分钟级、中等任务
L2 Checkpoint + 持久等待 + 操作账本 长任务、审批、副作用
L3 Durable Workflow Runtime 大规模、长事务、强恢复 / 审计

这四档不是成熟度排名,而是:

Runtime 复杂度应匹配 Failure Cost。


1.4 为什么运行时会回到分布式系统问题 ​

Agent Runtime 看起来是一个 AI 新问题,但只要任务跨出一次请求 / 一个进程的生命周期,它就会重新进入经典分布式系统世界。

演进链可以理解为:

text
Single Request
→ 进程内内存足够

Long-running Run
→ State 必须脱离进程生命周期

External Wait / HITL
→ Wait / Signal 必须持久化

External Side Effect
→ 需要 Idempotency / Operation Ledger / Reconciliation

Multiple Workers
→ 需要 Lease / Fencing / Ownership

Large Scale
→ 需要 Queue / Backpressure / Fair Scheduling / Capacity

Long-lived Versions
→ 需要 Version Pin / Migration / Replay

Cross-system Workflow
→ 需要 Saga / Compensation / Failure Domain

因此:

Agent Runtime 的新鲜之处在于“控制者是非确定性的 Agent”;但它面对的持久化、并发、恢复、副作用、版本和灾备问题,本质上仍然是分布式系统问题。

这带来一个非常重要的架构判断:

text
不要让 Agent 自己重新发明分布式可靠性

模型可以决定“下一步做什么”,但:

text
状态是否丢失
副作用是否重复
谁拥有执行权
等待是否持久
恢复是否一致
版本是否兼容

这些必须由确定性的 Runtime / Software Infrastructure 保证。


Agent Runtime 和传统 Workflow Runtime 有什么不同 ​

不能因为很多机制来自 Temporal / Restate / DBOS,就认为 Agent Runtime 与传统 Workflow Runtime 完全一样。

传统 Durable Workflow 通常更强调:

text
已知 Control Flow
+ Deterministic Replay
+ Durable Activity

Agent Runtime 还额外面对:

text
Model Decision 非确定
Context 每轮变化
Tool Set 可动态变化
Session / History 会影响后续决策
Agent 可能 Re-plan / Handoff / Spawn Subagent
Verification 结果可能把任务打回继续

所以 Agent Runtime 的额外难点是:

恢复的不只是“程序执行位置”,而是“一个还能继续正确决策的语义世界”。

这也是本文强调 Semantic Recovery(语义恢复)的原因。


二、为什么需要 Durable Execution ​

2.1 为什么请求生命周期承载不了长任务 ​

一次网络请求为什么不够 ​

传统 Web 服务常假设:

text
请求到达
→ 完成计算
→ 返回响应

几十毫秒到几十秒结束。

但 Agent Task 可能:

text
用户任务
→ 模型决策
→ 调用 Tool
→ 等待
→ 人工审批
→ 恢复
→ 再调用 Tool
→ 子 Agent
→ 再次等待
→ 最终验证

持续:

text
几分钟
几小时
甚至几天

如果 Run 生命周期绑定一个进程 / HTTP Request:

text
进程崩溃
=
任务状态一起丢失

这是最基本的 Runtime 问题。


为什么失败后重新跑一遍不够 ​

对于纯计算:

text
算失败了
→ 再算一次

通常问题不大。

但 Agent 和普通计算最大的区别之一是:

Agent 会真的改变外部世界。

例如它可能:

  • 发一封邮件;
  • 创建一张工单;
  • 发起一笔支付;
  • 合并一个代码变更;
  • 执行一次部署。

真正危险的是下面这种情况:

text
Agent 请求“创建工单”
        ↓
工单系统已经创建成功
        ↓
Runtime 所在进程突然崩溃
        ↓
“创建成功”还没来得及写进 Runtime State

这中间形成了一个非常关键的 Crash Window(崩溃窗口):

工单系统Runtime工单系统Runtime进程此时崩溃成功结果尚未持久化创建工单创建成功

两分钟后任务恢复,Runtime 面临一个现实问题:

刚才那张工单到底创建成功没有?

如果直接重跑:

text
再次创建
→ 可能得到两张工单

如果直接跳过:

text
直接认为成功
→ 万一第一次其实失败了呢?

所以 Durable Runtime 必须解决的核心,不是简单的:

“失败以后要不要 Retry(重试)?”

而是:

我如何知道外部动作到底有没有真实发生?

《运行时的关键可靠性机制》会深入推导三个生产机制:

text
Operation Ledger(操作账本)
+
Idempotency(幂等)
+
Reconciliation(对账)

这一节的根问题是:

只要 Agent 会改变真实世界,恢复就不能等同于简单重跑。


2.2 等待和系统升级为什么会改变恢复语义 ​

外部等待为什么是一等状态 ​

真实 Agent 会等待:

text
等待人工审批
等待 Webhook 回调
等待异步任务完成
等待用户上传文件
等待支付回调
等待浏览器事件
等待 Tool 完成
等待限流窗口结束

等待期间:

text
CPU = 0

但 Run 仍然“活着”。

因此必须存在:

text
WAITING_APPROVAL
WAITING_EXTERNAL
WAITING_TIMER
WAITING_TOOL

而不是只有:

text
RUNNING / SUCCESS / FAILED

真实框架也是这样处理的。

OpenAI Agents SDK 的 RunState 可以把等待审批所需的运行状态序列化保存,等审批完成后再恢复 Run。[^openai-runstate]

Microsoft Agent Framework 的 Checkpoint 也会把“正在等待的外部请求”一起保存;恢复后,这个等待请求会重新进入工作流。[^ms-checkpoint][^ms-hitl]

这说明:

“正在等待”不是页面 UI 状态,而是 Runtime 必须持久保存的真实运行状态。


系统发布为什么会变成 Runtime 问题 ​

一个 Run:

text
周一 10:00
→ 进入审批等待

周三 15:00
→ 用户批准

这两天之间:

text
Agent Prompt 更新了
Tool 参数结构变了
Skill 更新了
Workflow 代码发布了新版本
SDK 也升级了

恢复时到底用哪个版本?

这不是边缘问题,而是所有 Long-running Run 最终都会遇到的问题。

OpenAI Agents SDK 当前官方也明确建议:如果 Pending Task 可能等待很久,应把 Agent Definition / SDK 的 Version Marker(版本标记)和序列化状态一起保存,以避免模型、Prompt、Tool 定义变化造成恢复不兼容。[^openai-runstate]


2.3 规模为什么会把 Runtime 变成调度系统 ​

10 个 Run:

text
一张数据库表
+
一个 Worker

可能够。

10 万个 Waiting Run:

text
10 万个状态对象
10 万个定时等待
大量审批通知
过期清理
索引
版本兼容
集中恢复

CPU 可能几乎为零,但:

text
状态存储
定时器索引
通知系统
恢复队列

都会成为成本。

因此:

Durable Runtime 的规模不等于 CPU 规模。

等待中的 Run 规模可能远大于真正正在执行的 Run。


第一性问题最终是什么 ​

最终可以压缩成五个问题:

text
1. 状态(State)
   → 我现在在哪里?

2. 控制流(Control Flow)
   → 下一步该执行什么?

3. 副作用(Side Effect)
   → 哪些外部动作已经真实发生?

4. 等待与外部信号(Wait / Signal)
   → 我在等谁?什么时候继续?

5. 版本(Version)
   → 恢复时应该使用哪一版逻辑?

只要一个 Runtime 能可靠回答这五个问题,它才真正接近 Durable Runtime。


三、运行时怎样推动任务向前执行 ​

这里的“运行时”不是模型推理层,而是负责 Run 状态、等待、恢复、Ownership、版本和调度的持久生命周期系统。

这一章用一个贯穿案例理解 Runtime:

Coding Agent 修改支付代码,测试通过以后,需要等待 Senior Engineer 审批两小时,再继续 Merge PR。

整个过程:

text
开始执行
→ 修改代码
→ 跑测试
→ 保存状态
→ 等待审批
→ Worker 释放
→ 两小时后收到批准
→ 重新恢复
→ Merge PR
→ 验证成功

后面出现的 Queue、Claim、Checkpoint、Wait、Signal、Resume,都映射回这个案例。

3.1 Run、状态和恢复点怎样形成主链路 ​

一个 Run 怎样被 Runtime 推着往前走 ​

Claim / Load / Persist 只是实现动作,真正重要的是它们分别解决 Ownership、State Loading 和 Durable Commit。

把它们放进刚才的 Coding Agent:

text
1. 用户发起任务
   → Runtime 创建 Run R123

2. Run 进入队列
   → 等待 Worker

3. Worker A 获得 R123 的执行权
   → Claim(领取)

4. Worker A 读取之前保存的状态
   → Load(加载)

5. Agent 修改代码并执行测试
   → Execute(执行)

6. 测试结果和当前进度被保存
   → Persist(持久化)

7. 任务需要人工审批
   → Runtime 把状态变成 WAITING_APPROVAL

8. Worker A 被释放
   → 不需要陪 Run 等两小时

9. 两小时后审批系统返回“通过”
   → Signal(外部信号)到达

10. Run 重新进入队列
    → 新 Worker B 可以继续执行

11. Worker B 读取 Checkpoint
    → Resume(恢复)

12. 执行 Merge PR 并验证
    → SUCCEEDED

再把它抽象成 Runtime 主链路:

继续

等待

重试

成功

失败

取消

Run Created

Queued
等待执行

Claim
Worker 获得执行权

Load
读取状态 / Checkpoint

Execute
执行本轮工作

Persist
保存结果和状态

下一步是什么?

Durable Wait
持久等待

Signal / Timer / Approval
外部事件到达

Retry Scheduled
计划重试

SUCCEEDED

FAILED

CANCELLED

因此一次 Runtime Iteration(运行迭代)可以理解成:

拿到执行权 → 读取真实状态 → 执行一小段工作 → 保存结果 → 决定继续、等待、重试还是结束。

Run 状态机 ​

生产 Run 不应该只有:

text
running
success
failed

推荐至少区分:

CREATED

QUEUED

RUNNING

WAITING_TOOL

WAITING_APPROVAL

WAITING_EXTERNAL

RETRY_SCHEDULED

CANCELLING

CANCELLED

SUCCEEDED

FAILED

TIMED_OUT

不同产品状态名可以不同,但必须能够表达:

  • 正在运行;
  • 正在等什么;
  • 是否计划重试;
  • 是否正在取消;
  • 是否已经终态。

State / Checkpoint / History / Operation 有什么区别 ​

对象 是什么 主要用途
Run State 当前真实状态 当前执行
Checkpoint 某一时刻的状态快照 Resume
Event 状态发生过什么变化 Audit / Replay / Debug
Operation Reference Runtime 保存的 operation_id 与权威账本引用 等待 / 调度 / 恢复查询
Operation Ledger Execution Control Plane 或 Operation Service 持有的外部副作用权威账本 Idempotency / Reconciliation / Audit

例如:

text
Event:
TOOL_SUCCEEDED(operation_id=123)

Checkpoint:
current_step = VERIFY
latest_tool_result = ref://123

Run State:
status = RUNNING

Operation:
operation_id = 123
external_ticket_id = T-999
status = SUCCEEDED

不能把四者混成一个 JSON。


3.2 Checkpoint 与 History 怎样设计 ​

Checkpoint 应该保存什么 ​

Checkpoint 不是:

text
pickle(agent)

至少要考虑:

text
Logical State
Workflow Cursor / Next Step
Pending Messages
Pending Requests
Pending Tool / Operation
Approval State
Artifact References
Budget / Deadline
Retry Metadata
Version Manifest
Execution Environment Requirement

Microsoft Agent Framework 当前 Checkpoint 会保存 Executor State、下一 Superstep 的 Pending Messages、Pending Requests / Responses、Shared State。[^ms-checkpoint]

LangGraph 当前在每个 Superstep Boundary(超级步边界)保存 StateSnapshot,并在并行 Node 中记录 Pending Writes,使某个 Node 失败时已成功 Node 不必重新执行。[^langgraph-persistence]


Checkpoint 多久保存一次 ​

不是越频繁越好。

频率高:

text
Recovery Loss 小
但
Storage / QPS(Queries Per Second,每秒请求数)/ Latency 高

频率低:

text
成本低
但
Crash 后重做更多

可以把 Trade-off 表达成:

text
Checkpoint Cost
vs
Recovery Rework Cost

对于:

text
Model Call
Tool Side Effect
Human Approval

这些高价值边界通常值得持久化。

对于:

text
纯内存格式转换

不一定需要。


为什么有些 Runtime 还要保存 History(历史)

Snapshot-first(快照优先) ​

只保存当前状态:

text
run_state = {...}

优点:

  • 实现简单;
  • Resume 快。

缺点:

  • 难知道为什么变成当前状态;
  • Time Travel / Audit 弱。

Event + Snapshot(事件日志与快照) ​

记录事件:

text
RUN_CREATED
STEP_STARTED
MODEL_COMPLETED
TOOL_REQUESTED
TOOL_SUCCEEDED
APPROVAL_REQUESTED
APPROVAL_GRANTED
CHECKPOINT_CREATED

再定期 Snapshot。

优点:

  • Audit;
  • Replay;
  • Time Travel;
  • Debug;
  • 指标计算。

缺点:

  • 存储、版本和重放更复杂。

LangGraph 的 Persistence / Time Travel 就是很有代表性的 Event + Checkpoint 思路:可以查看历史 StateSnapshot、Replay 旧 Checkpoint、Fork 出新分支。[^langgraph-persistence][^langgraph-time-travel]


3.3 等待、恢复和核心对象怎样建模 ​

如何等待却不占 Worker ​

Runtime 必须把:

text
sleep 1 hour

和:

text
Thread.sleep(1h)

区分开。

真正 Durable Timer:

text
Persist wake_at
→ Worker 释放
→ Timer Service 等待
→ 到期后重新 Queue

同样:

text
Wait for Approval

应该:

text
Persist Pending Request
→ Release Worker
→ Human Response
→ Signal Run
→ Resume

而不是让 HTTP Connection / Worker 一直挂着。


一张图理解“暂停 → 等待 → 恢复” ​

Worker BHumanRuntimeWorker AWorker BHumanRuntimeWorker AWorker A 被释放两小时过去从持久状态继续执行保存 Checkpointstatus = WAITING_APPROVAL发出审批请求APPROVEDSignal 持久化Queue / Claim RunLoad Checkpoint

最重要的认知:

等待两小时的是 Run,不是 Worker。

Worker 可以在等待期间完全不存在。


暂停后从哪里恢复 ​

一个真正可恢复的 Interrupt,需要:

text
Where to resume
What data to wait for
What state is already committed
What side effects already happened
What code version should resume

LangGraph 当前 interrupt() 会持久化图状态,并可无限期等待;恢复时 Node 会从头重新执行,所以 Interrupt 之前的副作用必须设计成 Idempotent(幂等)。[^langgraph-interrupt]

这是一个非常重要的坑:

Resume 并不一定等于从某一行代码继续。

很多 Runtime 实际是:

text
重新进入 Step / Node
+
利用 durable state 跳过已完成部分

Runtime 最核心的数据对象 ​

参考设计:

typescript
interface Run {
  runId: string;
  sessionId?: string;

  agentId: string;
  agentVersion: string;

  status: RunStatus;

  currentStep?: string;

  createdAt: string;
  startedAt?: string;
  deadline?: string;

  budget: RunBudget;

  checkpointId?: string;
  stateVersion: number;

  runtimeVersion: string;
  versionManifest: VersionManifest;

  outcome?: RunOutcome;
}

interface Checkpoint {
  checkpointId: string;
  runId: string;

  stateVersion: number;
  stateRef: string;

  pendingRequests: PendingRequest[];
  pendingOperations: PendingOperation[];

  artifactRefs: string[];
  environmentManifest?: string;

  createdAt: string;
}

interface Operation {
  operationId: string;
  runId: string;

  capability: string;
  idempotencyKey?: string;

  status:
    | "PLANNED"
    | "STARTED"
    | "SUCCEEDED"
    | "FAILED"
    | "UNKNOWN";

  externalResourceId?: string;
  resultRef?: string;
}

字段名不是标准。

重要的是三个一等对象:

text
Run
Checkpoint
Operation

3.4 外部副作用和恢复语义怎样保持一致 ​

外部动作和 Runtime 状态怎样提交 ​

Durable Runtime 最容易出错的地方,不是“有没有 Checkpoint”,而是:

Step 的业务结果、外部副作用和 Runtime State 到底以什么顺序提交?

最基本的 Crash Window:

text
execute side effect
→ crash
→ persist result

如果 Crash 发生在中间,恢复时无法判断外部动作是否已经成功。

所以一个 Step 通常需要显式 Commit Protocol:

text
1. Reserve Intent / Operation ID
2. Persist PLANNED / STARTED
3. Execute
4. Persist Result / External Resource ID
5. Advance Run State
6. Create / Advance Checkpoint
External SystemState StoreRuntimeExternal SystemState StoreRuntimepersist operation PLANNEDexecute(operation_id)result / resource_idpersist operation SUCCEEDEDadvance run state / checkpoint

关键原则:

外部副作用的 Durable Record 不能晚于“Run 已经继续往后走”的事实。


同一数据库内可以做到更强原子性 ​

如果:

text
Business Data
+
Workflow State

都在同一个数据库事务里,就可以把:

text
业务写入
+
Durable Step Record

一起提交。

DBOS 的 Transaction Step 就是代表:业务 Postgres 写入和 Durable Workflow Record 可以在同一事务里提交,因此数据库边界内能获得更强的 Exactly-once 语义。[^dbos-outbox]


跨外部系统时只能缩小 Crash Window,不能幻想消失 ​

例如:

text
Runtime DB
+
GitHub API

不可能用一个普通数据库事务原子提交两边。

只能通过跨 Owner 协作缩小不确定窗口:

text
Execution / Operation Service 权威账本
+
Idempotency Key
+
Reconciliation

Restate 则通过 Journal Commit 定义 Durable Step 的完成:Step Result 先写入并复制提交到 Journal,之后重试时从 Journal 读取历史结果并跳过已完成动作。[^restate-architecture]

不同实现路径不同,但共同目标是:

让“这一步是否已经发生”拥有唯一、可恢复的 Durable Truth(持久事实)。


生产级 Runtime 最重要的系统性质 ​

Runtime 的目标不是“有状态”这么简单。

可以按“运行时系统性质优先级”分成 P0 / P1 / P2 三层。这不是投资阶段或成熟度等级,而是在冲突时应先保证哪一类系统性质。

P0:先保证状态正确、不会重复执行 ​

性质 核心问题 失败后果
State Consistency State 与真实执行是否一致? 错误恢复
Single Ownership 同一 Run 是否只有一个合法执行者? 双执行
Side-effect Safety 外部动作是否重复? 重复付款 / 工单
Signal Consistency 外部 Signal 是否丢失 / 重复? 错误 Resume

P0 先保证:

恢复以后不能把世界搞错。


P1:再保证任务不会丢、能够继续推进 ​

性质 核心问题
Durability Crash 后状态是否还在?
Recoverability 是否能从正确位置继续?
Liveness Run 是否最终能继续推进?
Wait Durability Timer / Approval / Signal 是否能跨进程存活?

P1 关注:

任务不能因为基础设施故障永久消失或永远卡住。


P2:最后优化恢复速度、成本和运维效率 ​

性质 核心问题
Resume Latency 多久能恢复?
Checkpoint Efficiency Checkpoint 成本是否合理?
Capacity Efficiency Waiting Run 是否低成本?
Economics 每个成功 Run 成本是否可接受?
Operability 是否可 Debug / Replay / Migrate / Rollback?

最终优先级:

text
P0
先保证不重复、不丢、不乱

↓
P1
再保证能恢复、能继续

↓
P2
最后优化延迟、成本、运维

这和普通 Web 服务的差异很大:

对 Durable Runtime 来说,“恢复正确性”比“恢复得快”优先级更高。


恢复时应该 Retry、Reuse 还是 Reconcile ​

这是 Runtime 最重要的恢复判断之一:

No

Yes

No

Yes

SUCCEEDED

FAILED

Yes

No

STARTED / UNKNOWN

确认已成功

确认未发生

仍无法确认

Run 恢复

Operation 有 Durable Record?

动作是否无副作用 / 可安全重做?

Retry

人工或业务对账

Operation 状态

Reuse Result
不要重复执行

错误可重试?

Re-plan / Fail

Reconcile
查询外部真实状态

这张图把后面很多术语压缩成一个判断:

text
已确认成功
→ 复用

已确认失败且可重试
→ 重试

状态未知
→ 先对账

不可安全判断
→ 人工 / 业务兜底

四、运行时的关键可靠性机制 ​

这一章开始进入真正的生产机制。

但需要先明确:

不是每一种机制都值得同样深入。

副作用正确性会讲到故障、数据模型和恢复路径;持久推进和版本恢复讲清适用条件与实现;规模治理和灾备机制则由实际并发、故障域与合规风险触发,不抢基础正确性的主线。

这些机制同样有优先级,不应该同时“全上”。

语义分组 机制 解决什么
副作用正确性 Operation Ledger(操作账本)、Idempotency(幂等)、Reconciliation(对账)、Saga(长事务) 弄清外部动作是否发生,避免重复副作用,处理跨系统局部失败
状态耐久性 Checkpoint(检查点)、Durable State(持久状态)、History 让 Run 跨进程和节点故障仍可恢复
控制流推进 Wait / Signal / Retry / Cancel(等待、信号、重试与取消) 让任务能暂停、唤醒、继续或终止
版本与所有权 Version / Replay(版本 / 重放)、Single Ownership(单一执行权)、Lease / Fencing 使旧 Run 能安全恢复,拒绝过期 Worker 写入
规模治理 Backpressure / Fairness / Retention(背压、公平调度与保留) 并发和等待规模扩大后仍可运营
高风险故障域 DR(Disaster Recovery,灾难恢复)、Multi-region(多地域) 在 RPO / RTO、合规或地域故障成本明确触发时,扩大耐久保证边界

原则:

先保证恢复正确性,再增加复杂调度与平台能力。

4.1 如何保证“恢复以后不会重复做事” ​

Exactly-once(恰好一次)为什么通常是危险幻觉 ​

真实分布式系统中:

text
Request Sent
→ Remote System Executes
→ Response Lost

调用方只看到:

text
timeout

它无法确定:

text
执行失败
or
执行成功但响应丢失

所以:

“我只调用一次”不等于“副作用只发生一次”。

真正工程目标通常是:

text
At-least-once Delivery
+
Idempotent Effect
+
Durable Operation Record

Restate 当前文档会用 “exactly-once semantics” 描述它的可靠通信能力,但即使底层 Runtime 提供强语义,连接外部非事务系统时仍然需要考虑外部系统本身的 Idempotency / Side Effect Contract。[^restate]


“消息只处理一次”和“业务动作只发生一次”不是一回事 ​

工程讨论里最容易混淆的是:

text
Message Delivery
vs
Business Effect

例如消息系统说:

text
exactly-once delivery

并不自动等于:

text
业务副作用 exactly-once

可以用这张表理解:

层 能保证什么 仍然需要什么
Queue Delivery 消息不丢 / 去重 Handler 幂等
Workflow Step 某 Step 的 Durable Result 外部 Side Effect 对账
DB Transaction 数据库内原子提交 外部 API 仍需幂等
External API 取决于对方契约 Idempotency Key / Reconcile

DBOS 是一个很好的边界案例:在 Transaction Step 中,业务数据库写入与 Workflow Checkpoint 可以在同一个 Postgres 事务里原子提交,因此数据库内部 Step 可以真正做到 Exactly-once;但对外部消息 / API,官方仍明确指出它们可能是 At-least-once,因此仍应该 Idempotent。[^dbos-outbox]

所以最稳妥的思维方式是:

先问“哪个边界内 Exactly-once”,再问“跨出这个边界以后怎么保证业务效果”。

可以把 Guarantee Boundary(保证边界)压缩成:

保证边界 可以依赖的强语义 跨出边界后怎么办
同一数据库事务 Atomic / Exactly-once DB Effect 不自动覆盖外部 API
Runtime Journal / Workflow History 已完成 Step 可 Replay / Reuse 外部系统仍需业务幂等
Queue / Message Delivery 去重 / 投递语义 Handler 仍需幂等
外部 SaaS / API 取决于对方 Contract Idempotency Key + Reconciliation

所以以后看到:

text
Exactly-once
Atomic
Transactional
Durable

都不能只问“支不支持”,还必须问:

这个保证到底在哪个边界内成立?


Operation Ledger(操作账本) ​

一个外部副作用应拥有独立的 Operation 记录和状态机。Operation 的业务语义、幂等契约、状态推进和对账方法由 Execution / Capability(执行 / 能力)定义;Execution Control Plane(执行控制面)或独立 Operation Service(操作服务)是权威账本。Runtime 只持久保存 operation_id、等待 / 调度状态和一致引用,并在恢复时查询权威账本。即使两类数据物理上位于同一数据库,逻辑 Owner 也不会改变。

权威账本中的状态机可以是:

text
PLANNED
→ STARTED
→ SUCCEEDED
   or FAILED
   or UNKNOWN

其中最关键的是 UNKNOWN(状态未知)。

它表示:

Runtime 已经发出了请求,但无法确认外部世界到底发生了什么。

例如:

text
operation_id = OP123
action = 创建工单
status = UNKNOWN

这时绝不能直接把它当 FAILED。

推荐至少记录:

字段 作用
operation_id 这次外部动作的唯一身份
run_id 属于哪个 Run
action / capability 做了什么
request_hash 请求内容是否相同
idempotency_key 外部系统去重键
status PLANNED / STARTED / SUCCEEDED / FAILED / UNKNOWN
external_resource_id 外部真实资源 ID
result_ref 成功结果引用
attempt 第几次尝试
started_at / finished_at 时间证据

这样恢复时不是“猜”,而是 Runtime 根据权威账本的读取结果决定复用、等待还是触发对账。

推荐协作顺序:

text
Harness 生成 Action Proposal
→ Execution / Operation Service 保留 operation_id 并写入 PLANNED
→ Runtime 保存 operation_id 引用与等待状态
→ Execution 执行 Tool 并推进权威账本
→ Runtime 收到结果引用
→ Harness 组装 Observation 并推进 Run

如果 Crash:

text
Operation = SUCCEEDED
Run Checkpoint = old

恢复时,Runtime 通过 operation_id 读取 Execution Control Plane 或 Operation Service 的权威状态:

不再执行 Tool,而是读取 Ledger 中已成功 Result。

如果:

text
Operation = STARTED

但结果未知:

进入 Reconciliation(对账)流程,而不是直接 Retry。


Idempotency(幂等)怎么真正设计 ​

Tool Contract 最好声明:

text
side_effect
idempotency_mode
idempotency_key
reconcile_method
compensation

例如:

Tool 是否幂等 恢复策略
read_file 是 直接重试
query_sql SELECT 是 直接重试
create_ticket 取决于 key 用 idempotency key
send_email 通常否 查询 / 记录 Message ID
charge_payment 必须业务幂等 Payment Idempotency Key
merge_pr 需检查状态 Read-before-write

Retry(重试)必须分类 ​

Failure 类型 例子 策略
Transient(瞬时) 429、短暂网络失败 Backoff + Jitter
Deterministic(确定性) SQL 语法错误 返回 Agent Re-plan
Permission 权限不足 Ask / Escalate
Side-effect Unknown Timeout 后状态未知 Reconcile,不直接重放
Model Format JSON 不合法 Limited Retry / Constrained Output
Dependency Outage 外部系统宕机 Circuit Breaker / Durable Timer

重试策略至少包含:

text
max_attempts
backoff
jitter
deadline
retry_budget
error_classifier

4.2 如何让任务暂停、等待,再安全地继续 ​

Cancellation(取消)必须传播到底 ​

用户点击:

Cancel

不代表任务真的停止。

取消链路应该:

text
User Cancel
→ Run = CANCELLING
→ Cancel Queued Steps
→ Signal Running Worker
→ Cancel Model Request if possible
→ Cancel Tool / Process
→ Cancel / Reclaim Sandbox
→ Mark CANCELLED

如果 Runtime 只改数据库状态:

text
status = CANCELLED

但后台 Shell 继续:

text
rm -rf ...

就是典型生产事故。


人工审批本质上是一种可持久等待 ​

审批至少包含:

text
request_id
run_id
request_type
requested_action
evidence
requester
approver_policy
deadline
decision
decision_at

必须考虑:

  • 谁能批;
  • 审批多久过期;
  • 多人审批;
  • 审批回来后 Environment 是否还存在;
  • Tool / Agent Version 是否变化;
  • 用户是否能在等待期间补充输入。

OpenAI Agents SDK 当前明确允许 RunState 序列化后长期等待审批,并建议 Pending Task 与 Agent / SDK Version 一起保存。[^openai-hitl]

Microsoft Agent Framework 则把外部等待建模为 RequestPort / RequestInfoEvent,Checkpoint 会把 Pending Request 一起保存,恢复时重新发出。[^ms-hitl]


一个执行跑很久时,Runtime 怎么知道它还活着 ​

某些 Tool / Activity 本身可能执行几十分钟:

text
Large Data Job
Long Browser Automation
Code Build
Video Processing

如果 Runtime 只看:

text
请求还没返回

无法区分:

text
真的在工作
vs
Worker 已经死了

所以 Long-running Activity 常需要:

text
heartbeat
last_progress
progress_payload
heartbeat_timeout

Runtime 可以:

text
heartbeat 超时
→ 标记 Activity Lost
→ Retry / Reconcile

如果 Heartbeat Payload 能保存进度:

text
processed_rows = 3,000,000 / 10,000,000

新 Worker 还可以从更接近当前位置继续,而不是从头开始。


4.3 服务已经升级,旧任务怎么继续跑 ​

旧任务恢复时,到底使用旧版本还是新版本 ​

长 Run 最大的隐性风险之一:

运行逻辑变了,但状态还停留在旧世界。

Run 创建时建议记录:

text
agent_version
prompt_version
tool_version
skill_version
workflow_version
runtime_version
checkpoint_schema_version

恢复策略通常有三种:

策略 做法 适合
Pin Old Version 旧 Run 继续旧代码 高兼容要求
Migrate State 旧 Checkpoint 显式升级 Schema 可迁移
Restart / Reconcile 无法安全恢复时重新起 Run 低风险 / 可重做

不要默认:

text
deserialize old checkpoint
→ run latest code

Determinism(确定性)与 Replay ​

Durable Workflow Runtime 经常依赖:

同一个历史记录重新执行控制逻辑时,应得到相同控制路径。

因为 Replay 不是简单:

text
load Python stack frame

而是:

text
重新执行 Workflow Logic
+
从历史读取已完成外部结果

因此 Workflow Code 中:

  • Random;
  • Current Time;
  • Network Call;
  • LLM Call;

不能随意直接执行,通常需要被 Runtime 包装成 Durable Activity / Task。

LangGraph Functional API 同样强调:恢复特定 Run 时应该沿相同已记录步骤前进,并通过持久化 Task / Subgraph Result 避免重复非确定性工作。[^langgraph-functional]

Temporal 的核心 Durable Execution 模型也建立在持久化 Workflow History 与 Replay 上。[^temporal]


恢复正确,不只要恢复 Run State,还要恢复 Session / History 一致性 ​

这是 Agent Runtime 和普通 Workflow Runtime 很容易不同的地方。

假设:

text
Tool 已经执行成功
↓
准备把 Tool Result append 到 Session
↓
Session 写入失败
↓
进程崩溃

恢复以后如果简单:

text
重新执行 Tool
+
重新 append

就可能产生:

  • Tool 重复执行;
  • Session 历史重复;
  • 模型看到两份相同 Observation;
  • 后续决策被污染。

OpenAI Agents SDK 当前已经专门处理这一类场景:如果 Resume 之后 Tool Work 已完成,但 Session Append 失败,这个 Pending Batch 会随 RunState 一起继续持久化;下次恢复时先精确 Reconcile(对齐)这个 Batch,而不是重新执行 Tool。官方同时要求恢复时继续使用原 Session Backend / Session ID,并对该历史保持 Exclusive Access(排他访问),避免两个独立恢复过程同时修改同一 Session。[^openai-runstate]

因此企业 Runtime 最好把:

text
Run State
+
Session / Thread State
+
Pending Append

作为一个一致性问题考虑。

关键原则:

“Run 恢复成功”不代表“Agent 历史恢复正确”。

对于 Agent Runtime,History / Session Corruption(历史污染)同样会改变后续 Model Decision。

因此真正的 Semantic Recovery(语义恢复)至少要同时检查:

text
Run State 正确
+
Control Flow 正确
+
External Side Effect 正确
+
Session / History 正确
+
Version 正确
+
Execution Environment 正确
+
Pending Work 正确

只有这些同时成立,系统才真正回到一个:

可以继续安全决策的真实世界状态。

Outbox 与 Inbox 分别保护哪个方向 ​

Runtime 还需要区分“我准备发出什么”和“我已经收到什么”。Transactional Outbox(事务外发箱)先把待发事件与本地状态放进同一数据库事务,再由投递器至少一次地发送;Durable Inbox(持久收件箱)则用 signal_id 和状态前置条件接收审批、Webhook 或回调,先落盘去重,再推进 Run。

本地状态变更

同事务写入
State + Outbox

至少一次投递

外部系统

回调 / Signal

Inbox 持久化
去重 + 状态前置条件

推进 Run

这两个机制不提供跨系统“全局恰好一次”。Outbox 解决本地提交后消息不丢,接收方仍需幂等;Inbox 解决重复信号不重复推进,但不能证明上游业务动作只发生了一次。如果回调与外部资源状态冲突,Runtime 仍必须回源对账。


4.4 多个 Worker、海量任务同时运行时怎么不乱 ​

Distributed Concurrency(分布式并发) ​

最典型问题:

text
Worker A claim Run
→ GC Pause

Lease Expire

Worker B claim Run
→ resume

Worker A 恢复
→ 继续写状态

这就是 Split Brain(脑裂)。

常见机制:

text
lease_owner
lease_expire_at
state_version
fencing_token

所有状态写入:

text
write(
  run_id,
  expected_state_version,
  fencing_token
)

过期 Worker 写入必须失败。


任务突然暴增时,怎么避免整个系统被拖垮 ​

Agent 很容易 Fan-out:

text
1000 Parent Runs
×
5 Subagents
×
3 Browser Tools
=
15000 Execution Slots

Runtime 不能等下游:

text
429

再被动处理。

至少要有:

text
global concurrency
tenant quota
model quota
tool quota
execution quota
subagent budget
priority queue

并避免:

text
大客户 / 一个爆量 Tenant
→ 饿死所有其他 Run

所以需要 Fair Scheduling(公平调度)。


一个永远恢复失败的 Run 怎么处理 ​

某些 Run 因代码 Bug:

text
Crash
→ Retry
→ Crash
→ Retry

会无限消耗资源。

必须设置:

text
max_recovery_attempts
dead_letter_state
manual_review

DBOS 当前 Workflow 就提供 max_recovery_attempts,达到上限后进入终态,避免一个 Buggy Workflow 无限拖垮系统。[^dbos-recovery]

因此 Runtime Failure 不只分:

text
retryable / non-retryable

还要考虑:

这个 Run 是否应该退出自动恢复路径,进入人工处理。


4.5 跨多个系统执行失败后,怎么恢复真实世界 ​

Saga / Compensation(长事务 / 补偿) ​

Agent 经常跨系统:

text
Create Ticket
→ Provision Resource
→ Update CMDB
→ Notify Owner

第三步失败后不可能:

text
database rollback

整个世界一起回滚。

因此采用 Saga 思想:

Action Compensation
create resource delete resource
create ticket close ticket
merge PR revert commit
send email 通常不可逆

不可逆操作:

应该提高 Verification / Approval 门槛,而不是幻想 Compensation。


Runtime Recoverability(运行时可恢复性) ​

Recoverability 不只是 Checkpoint 存在。

还需要:

text
State Recoverable
+
Operation Reconciliable
+
Environment Reconstructable
+
Code Version Available
+
Pending Signal Recoverable

例如 Browser Agent:

text
逻辑 Checkpoint 还在
但 Browser Session 已过期

Runtime 必须知道:

text
重新创建 Browser
→ 重放到安全状态
or
重新登录
or
人工介入

这也是 Runtime 与《Agent 安全执行与结果验证》的边界:

Runtime 定义“需要什么环境才能恢复”;Execution 负责真正重建环境。


4.6 运行历史到底应该保留多久 ​

Run 完成以后,下面这些数据留多久?

text
Checkpoint
Journal
Operation Ledger
Idempotency Key
Artifact
Approval Evidence
Trace

不同数据的 Retention 目标不同。

数据 保留目的 太短风险 太长成本
Idempotency Key 防重复请求 重复副作用 存储
Journal Debug / Audit 无法复盘 存储增长
Checkpoint Resume 无法恢复 State Cost
Artifact Evidence 无法验证 Object Storage
Approval Compliance 审计缺失 合规存储

Restate 当前就把 Workflow Retention、Idempotency Retention 和 Journal Retention 作为独立可调配置。[^restate-retention]

所以:

Retention 不只是数据库 TTL,而是 Durability / Audit / Cost 的业务契约。


核心机制如何组合成完整可靠性边界 ​

前面机制可以按系统责任压缩成五组:

责任 核心机制 解决的问题
副作用正确性 Operation Ledger、Idempotency、Reconciliation 外部动作到底成功没有,恢复时会不会重复
持久等待 Wait / Signal、Checkpoint 任务怎样暂停几小时后继续
版本恢复 Version Pinning、Replay、Migration 旧任务遇到新代码怎样继续
Ownership Lease、Fencing、Heartbeat 多个 Worker 怎样避免双执行
大规模治理 Backpressure、Retention、Dead Letter、Multi-region 规模扩大后怎样保持可恢复与可运营

这些机制不是按“基础 / 高级”分层,而是由 Failure Cost、任务持续时间和副作用风险决定是否需要。


五、主流运行时怎样设计 ​

这一章只承担行业证据职责:验证前面推导出的机制在主流 Runtime 中怎样落地。

评价实现时不比较 Feature 数量,而是回答:

text
这些 Runtime 用什么机制实现前面的问题?
为什么这样设计?
代价是什么?
企业应该吸收什么?

5.1 主流 Runtime 怎样验证 Durable Execution 机制 ​

先用统一维度比较 ​

统一比较 Runtime 时,需要回答九个问题:

  • State Model(状态模型):Run 的真实状态怎样表示;
  • Checkpoint Boundary(检查点边界):什么时刻才算状态安全持久化;
  • Replay Model(重放模型):恢复是从 Snapshot 继续,还是依据 History Replay;
  • Retry Semantics(重试语义):失败时哪些步骤可以安全重试;
  • Interrupt / HITL(中断 / 人在回路):等待外部输入怎样成为 Durable State;
  • Side-effect Semantics(副作用语义):DB / API / Deploy 已经发生时怎样避免重复;
  • Concurrency(并发):多个 Worker 怎样争夺 Run Ownership;
  • Versioning(版本):旧 Run 遇到新代码怎样继续;
  • Execution Coupling(执行耦合):Runtime 是否绑定具体 Shell / Browser / Sandbox。

机制对照

实现 核心状态 Checkpoint / Persistence Resume 模型 HITL 最值得研究
OpenAI Agents SDK RunState Serialize RunState 继续 Agent Run Tool Approval Agent 原生 Pause / Resume
LangGraph Thread State Superstep Checkpoint Replay / Fork interrupt() Agent Graph Persistence
Microsoft Agent Framework Workflow State Superstep Checkpoint Resume Workflow RequestPort Workflow + Pending Request
Temporal Workflow History Durable History Deterministic Replay Signal / Update 通用 Durable Execution
Dapr Workflows / Agents Workflow State Workflow Checkpoint Workflow Recovery Workflow Event Agent + Workflow Durability
Restate Journal / Durable State Durable Steps Journal Replay Signal / Promise Journal + Epoch Fencing
DBOS Postgres Workflow State Step Checkpoint Resume Last Completed Step Durable Queue / Event Postgres-native Durability

OpenAI:RunState 怎样解决暂停和恢复 ​

OpenAI 当前 RunState 是:

可序列化的 Agent Run Snapshot,包含 Context、Usage、Interruptions、Model Response、Approval State 等。[^openai-runstate]

重点能力:

  • to_json / to_string;
  • from_json / from_string;
  • Pending Approval;
  • Nested Agent.as_tool() Resume;
  • Pending Session Append Reconciliation;
  • Version Marker 建议。

它最值得学习的是:

一个 Agent SDK 内部怎样把 HITL 中断变成真正可以跨请求 / 跨进程恢复的 Run State。

但它不是完整分布式 Workflow Scheduler。


LangGraph:为什么把 Checkpoint 放在中心 ​

LangGraph 当前把 Graph State 持久化成 Checkpoint,并按 Thread 组织。[^langgraph-persistence]

特点:

  • 每个 Superstep 保存 StateSnapshot;
  • Pending Writes 保留已经完成的并行 Node;
  • Interrupt;
  • Replay;
  • Fork / Time Travel;
  • 可从历史 Checkpoint 重新执行。

特别值得研究的是:

Checkpoint 不只是容灾能力,还同时成为 HITL、Debug、Time Travel、Fork 的统一基础。

LangGraph 当前还提供 DeltaChannel,以减少长 Thread 中 append-heavy State 的 Checkpoint 存储成本,但处于 Beta。[^langgraph-persistence]


Microsoft:怎样把外部等待建模进 Workflow ​

Microsoft Agent Framework 的 Workflow Graph 把不同责任拆开:

  • Executor(执行节点):真正处理一段业务逻辑;
  • Edge(边):定义消息 / 控制流怎样在节点间移动;
  • Event(事件):表达 Runtime 中发生的状态变化;
  • Shared State(共享状态):保存多个 Executor 协作时需要的持久信息。

这种拆分的价值是把“谁执行、怎样连接、发生了什么、共享什么状态”分成不同对象。[^ms-workflow]

Checkpoint 在每个 Superstep 完成后创建,并保存:

  • Executor State;
  • Pending Messages;
  • Pending Request / Response;
  • Shared State。[^ms-checkpoint]

HITL 则通过 RequestPort 实现外部请求 / 响应,恢复 Checkpoint 时 Pending Request 会重新发出。[^ms-hitl]

最值得学习的是:

“等待外部输入”被建模成 Workflow Runtime 的一等机制,而不是业务 UI 特例。


Temporal:Durable History 怎样支撑长期运行 ​

Temporal 的定位非常明确:

Workflow 在 Crash、Network Failure、Infrastructure Outage 后能够继续,并可以运行几秒、几天甚至几年。[^temporal]

它最值得研究的不是 Agent Feature,而是 Durable Execution 的经典机制:

text
Workflow History
Deterministic Replay
Activity
Retry Policy
Timer
Signal
Versioning

适合:

  • 长事务;
  • 跨系统业务流程;
  • 高可靠审批;
  • 不可丢失任务。

代价:

  • Runtime 模型更强;
  • 代码需要遵循 Determinism;
  • 团队学习成本更高。

Dapr:怎样把成熟 Workflow Runtime 带进 Agent ​

截至 2026-09-13,Dapr Agents v1.0 已经 GA(Generally Available,正式可用于生产),官方将其定位为面向生产的 Durable / Resilient Agent Framework,并建立在 Dapr 的状态、消息与 Workflow 能力之上。[^dapr-agents]

它的关键特点不是“能存聊天记录”,而是:

text
LLM Call
Tool Call
Agent State
Workflow Progress

都会进入 Durable Workflow 的持久执行语义。

官方当前示例明确展示:

  • 启动 Agent Run 后立即返回 Workflow ID;
  • 中途杀掉 Agent Process;
  • 重新启动以后继续同一个 Workflow;
  • 已完成步骤由 Durable Workflow History / State 负责恢复,目标是避免因进程重启而从头丢失进度。[^dapr-agents]

Dapr 还明确区分两种控制流:

形态 下一步由谁决定 适合
Workflow 开发者定义 确定性业务流程
DurableAgent Agent 动态决定 开放式 Agent 任务

因此它很适合研究:

如何把 Agent 自主决策放在一个成熟 Durable Workflow Runtime 上,而不是让 Agent 自己重新实现分布式可靠性。

另外,Dapr 当前还强调 Durable / Verifiable Execution 与可审计执行历史,这对于企业合规型 Agent 很有价值。[^dapr-docs]


Restate:Journal 和 Replay 怎样做 Durable Process ​

Restate 当前把自己定位为:

将 AI Agent、Workflow、Backend Service 变成 Durable Process。[^restate]

它把几个传统上分散的可靠性问题放进同一个 Durable Process 抽象:

  • Durable Execution(持久执行):步骤失败后可以根据 Journal 恢复;
  • Built-in State(内建状态):状态和执行历史处于同一可靠性边界;
  • Reliable Communication(可靠通信):服务调用不只是一条易丢失的网络请求;
  • Durable Timer(持久定时器):长时间等待不依赖一个活着的 Worker;
  • Signal / External Event(信号 / 外部事件):外部输入可以唤醒等待中的 Process;
  • Workflow(工作流):这些能力可以组合成长期业务控制流。

Restate 当前实现很值得研究:每个 ctx.run 等 Durable Step 的结果先写入 Journal;Journal Entry 达成复制提交后才认为这一步真正发生。失败重试时,新的 Attempt 会带着完整 Journal,SDK 根据历史结果跳过已经完成的 Step。Runtime 还用递增 Epoch 拒绝旧 Attempt 的迟到写入,避免 Zombie / Split-brain。[^restate-architecture]

这说明:

text
Durability
=
Journal
+
Replay
+
Ownership / Epoch

而不只是“存 State”。

适合研究:

Durable Runtime 是否一定要使用重量级 Workflow DSL,还是可以尽量保持普通代码体验。


DBOS:怎样用 Postgres 承载 Durable Execution ​

DBOS 代表另一种很值得企业研究的路线:

不引入独立 Workflow Cluster,而直接利用 Postgres 作为 Durable Workflow / Queue 的持久底座。

当前 DBOS 官方架构会:

  • Workflow / Step Checkpoint 写入 Postgres;
  • Crash 后从最后完成 Step 恢复;
  • Durable Queue 支持 Global / Worker Concurrency 和 Rate Limit;
  • 事务 Step 可以让业务 DB Write 与 Durable Step Record 同事务提交。[^dbos][^dbos-queue][^dbos-outbox]

最值得学习的是:

text
Durability 不一定等于独立大集群

对于本来就重度依赖 Postgres 的团队,这种架构可能显著降低运维复杂度。

代价是:

  • Durable State 与 Postgres Scale 绑定;
  • 高吞吐 / 大量 History 仍然需要容量设计;
  • 跨数据源副作用仍需要 Idempotency。

5.2 主流路线共同收敛到什么,真正分歧在哪里 ​

案例

案例

案例

案例

Runtime Design Space

State Model
Implicit ↔ Explicit

Persistence
Snapshot ↔ Event History

Control Flow
Agent Loop ↔ Explicit Workflow

Durability
Request-scoped ↔ Multi-day

Replay
None ↔ Deterministic

Execution Coupling
Embedded ↔ Decoupled

OpenAI RunState

LangGraph

Microsoft Agent Framework

Temporal / Dapr / Restate / DBOS

问题不是:

“哪个 Runtime 最先进?”

而是:

当前任务到底需要多强的 Durability / Replay / Workflow Control。


主流 Runtime 共同收敛的机制 ​

跨 OpenAI RunState、LangGraph、Microsoft Agent Framework、Temporal、Dapr、Restate 和 DBOS,可以看到:

  1. Run / Workflow Instance 必须是一等持久对象;
  2. Waiting 不占 Worker,Timer / Human / External Event 都应被建模成 Durable State;
  3. Checkpoint / History 不只是容灾,还支撑 Debug、Fork、HITL 和恢复;
  4. 副作用必须有 Idempotency / Ledger / Reconciliation,Runtime 自己无法魔法实现 Exactly-once;
  5. Ownership 需要 Lease / Epoch / Fencing 等确定性机制;
  6. 版本升级必须进入恢复语义,旧任务不能假设新代码永远兼容。

真正的架构分歧 ​

行业没有统一答案的主要是:

  • Snapshot-centric 还是 History / Replay-centric;
  • Agent Loop 和显式 Workflow 谁拥有主控制流;
  • Runtime 是否要求 Deterministic Code;
  • Durable State 使用独立 Runtime Cluster 还是现有 Database;
  • Runtime 与 Execution Provider 耦合多深。

因此企业选择 Runtime 的核心不是“谁 Feature 多”,而是 任务失败成本、等待时长、副作用风险、恢复语义和运维复杂度 是否匹配。

六、企业级运行时怎样设计 ​

企业级运行时的目标不是把所有 Agent 逻辑搬进 Workflow Engine,而是把“必须可靠”的状态、等待、副作用和 Ownership 语义放进稳定基础设施。

6.1 企业运行时应该统一什么 ​

Runtime 不会消灭复杂度,只会重新分配复杂度 ​

Durable Runtime 解决的是“任务不能因为基础设施故障就丢失”,但它不会让复杂度消失。

设计选择 解决的问题 新复杂度进入哪里
Checkpoint Crash 后可恢复 State Schema、Storage、Migration、Checkpoint Cost
Event History / Replay 可审计、可重放 Determinism、History Growth、Version Compatibility
权威 Operation Ledger 与 Runtime 引用 避免副作用重复 Execution / Capability 负责 Operation State、Reconciliation、Retention;Runtime 负责 operation_id 和等待语义
Lease / Fencing 避免双执行 Ownership、Clock / Expiry、Zombie Writer
Durable Wait Worker 不必长时间占用 Timer、Signal、Pending Request、Resume Burst
Saga / Compensation 跨系统部分失败可处理 Compensation Logic、Irreversible Action
Shared Runtime Platform 多 Agent 复用可靠性底座 Platform Ownership、Migration、Multi-tenant Capacity

因此评审 Runtime 时不能只问:

“能不能 Resume?”

还必须问:

“为了获得 Resume,我们新增了哪些状态、版本、容量、调度和治理复杂度?这些复杂度是否值得?”


Runtime 升级应该由 Trigger 驱动 ​

Runtime 最容易被过度设计。升级建议统一看五类 Trigger:

text
Failure Trigger
→ Crash 后任务丢失、重复副作用、History 污染

Scale Trigger
→ 大量 Waiting Run、Resume Storm、并发 Worker、Fan-out

Risk Trigger
→ Payment / Deploy / Production Write 等高价值副作用

Reuse Trigger
→ 多个 Agent 重复实现 Queue / Timer / Checkpoint / Recovery

Governance Trigger
→ 多版本、多租户、长 Retention、审计与合规

典型演进:

text
In-process State
→ DB-backed Run State
→ Checkpoint + Wait / Signal
→ Runtime 保存 Operation Reference,Execution / Operation Service 提供权威账本与 Idempotency
→ Lease / Backpressure / Versioning
→ Durable Workflow Runtime

统一决策格式:

text
Trigger
→ 当前 Runtime 为什么开始失效

Decision
→ 增加什么可靠性机制

Trade-off
→ 新增什么复杂度 / 成本

Evidence
→ 用什么 Recovery / Duplicate / Resume 指标证明值得

6.2 运行时契约与状态怎样协作 ​

设计原则、职责边界与 Runtime Contract ​

企业 Runtime 最核心的原则:

把 Run 当成一等对象,而不是一个函数调用。

一个 Run 应拥有:

  • ID;
  • 状态;
  • Version;
  • Deadline;
  • Budget;
  • Checkpoint;
  • operation_id 与权威操作账本引用;
  • Trace;
  • Outcome。

这些字段不能因为都被 Runtime 保存,就都由 Runtime 定义语义。企业级契约应把 Owner(责任方)和恢复时的证据分开:

对象 / 契约 语义 Owner Runtime 负责什么 恢复时依据
Action Proposal(动作提案) Harness 与业务 Agent 保存引用、等待审批或调度 提案版本、参数摘要、风险等级
授权决策 / 执行票据 Policy Owner / Policy Service 持久等待、过期时间和票据引用 策略版本、决策证据、票据时效
Operation(外部操作) Execution / Capability 定义并推进业务语义;Execution Control Plane 或 Operation Service 持有权威账本 持久 operation_id、等待 / 调度状态和一致引用 权威操作账本、外部资源 ID、回源结果
Raw Result(原始结果) Execution / Tool Adapter 持久或保存引用 执行器原始回包、状态码、时间戳
Observation(观测结果) Harness 将其作为后续 Step 的输入引用 规范化版本、来源 Raw Result
Artifact / Evidence(产物 / 证据) 业务域与验证机制 保存不可变引用和保留策略 内容哈希、版本、验证结果

Runtime 不能根据自己的数据库状态重新解释业务授权,也不能把 Raw Result 直接当成 Observation 或最终 Evidence。它的责任是让这些由不同 Owner 定义的对象在跨故障后仍保持身份、版本和引用关系。


为什么任务生命周期和真实执行必须分开

Runtime 最好区分:

运行时控制平面 ​

负责:

text
Run State
Scheduler
Queue
Timer
Lease
Retry
Deadline
Version
Checkpoint
Signal

Execution Plane(执行平面) ​

真正执行:

text
Model
Tool
Shell
Browser
Sandbox
VM
SQL

Runtime Control Plane

Queue / Scheduler

State / Checkpoint

Timer / Signal

Lease / Concurrency

Version Manifest
版本清单 / 兼容性

Execution Plane

Model

Tool

Sandbox / Browser

External API

Operation / Result

Harness
行为推进 / 门禁执行

Policy Service
授权决策

这样:

Runtime 不需要自己变成 Browser / Sandbox 系统;它只管理这些执行的生命周期。


Runtime Contract(运行时契约) ​

参考接口:

typescript
interface Runtime {
  createRun(input: RunInput): Promise<Run>;

  claim(runId: string): Promise<Lease>;

  load(runId: string): Promise<RunState>;

  checkpoint(
    runId: string,
    state: RunState
  ): Promise<Checkpoint>;

  wait(
    runId: string,
    condition: WaitCondition
  ): Promise<void>;

  signal(
    runId: string,
    signal: RuntimeSignal
  ): Promise<void>;

  scheduleRetry(
    runId: string,
    retry: RetrySpec
  ): Promise<void>;

  cancel(runId: string): Promise<void>;

  complete(
    runId: string,
    outcome: RunOutcome
  ): Promise<void>;
}

这只是工程参考抽象,不是行业统一 API。


运行时状态和数据怎样存

Runtime Store 怎么选 ​

常见选择:

Store 优点 风险 适合
Relational DB 强事务、查询方便 高 QPS 下需设计 企业通用
KV Store 快、简单 查询能力弱 高频状态
Event Store Audit / Replay 强 复杂 强审计
Workflow-native Store 与 Runtime 语义集成 平台绑定 Temporal / Dapr 等

通常不是只选一种。

例如:

text
Run Metadata
→ Postgres

Hot Lease
→ Redis / KV

Artifacts
→ Object Store

Events
→ Log / Event Store

Checkpoint 是存完整状态还是只存变化 ​

Full Snapshot:

text
每次保存完整 State

简单,但长 Run 状态不断增长。

Delta:

text
只保存变化

存储更省,但恢复要重放。

LangGraph 当前 DeltaChannel 就是针对 append-heavy State 的优化:减少每个 Superstep 写完整累积值,但读取恢复会增加合并成本。[^langgraph-persistence]

所以:

Checkpoint 也存在 Storage vs Recovery Latency 的 Trade-off。


企业 Runtime 参考架构 ​

把前面的对象放到同一张图里:

一致引用

观测

观测

Agent / Workflow API

Runtime Control Plane

Run Registry

Scheduler / Queue

Timer / Signal Inbox

Lease / Fencing

Version Router

State / Checkpoint Store

operation_id / Ledger Ref

Event / Audit Log

Execution Adapter

Model

Tool / API

Sandbox / Browser

Execution Control Plane
或 Operation Service

Authoritative Operation Ledger
权威操作账本

Artifact Store

Trace / Metrics / Eval

这张图强调四个边界:

text
Run Registry
→ 管任务身份和状态

Scheduler / Timer / Lease
→ 管什么时候、由谁执行

Operation Ledger Reference
→ Runtime 管副作用身份和等待引用;Execution Control Plane 或 Operation Service 管权威副作用事实

Execution Adapter
→ 管如何调用真实执行环境

企业 Runtime 的核心不是把这些都做成一个“大服务”,而是保证它们的 Contract 清晰。


6.3 规模、成本和多地域怎样改变运行时 ​

规模上来以后,哪些简单方案会失效 ​

小规模 大规模 架构变化
1 Worker 1000 Worker Lease / Fencing
100 Run 100 万 Run Sharding / Index
10 Waiting Run 10 万 Waiting Run Durable Timer / Efficient Wait
1 Tool 大量异步 Tool Operation Ledger
单 Agent Subagent Fan-out Quota / Backpressure
手工 Retry Retry Storm Retry Budget / Circuit Breaker
单版本代码 多版本 Run 共存 Version Pin / Migration

Scale 最大的反直觉:

Waiting Run 可能比 Running Run 多几个数量级。

所以容量规划不能只看 CPU。


Runtime 的成本主要花在哪里 ​

Runtime 成本不只来自 Compute。

text
Total Runtime Cost
=
State Storage
+ Checkpoint IO
+ Queue / Timer
+ Scheduler
+ Retry Waste
+ Idle Environment Cost
+ Artifact Storage
+ Operations / Human Cost

特别关注:

text
Cost per Successful Run

以及:

text
Cost per Waiting Run / Day

例如:

text
10 万 Waiting Approval Runs

即使 CPU 几乎为 0,仍然有:

  • DB;
  • Timer;
  • Notification;
  • Index;
  • Compliance retention。

6.4 企业运行时什么时候应该自建或采购 ​

贯穿案例与跨领域验证

贯穿案例:Coding Agent 跨小时审批 ​

任务:

“修改支付代码,测试通过后等待 Senior Engineer Approval,再 Merge PR。”

Run 创建 ​

text
run_id = R123
agent_version = 12
tool_version = git_v3
status = RUNNING

修改 / 测试 ​

Tool:

text
edit_file
run_test

都完成后:

text
checkpoint C1

请求审批 ​

text
status = WAITING_APPROVAL
approval_id = A100

Worker 释放。

两小时后 ​

期间:

  • 服务发布新版本;
  • 原 Worker 已销毁;
  • Sandbox TTL 已过期。

Runtime 恢复:

text
load R123
→ agent_version = 12
→ reconstruct execution environment
→ restore artifact / diff
→ receive A100 approval

Merge(合并) ​

生成:

text
operation_id = OP900
idempotency_key = pr_123_merge

调用 Git Provider。

如果 Merge 成功后进程 Crash:

text
Execution / Operation Service 权威账本 = SUCCEEDED
Runtime 保存 operation_id = OP900
Checkpoint = old

恢复时:

Runtime 使用 operation_id 查询权威账本,读到 SUCCEEDED 后复用结果,不再 Merge 第二次。

这个案例串起来:

text
Checkpoint
Wait
Version Pin
Environment Rehydrate
Operation Ledger
Idempotency
Resume

跨领域案例

不同 Agent 需要 Runtime,不是因为它们都使用模型,而是因为它们跨越了不同的时间、故障和副作用边界。下表先说明场景特征和简单方案为什么失效,再推导最小机制:

场景 本质特征 简单方案怎样失效 Runtime 最小机制 恢复证据与验收
Data Agent 查询可能长时运行,结果大且应与查询快照绑定 Worker 阻塞等待会耗尽并发;盲目重提交会重复消耗计算资源,并可能读到不同数据快照 持久 Job ID、等待信号、结果产物引用、截止时间 回调与主动查询结果一致;恢复后仍指向原查询快照
Coding Agent 跨多轮修改、构建和审批,工作区会被回收,动作具有文件与进程副作用 只保存对话会丢失 Diff、依赖和运行进度;从头重跑可重复提交或使用已过期工具 Checkpoint、环境清单、产物引用、版本锁定、审批等待和权威操作引用 在新 Worker 上恢复后 Diff 哈希一致;构建和测试可重放;Merge 不重复
Ops Agent 诊断状态持续变化,动作直接修改生产,存在影响面和回滚时限 用旧 Checkpoint 直接重放生产写入,可能在环境已变化时扩大故障 时效化授权票据、执行前重读、权威操作引用、补偿计划和健康验证 恢复前对账生产实际状态;执行后重新读取健康指标;超过风险门槛转人工

共享 Runtime 因此只应统一 Run 身份、耐久状态、等待、调度、版本、operation_id 和证据引用等稳定语义。“数据结论是否正确”、“代码是否可合并”、“服务是否恢复”仍由各业务域的 Verification(验证)判定,Runtime 只保存结果和证据引用。

Data Agent(数据智能体) ​

长 SQL / Notebook Job:

text
submit_query
→ WAITING_EXTERNAL
→ query callback
→ Resume

不要 Worker 阻塞等待。


Browser Agent(浏览器智能体) ​

Browser Session TTL 到期:

text
Checkpoint
→ environment manifest
→ recreate browser
→ restore authenticated / navigable state

Runtime 定义恢复需求,《Agent 安全执行与结果验证》负责实际环境恢复。


Ops Agent(运维智能体) ​

执行 Production Change:

text
Approval
→ Execute
→ Health Check
→ If Failed
→ Compensation / Rollback

Execution Control Plane 或 Operation Service 的权威操作账本必须完整,Runtime 保存 operation_id 与等待引用。


什么时候自己做,什么时候使用成熟 Runtime

不要默认自研 Durable Workflow Engine。

简单场景 ​

text
Postgres Run Table
+ Queue
+ Worker

可能足够。

此时最重要的不是“买 Workflow Engine”,而是先把:

text
Run ID
State Machine
Operation ID
Cancellation

做正确。

中等复杂度 ​

text
Application Checkpoint
+ Durable Timer
+ Operation Ledger

高复杂度 ​

满足多个条件时考虑成熟 Workflow Runtime:

text
大量 Long-running
大量 External Wait
跨系统 Saga
强恢复
高并发
严格 Audit

可以评估:

text
Temporal
LangGraph
Dapr
Restate
Microsoft Agent Framework

核心问题不是:

“Agent 团队是不是应该用某个热门框架?”

而是:

我们真正需要哪一种 Durable Semantics。

Build、Buy、OSS 和 Managed 怎样做 Runtime 采购决策 ​

Build(自建)、Buy(商业软件采购)、OSS(开源软件)和 Managed(托管服务)不应通过功能数量打分。Runtime 的决策核心是:在预期故障和版本变化下,候选方案能否使用可导出的状态和证据恢复正确业务语义。

需求与故障成本

RFI
信息征询

PoC
概念验证

安全 / 合规 / 容量

三年 TCO
总拥有成本

SLA
服务等级协议

状态导出与退出演练

决策

Runtime 专属 PoC 应使用同一组带故障的任务,而不是只跑快乐路径:

验证项 必须注入的条件 通过证据 直接淘汰信号
副作用恢复 Tool 成功后丢失回包,并在 Checkpoint 前崩溃 恢复前先对账,业务资源只有一份,账本可追溯 恢复默认重跑外部写操作
等待与信号 审批期间重启,回调重复与乱序 Inbox 先持久化并去重,只有符合状态前置条件的信号推进 Run 回调只存内存,重放会二次推进
版本兼容 旧 Run 等待期间升级 Workflow、Tool 和 Schema 可锁定旧版本或显式迁移,恢复回归集通过 默认用最新代码反序列化旧状态
并发所有权 Worker 失联后旧 Worker 恢复,新 Worker 已接管 过期 Fencing Token(栅栏令牌)写入被拒绝,无重复副作用 只靠超时判断 Worker 死亡
可移植与退出 导出 Waiting Run、Checkpoint、History、Timer 和 Operation Ledger 备用实现可重建等待、版本和操作状态,并重放验证集 只能导出业务结果,不能导出可恢复语义

三年 TCO(Total Cost of Ownership,总拥有成本)至少包含:许可或托管费用、状态与 History 存储、跨地域复制、执行环境待机、迁移适配、平台运维人力、故障演练以及退出重建成本。成本口径应同时报告每个验证成功 Run、每个 Waiting Run 每日和每次故障恢复的完整成本,否则低价存储可能掩盖高额运维与迁移费用。

SLA(Service Level Agreement,服务等级协议)不能只约定 API 可用性,还应约定状态耐久边界、恢复时间、恢复点、信号丢失和重复的处理、版本下线通知期、安全事件通知、数据导出时限与删除证明。采购通过不等于退出能力成立;至少应在签约前完成一次导出、备用实现恢复和回放验证集的退出演练。


多地域、数据安全与合规

当 Failure Domain(故障域)从“进程 / 机器”扩大到 Region(地域)时,Durability(持久性)的保证边界也必须同步扩大:状态复制、Timer Ownership、Lease Failover、Signal 去重和 Global Idempotency 都要具备跨地域语义。

当整个地域发生故障时还能不能恢复 ​

企业级 Runtime 最终还会面对:

text
一个 Process 挂
→ Worker Recovery

一个 Node 挂
→ Cluster Recovery

一个 Region 挂
→ Disaster Recovery

必须定义:

text
RPO(Recovery Point Objective,恢复点目标)
→ 最多能丢多少状态?

RTO(Recovery Time Objective,恢复时间目标)
→ 多久必须恢复?

Multi-region 需要考虑:

  • State Replication;
  • Timer Ownership;
  • Lease Failover;
  • Duplicate Signal;
  • Clock Skew;
  • Global Idempotency;
  • Artifact Replication。

因此:

Durability 的最高层不是“进程不丢”,而是“故障域变化以后语义仍然正确”。


持久化以后,原本的内存数据会带来哪些安全问题 ​

Runtime 会把大量原本“只在内存里”的数据长期落盘:

text
User Context
Tool Arguments
Approval Evidence
Model Output
Secrets / Tokens
Artifact Ref

OpenAI Agents SDK 当前也明确提醒:序列化 RunState 时,应用 Context 会成为持久数据,不应把 Secret 放进去,除非明确希望它随 State 一起存储 / 传输。[^openai-runstate]

企业 Runtime 至少需要:

  • Encryption at Rest;
  • Tenant Isolation;
  • Field-level Redaction;
  • Secret Reference,而不是 Secret Value;
  • Retention Policy;
  • Approval Audit;
  • Access Log。

所以:

Durability 会把短期内存风险变成长期数据治理风险。


企业演进路线 ​

演进阶段不是功能清单,而是由已经出现的失效信号驱动。每个阶段都应有进入条件、退出证据、暂不建设的能力与回滚方式:

阶段 进入条件 核心机制 退出证据 暂不建设 / 回滚
阶段一:统一 Run 无法追踪任务归属、截止时间和结果 run_id、状态机、截止时间、预算、Trace Run 不丢失,终态可解释,一次任务可端到端追踪 不自建 Workflow Engine;不稳定时回退到单 Worker 但保留 Run 记录
阶段二:副作用可对账 已出现写操作、超时未知或重复资源 Operation ID、幂等键、操作账本、Reconciliation 故障注入中无未解释重复副作用,UNKNOWN 均有可执行的对账路径 不为全部读操作建账本;紧急回滚为停止自动写入、转人工对账
阶段三:持久等待与恢复 任务跨进程、需要审批或等待外部作业 Checkpoint、Wait / Signal、Durable Inbox、版本清单 重启、重复信号、等待期间发版等测试下均能正确恢复 不持有长期 Worker 或执行环境;恢复不确定时暂停并转人工
阶段四:分布式调度 多 Worker、多租户或恢复风暴使单队列方案失效 Lease、Fencing、背压、配额、公平调度 无脑裂写入,峰值下重要租户 SLO(Service Level Objective,服务水平目标)仍可达 不提前做多地域;调度故障时降低准入、保护正在执行的 Run
阶段五:引入完整持久工作流 多团队重复实现 Timer、Saga、版本恢复和审计,自研边际成本高于迁移 成熟 Runtime 及治理控制面 PoC 故障用例、三年 TCO、迁移及退出演练均达标 不迁移短任务和低失败成本流程;保留双读、影子恢复和回切窗口

这一顺序的含义不是所有系统都必须走到阶段五,而是先证明当前复杂度已经失效,再把对应可靠性责任移入共享 Runtime。如果任务可以安全从头重跑、没有外部写入且没有长时等待,停留在阶段一仍是合理架构。


七、运行时问题怎样治理 ​

7.1 先建立失败分类和 Debug 路径 ​

Runtime 故障

状态 / Checkpoint

重试 / 副作用

等待 / 信号

并发 / 版本

环境恢复 / 容量

故障类型 典型症状 首查证据 责任边界与恢复方向
状态丢失 Run 消失或退回旧状态 State Store 写入记录、状态版本 Runtime 恢复 Durable State(持久状态),业务域确认是否可继续
Checkpoint 损坏 反序列化失败或状态缺字段 Checkpoint Schema Version、校验和 从备份恢复或显式迁移,不用最新代码强行读取
重试风暴 依赖故障时请求放大 Retry Trace、依赖健康度 Runtime 实施退避、重试预算和熔断,Harness 处理业务重规划
重复副作用 重复工单、通知或付款 Operation Ledger、外部资源 ID 恢复前对账,使用幂等键或补偿,不盲目重试
信号丢失或重复 Run 永久等待或重复推进 Inbox、signal_id、状态迁移日志 Runtime 先持久化并去重,只在前置状态匹配时 Resume
脑裂执行 两个 Worker 同时写同一 Run Lease Owner、Fencing Token、State Version Runtime 拒绝过期所有者写入;Execution 的副作用仍需幂等与对账
版本漂移 旧 Run 恢复失败或语义改变 Version Manifest、恢复回归结果 锁定旧版本、显式迁移或安全重启并对账
执行环境丢失 Sandbox 已销毁或凭证过期 Environment Manifest、Artifact Hash Runtime 提供恢复需求,Execution 重建环境,验证机制判定可否继续
背压失效 Queue 和 Resume 速率超过下游容量 Queue Depth、恢复速率、租户配额 准入控制、分批唤醒和公平调度

Debug(调试)顺序 ​

text
Run 还存在吗?
↓
State Version 正确吗?
↓
最新 Checkpoint 可读吗?
↓
Pending Operation 是什么状态?
↓
是否有 Pending Wait / Signal?
↓
当前 Lease Owner 是谁?
↓
版本兼容吗?
↓
Execution Environment 能恢复吗?

No

Yes

No

Yes

Yes

No

Yes

No

Yes

No

No

Yes

No

Yes

Run Stuck / Failed

Run State 存在?

State Loss

Checkpoint Valid?

Checkpoint / Migration

Pending Operation Unknown?

Reconcile Side Effect

Waiting for Signal?

Check Durable Inbox / Timer

Lease Conflict?

Lease / Fencing

Version Compatible?

Pin / Migrate

Execution Restorable?

Environment Rehydrate

Application / Harness Logic


7.2 典型故障场景怎样暴露 Runtime 机制缺口 ​

以下是由分布式运行时失效模式构造的架构推演,用于设计故障注入和验收用例,不声称它们来自某家企业未公开的真实事故。

故障场景一:Tool 成功后 Crash,恢复时重复创建 ​

链路

text
create_ticket succeeds
→ process crash
→ checkpoint not advanced
→ resume
→ create_ticket again

错误修复

text
Retry max = 1

仍不能解决“不知道第一次成功没有”。

正确修复

text
operation_id
+ idempotency_key
+ external_resource_id
+ durable result

平台结论

副作用恢复靠 Operation Semantics,不靠 Retry 次数。


故障场景二:审批回来后代码已经升级 ​

症状

旧 Run 反序列化失败,或 Tool 参数语义改变。

根因

Checkpoint 没 Version Manifest。

正确修复

text
agent_version
tool_version
workflow_version
checkpoint_schema_version

Run 恢复时按旧版本执行或显式 Migration。


故障场景三:Cancel 了,但后台 Shell 继续跑 ​

根因

Cancellation 只更新 Control Plane,没有传播到 Execution Plane。

正确修复

text
Cancel Run
→ Propagate Cancel Signal
→ Kill Process / Tool
→ Reclaim Environment
→ Persist Terminal State

故障场景四:两个 Worker 同时恢复同一 Run ​

链路

text
Worker A stalls
→ Lease expires
→ B resumes
→ A wakes up
→ both write

正确修复

text
Lease
+ Fencing Token
+ State Version

故障场景五:Retry Storm(重试风暴) ​

外部 API 大面积故障时,每个 Run 独立重试会把原始请求放大为“Run 数 × 每个 Run 重试次数”,进一步压垮依赖。这里的关键不是某个示意数字,而是请求放大机制。

正确:

text
Exponential Backoff
Jitter
Retry Budget
Circuit Breaker
Global Rate Limit

故障场景六:Waiting Run 数量激增 ​

审批系统积压时,Waiting Run 可以在短时间内持续增长。

CPU 仍然不高,但:

  • Timer;
  • DB Index;
  • Notification;
  • Retention;

开始成为瓶颈。

平台结论:

Waiting Capacity 必须独立建模。


故障场景七:恢复后重复收到同一个 Signal ​

症状

Webhook / Approval 回调重复发送:

text
APPROVED
APPROVED
APPROVED

Runtime 如果每次都 Resume,可能重复执行后续 Step。

根因

Signal 没有:

text
signal_id
deduplication
expected_run_state

正确设计

text
Durable Inbox
+ signal_id
+ state precondition
+ idempotent transition

即:

text
WAITING_APPROVAL
+ APPROVAL(A100)
→ QUEUED

再次收到 A100
→ ignore / return previous result

平台结论

外部 Signal 也必须有 Idempotency Semantics。


故障场景八:Heartbeat 丢失导致双执行 ​

长 Tool:

text
Worker A processing 30 min

网络隔离后 Runtime 认为 A 死了,Worker B 开始 Retry。

但 A 实际仍在外部系统执行。

这时:

text
A + B

可能同时产生副作用。

正确设计:

  • Activity Heartbeat;
  • Lease / Fencing;
  • Operation ID;
  • 外部系统 Idempotency;
  • Reconciliation。

平台结论

“Worker 看起来死了”不代表外部副作用已经停止。


故障场景九:Run 恢复了,但 Session History 被重复写入 ​

症状

Agent 恢复以后:

  • 同一个 Tool Result 出现两次;
  • 模型认为执行了两遍;
  • 后续 Planning 开始偏离。

链路

text
Tool succeeded
→ append Tool Result to Session
→ append failed
→ process crashed
→ resume
→ tool executed again / result appended again

根因

Runtime 只保证:

text
Run State durable

却没有保证:

text
Session History mutation durable / idempotent

正确修复

text
pending session append
+
append batch identity
+
exclusive session access
+
resume reconciliation

OpenAI Agents SDK 当前已经对这类 Pending Session Append 做持久化和恢复前 Reconcile。[^openai-runstate]

平台结论

Agent Runtime 的恢复一致性必须覆盖 Run State 和 Agent History 两层。


7.3 怎样把故障映射到机制、证据和指标 ​

前面的故障场景不应该只是“故事”。

真正有价值的是形成一张 Production Map(生产映射表):

故障场景 根因 核心机制 调试证据 关键指标
Tool 成功后 Crash,恢复时重复创建 副作用状态未知 Operation Ledger + Idempotency + Reconciliation operation_id、external_resource_id、Tool Result Duplicate Side-effect Rate
审批回来后旧 Run 无法恢复 版本漂移 Version Pinning + Migration version manifest、checkpoint schema Resume Failure Rate
Cancel 后 Shell 继续跑 Cancel 未传到执行层 Cancellation Propagation cancel event、process state Cancel Completion Latency
两个 Worker 同时恢复一个 Run Ownership 不唯一 Lease + Fencing Token lease_owner、fencing_token Split-brain Incident
外部系统故障引发 Retry Storm Retry 无全局预算 Backoff + Retry Budget + Circuit Breaker retry trace、dependency health Retry Amplification
Waiting Run 数量爆炸 等待容量未建模 Durable Timer + Capacity Planning waiting_count、timer_count Cost per Waiting Run / Day
同一个 Approval Signal 重复到达 Signal 非幂等 Durable Inbox + signal_id signal log、state transition Lost / Duplicate Signal Rate
Heartbeat 丢失后双执行 Liveness 与 Ownership 混淆 Heartbeat + Lease + Fencing heartbeat、lease、operation ledger Duplicate Side-effect Rate
Run 恢复但 Session History 重复 History mutation 未持久对齐 Pending Append + Reconciliation session batch id、history diff History Corruption Rate

这张表体现一个重要原则:

生产治理不是“遇到事故再看日志”,而是 Failure → Evidence → Mechanism → Metric 的闭环。


7.4 怎样衡量运行时的正确性、稳定性和效率 ​

指标只有在样本、分母、时间窗和归因规则固定后才能用于治理。本节不再沿用系统性质的 P0 / P1 / P2,而是分为结果指标、诊断指标和效率指标,避免把“先保证什么”与“如何定位问题”混成一套优先级。

结果指标|最终是否不丢、不重、不乱

Metric 口径 主要证据
Run Completion Rate 观测窗口内进入合法终态且通过业务验证的 Run / 到达 Deadline 的有效 Run;用户取消单独分类 Run State Transition、Verification Result
Recovery Success Rate 故障注入或真实故障后在恢复时限内回到可安全推进状态的 Run / 进入恢复的 Run Recovery Attempt、Checkpoint、Reconciliation Evidence
Duplicate Side-effect Rate 被确认为重复业务效果的 Operation / 已执行外部写 Operation Operation Ledger、外部资源 ID
Lost Run Rate 已接受但无可查状态或不能解释终态的 Run / 已接受 Run 接入日志、Run Registry
Lost Signal Rate 已由上游确认投递却未进入 Inbox 或未形成合法迁移的信号 / 已投递有效信号 上游投递记录、Inbox、State Transition
History Duplication / Corruption Rate 恢复后发生重复或无来源 History 写入的 Run / 已恢复 Run Session Batch ID、History Diff

诊断指标|问题发生在哪个环节

Metric 含义
Stuck Run Rate 卡住比例
Checkpoint Failure Rate Checkpoint 失败
Retry Recovery Rate 重试恢复效果
Split-brain Incident 并发所有权错误
Resume Failure Rate 恢复失败

效率指标|是否足够快、足够省

Metric 含义
Mean / P95 Resume Latency 恢复延迟
Checkpoint IO / Run 存储成本
Retry Amplification 重试额外倍数
Cost per Successful Run 成功任务成本
Cost per Waiting Run / Day 等待任务持有成本
Scheduler Queue Latency 调度等待

7.5 容量和成本怎样进入运行时治理 ​

至少估算:

text
Active Runs
Waiting Runs
Runs Created / sec
Resume / sec
Checkpoint QPS
Checkpoint Size
Timer Count
Queue Depth
Model Concurrency
Tool Concurrency
Subagent Fan-out
Artifact Volume

最容易漏掉:

Resume Storm(恢复风暴)

例如依赖系统恢复后:

text
100k WAITING_EXTERNAL
→ 同时收到 Signal
→ 瞬间 Resume

需要 Admission Control(准入控制)和分批唤醒。

可以做一个粗略容量模型:

text
required_resume_capacity
=
incoming_resume_rate
×
avg_step_duration

例如:

text
10,000 resumes / min
×
6 sec avg execution
≈
1,000 concurrent slots

再乘:

  • model fan-out;
  • subagent factor;
  • tool concurrency;

最终可能远大于表面 Run 数。

因此 Runtime Capacity Planning 必须同时建模:

text
steady-state
+
burst
+
recovery burst

三种流量。


Runtime 的成本到底花在哪里 ​

text
Runtime Cost
=
State Storage
+ Checkpoint IO
+ Queue / Timer
+ Scheduler
+ Retry Waste
+ Waiting Retention
+ Environment Hold Cost
+ Human Operations

优化要看:

text
Cost per Verified Successful Run
Cost per Waiting Run / Day
Cost per Retained Completed Run

Retention 越长:

  • Audit 越强;
  • Storage Cost 越高。

因此 Cost Model 需要同时考虑:

text
active cost
+
waiting cost
+
historical retention cost

而不是:

text
DB 单次写入多少钱

7.6 怎样证明运行时真的能够恢复 ​

上线前至少演练:

text
1. Model Call 中进程 Crash
2. Tool 成功后 Checkpoint 前 Crash
3. Approval 等待期间 Deploy
4. Sandbox 被回收
5. Database Failover
6. Queue Duplicate Delivery
7. Worker Split Brain
8. Timer Service 延迟
9. Version Migration Failure
10. Massive Resume Storm

Durability 是:

必须通过故障注入证明的系统属性。

不能只靠单元测试证明。


怎样评测 Runtime(运行时)

Outcome Eval(结果评测) ​

text
Recovery Success
Duplicate Side Effect
Resume Latency

Ablation(消融实验) ​

关闭:

text
Operation Ledger
Checkpoint
Fencing
Backoff

观察 Failure。

Counterfactual(反事实评测) ​

构造:

text
Tool success + lost response
Old Checkpoint + new Tool Schema
Duplicate Signal
Clock skew
Lease expiry

检查 Runtime 是否保持正确性。

Sensitivity(敏感性分析) ​

变化:

text
checkpoint_interval
lease_ttl
retry_max
queue_concurrency

寻找合理 Operating Range。


7.7 运行时怎样发布、灰度和迁移 ​

发布要考虑:

text
New Run
Old Running Run
Waiting Run
Paused Approval Run
Retry-scheduled Run

推荐:

text
new runs → new runtime version
old runs → pinned old version
worker drain
checkpoint compatibility check
migration canary
resume test
rollback

指标必须按:

text
runtime_version
checkpoint_schema_version
agent_version

分桶。


附录 A:高频架构问题与快速回答 ​

整篇 Runtime 机制可以压缩成下面这条主线:

text
任务活得越来越久
↓
内存状态不可靠
↓
需要 Run + Checkpoint

任务会等待
↓
需要 Durable Wait + Signal

任务会改变真实世界
↓
需要 Operation Ledger + Idempotency + Reconciliation

任务会分布式运行
↓
需要 Lease + Fencing + Backpressure

任务会跨版本、跨故障域恢复
↓
需要 Versioning + Migration + DR

A.1 核心概念与边界问题 ​

Q1:什么是 Agent Runtime? ​

30 秒答案

Agent Runtime 是负责一次 Agent Run 的状态、调度、等待、重试、恢复、并发和持久化的运行层。Harness 解决“怎么工作”,Runtime 解决“这个 Run 怎么可靠地活着”。

详细答案

如果只有 Agent Loop:

text
Model
→ Tool
→ Observation
→ Model

它可以在一个进程里正常工作。

但只要出现:

text
进程 Crash
人工审批等待
异步 Tool
服务发布
Worker 迁移
并发恢复

就需要另一个系统回答:

text
Run 现在是什么状态?
做到哪一步?
等什么?
哪些副作用已经发生?
谁有权继续执行?
恢复时用哪个版本?

Runtime 就负责这些语义。

它通常包括:

text
Run State
Checkpoint
Queue / Scheduler
Wait / Signal
Retry
Lease
Cancellation
Version
Operation Ledger

边界

Runtime 不等于 Harness,也不等于 Sandbox。Runtime 可以调用 Execution Plane,但不负责真正执行 Browser / Shell。

常见误区

“Runtime 就是保存 Agent Messages 的数据库。”

Messages 只是状态的一部分;真正 Runtime 还要管理 Control Flow、等待、副作用和恢复。


Q2:什么是 Durable Execution? ​

30 秒答案

Durable Execution 是让一个长任务在 Crash、Restart、Deploy、Node Migration、Long Wait 之后,仍能从正确状态继续,而且不错误重复已经发生的副作用。

详细答案

Durability 至少包含:

text
Durable State
+
Durable Control Flow
+
Durable Wait
+
Durable Side-effect Semantics
+
Version-aware Resume

举例:

text
Agent 创建工单成功
→ 进程 Crash
→ 2 分钟后恢复

如果 Runtime 只保存“当前 Step”,恢复时可能再次创建工单。

真正 Durable Runtime 应该知道:

text
operation_id = OP1
external_ticket_id = T100
status = SUCCEEDED

于是跳过副作用,继续下一步。

高分点

Durable Execution 的核心不是“任务不会失败”,而是“失败以后可以在保持语义正确的前提下继续”。


Q3:Checkpoint 和 State 有什么区别? ​

30 秒答案

State 是“当前事实”;Checkpoint 是“某一时刻可以用于恢复的持久快照”。

详细答案

Run State 可能不断变化:

text
status
current_step
budget
latest_observation

Checkpoint 则是:

text
State
+ Resume Cursor
+ Pending Request
+ Pending Operation
+ Version Manifest
+ Artifact Pointer

因此:

text
State
≠
Checkpoint

一个系统可以在内存中有 State,但如果没有 Durable Checkpoint,进程 Crash 后仍然无法恢复。

工程边界

Checkpoint Frequency 需要权衡:

text
write cost
vs
recovery rework

高价值边界如 Tool Side Effect、Approval、Model Result 通常更值得保存。


Q4:为什么 Checkpoint 不是简单存 JSON? ​

30 秒答案

因为恢复需要的不只是“数据值”,还要恢复控制流、待处理工作、副作用状态、版本和环境需求。

详细答案

简单 JSON:

json
{"step": 3}

无法回答:

text
Step 3 的 Tool 是否已经执行?
审批是否还在等?
Tool 是 V1 还是 V2?
原 Sandbox 是否需要重建?
恢复后下一步是 Retry 还是 Continue?

完整 Checkpoint 至少需要:

text
logical state
next cursor
pending requests
pending operations
artifact refs
budget / deadline
version manifest
environment manifest

常见误区

“把整个 Agent 对象 pickle 一下。”

这会把进程内实现细节和 Durable Contract 混在一起,版本升级也极难兼容。


Q5:为什么 Exactly-once 很危险? ​

30 秒答案

Exactly-once 要先问“在哪个边界内”。网络和外部系统存在不确定性,通常不能靠 Runtime 一句话保证业务副作用全局恰好一次;现实方案是 Idempotency + Durable Ledger + Reconciliation。

详细答案

经典场景:

text
charge_payment()
→ 支付成功
→ Response Lost
→ Runtime 看到 timeout

如果直接 Retry,就可能重复付款。

所以:

text
Delivery exactly-once
≠
Business Effect exactly-once

更可靠:

text
operation_id
idempotency_key
external_resource_id
result record
reconcile()

例外

如果业务写入和 Durable Step Record 能在同一个 DB Transaction 中提交,例如 DBOS 的 Transaction Step,那么这个数据库边界内可以获得更强的 Exactly-once 语义;但跨外部 API 后仍要重新分析。


Q6:Run 和 Session 有什么区别? ​

30 秒答案

Run 是一次具体任务执行;Session / Thread 是多轮交互容器。一个 Session 可以包含多个 Run。

详细答案

例如:

text
Session: “修复支付 Bug”
├─ Run 1:定位
├─ Run 2:用户补充信息后修改
└─ Run 3:最终验证

Run 有自己的:

  • Budget;
  • Checkpoint;
  • Operation Ledger;
  • Outcome;
  • Trace。

Session 更偏:

  • conversation history;
  • user continuity。

如果两者混在一起:

  • 成本无法归属;
  • Checkpoint 不清楚;
  • Approval 难定位;
  • Retry 可能跨任务污染。

边界

不同产品命名不统一,关键是逻辑语义要分开。


Q7:为什么 HITL 是 Runtime 问题? ​

30 秒答案

因为 HITL 的本质不是 UI 弹窗,而是一个可能持续小时或数天的 Durable Wait。

详细答案

当 Agent 请求审批:

text
Run
→ WAITING_APPROVAL

此时 Runtime 应:

  • 保存 Pending Request;
  • 持久化 State;
  • 释放 Worker;
  • 等待 Signal;
  • 审批回来后重新 Queue;
  • 从正确 Version Resume。

审批期间进程可以完全不存在。

还需要:

  • approver identity;
  • deadline;
  • evidence;
  • multi-approval;
  • version compatibility。

所以 Approval 是 Runtime State,而不是前端状态。


Q8:为什么取消不是改 status? ​

30 秒答案

因为数据库里写 status=CANCELLED 只改变控制面,不代表真实 Tool、Shell、Browser 已停止。

详细答案

正确取消链路:

text
User Cancel
→ CANCELLING
→ stop queued work
→ notify worker
→ cancel model request
→ terminate tool / process
→ reclaim sandbox
→ persist terminal state

还要考虑 Race:

text
Cancel
vs
Tool just completed

如果 Tool 已产生副作用,Runtime 还需要正确记录 Result,不能因为 Cancel 就把真实世界状态忘掉。

高分点

Cancellation 是分布式状态转换,不是一个 Boolean。


Q9:什么场景不需要 Durable Workflow Engine? ​

30 秒答案

秒级、无副作用、无外部等待、失败可以低成本从头重跑的 Agent,通常不需要复杂 Durable Workflow Engine。

详细答案

例如:

text
用户问天气
→ Tool
→ Answer

即使进程 Crash:

text
重新请求一次

成本很低。

如果为了这种任务引入:

  • Event Sourcing;
  • Saga;
  • Durable Timer;
  • Worker Version Pin;

只会增加复杂度。

可以按:

text
Task Lifetime
×
Side-effect Risk
×
Recovery Value
×
Concurrency Scale

决定 Runtime 等级。

高分点

Durable Runtime 是失败成本驱动的,而不是 Agent 身份驱动的。


Q10:Runtime 和 Workflow Engine 有什么关系? ​

30 秒答案

Workflow Engine 是实现 Durable Runtime 的一种重要技术,但 Runtime 范围更广。

详细答案

Workflow Engine 强项:

text
Control Flow
Checkpoint
Timer
Retry
Signal

Agent Runtime 还可能需要:

text
Agent RunState
Operation Ledger
Model Usage
Approval
Execution Environment Manifest
Agent / Tool Version

有些系统:

  • Temporal:Workflow Runtime 更强;
  • OpenAI Agents SDK:Agent RunState 更强;
  • LangGraph:Agent Graph + Persistence 融合。

因此:

Workflow Engine 可以承载 Runtime,但 Runtime 概念不应被限定成 Workflow DAG。

常见误区

把“用了 Agent”理解成“不需要 Workflow Runtime”。实际上长任务 Agent 往往更需要 Durable Control。


A.2 生产工程问题 ​

Q11:Tool 成功后 Crash,怎么避免重复执行? ​

详细答案

最危险的 Crash Point 是:External Tool 已成功,但 Runtime 还没持久化 operation_id 与等待关系。正确链路应由 Execution / Operation Service 先保留 operation_id 并将权威账本写为 PLANNED,Runtime 再保存一致引用;Execution 调用带 Idempotency Key 的外部 Tool,并将 external_resource_id / result 写入权威账本后标记 SUCCEEDED。恢复时 Runtime 先使用 operation_id 查询权威账本:SUCCEEDED 直接复用;STARTED / UNKNOWN 先 Reconcile,不能盲目 Retry。


Q12:Retry 怎么分类? ​

详细答案

Retry 至少区分 Transient、Deterministic、Permission、Side-effect Unknown、Dependency Outage、Model Format。429 可以 Backoff;SQL Syntax Error 同参数 Retry 没意义;Payment Timeout 则必须先查外部状态。Retry Policy 应结合 Error Classifier、Deadline、Attempt、Side-effect Contract 和 Retry Budget。


Q13:Checkpoint 多久一次? ​

详细答案

Checkpoint 频率本质是 Checkpoint IO Cost 与 Crash 后 Rework Cost 的权衡。Model Call 完成、高价值 Tool Result、不可逆 Side Effect、Human Approval、Phase Boundary 通常值得 Checkpoint;纯内存格式转换未必。不要机械地“每 N 秒一次”。

看:

text
checkpoint cost
vs
recovery rework cost

副作用 / Model / Approval 等边界优先 Checkpoint。


Q14:如何处理 Side-effect Unknown? ​

详细答案

Side-effect Unknown 是最危险状态。请求 Timeout 后无法知道对方没执行、执行失败,还是已执行但响应丢失。必须提供 query_by_operation_id、查询外部资源或业务状态的 Reconcile Path;只有确认未发生,才能重试。


Q15:如何避免两个 Worker 同时执行一个 Run? ​

详细答案

典型做法是 claim(run_id, expected_version) → lease + fencing_token。Worker 每次写 State 都带 state version 和 fencing token。Lease 过期后旧 Worker 即使恢复,也因为 Token 过旧而无法写入。这比单纯分布式锁更能防 Zombie Writer。


Q16:Waiting Run 怎么实现低成本? ​

详细答案

Waiting Run 应持久化 wait condition + wake_at / signal key 后释放 Worker。Approval 等待 2 天不需要一个 Worker 活 2 天;Signal 到达后再重新 Queue / Claim / Resume。这让十万 Waiting Run 的 CPU 仍可接近零。

持久化:

text
wait condition + wake_at / signal key

释放 Worker,由 Timer / Signal 再 Queue。


Q17:审批回来时 Tool 已升级怎么办? ​

详细答案

Run State 应保存 Agent、Prompt、Tool、Skill、Workflow、Runtime、Checkpoint Schema Version。恢复策略只能是 Pin Old Version、Explicit Migration 或 Safe Restart / Reconcile 之一,不能默认用最新代码反序列化旧状态。


Q18:怎样处理 Runtime Version Upgrade? ​

详细答案

Runtime 发布必须区分 New Run、Running Run、Waiting Run 和 Retry-scheduled Run。推荐 New Run 使用新版本、Old Run Pin 老版本、旧 Worker Drain、Migration 先 Canary,并单独做 Resume Compatibility Test。


Q19:Saga 为什么适合 Agent? ​

详细答案

Agent 跨 Ticket、Cloud、Git、Email、Payment 时没有统一事务。Saga 将流程拆成 Forward Action + Compensation,例如 create resource → delete resource、merge PR → revert commit。但 Compensation 不等于真实 Rollback,不可逆动作应提高 Approval / Verification 门槛。


Q20:Checkpoint Full Snapshot 和 Delta 怎么选? ​

详细答案

Full Snapshot 简单且 Resume 快,但状态大时写放大严重;Delta 写入小,但恢复需要 Merge / Replay。常见折中是 Periodic Full Snapshot + Intermediate Delta。选择取决于 State Growth、Checkpoint QPS 和 Recovery Latency。


附录 B:正文资料脚注 ​

[^restate-architecture]: Restate, Architecture / Request Lifecycle. https://docs.restate.dev/references/architecture [^restate-retention]: Restate, Service Configuration — Retention. https://docs.restate.dev/services/configuration [^dbos]: DBOS Architecture. https://docs.dbos.dev/architecture [^dbos-queue]: DBOS Queues. https://docs.dbos.dev/python/reference/queues [^dbos-outbox]: DBOS Transactional Outbox. https://docs.dbos.dev/python/examples/outbox [^dbos-recovery]: DBOS Workflows & Steps — max recovery attempts. https://docs.dbos.dev/python/reference/decorators

[^openai-runstate]: OpenAI Agents SDK, RunState / Human-in-the-loop. https://openai.github.io/openai-agents-python/ref/run_state/ ; https://openai.github.io/openai-agents-python/human_in_the_loop/ [^openai-hitl]: OpenAI Agents SDK, Human-in-the-loop. https://openai.github.io/openai-agents-python/human_in_the_loop/ [^ms-checkpoint]: Microsoft Agent Framework, Workflows - Checkpoints. https://learn.microsoft.com/en-us/agent-framework/workflows/checkpoints [^ms-hitl]: Microsoft Agent Framework, Workflows - Human-in-the-loop. https://learn.microsoft.com/en-us/agent-framework/workflows/human-in-the-loop [^ms-workflow]: Microsoft Agent Framework, Workflow concepts. https://learn.microsoft.com/en-us/agent-framework/concepts/workflows/ [^langgraph-persistence]: LangGraph, Persistence. https://docs.langchain.com/oss/python/langgraph/persistence [^langgraph-time-travel]: LangGraph, Time travel. https://docs.langchain.com/oss/python/langgraph/use-time-travel [^langgraph-interrupt]: LangGraph, Interrupts. https://docs.langchain.com/oss/python/langgraph/interrupts [^langgraph-functional]: LangGraph, Functional API / Durable Execution. https://docs.langchain.com/oss/python/langgraph/functional-api [^temporal]: Temporal Documentation. https://docs.temporal.io/ [^dapr]: Dapr Documentation — Durable execution for workflows and AI agents. https://docs.dapr.io/ [^dapr-agent]: Dapr Agents — Why Dapr Agents / Durable Agent. https://docs.dapr.io/developing-ai/dapr-agents/dapr-agents-why/ [^dapr-agents]: Dapr Docs, Dapr Agents v1.0 — Generally Available, https://docs.dapr.io/developing-ai/dapr-agents/ [^dapr-docs]: Dapr Docs, Durable execution engine for workflows and AI agents, https://docs.dapr.io/ [^restate]: Restate Documentation. https://docs.restate.dev/

[^ms-checkpoint-storage]: Microsoft Agent Framework, Workflow Checkpoints and CheckpointStorage providers. https://learn.microsoft.com/en-us/agent-framework/workflows/checkpoints

附录 C:参考资料(截至 2026-09-13) ​

  1. OpenAI Agents SDK — RunState
    https://openai.github.io/openai-agents-python/ref/run_state/

  2. OpenAI Agents SDK — Human-in-the-loop
    https://openai.github.io/openai-agents-python/human_in_the_loop/

  3. LangGraph — Persistence
    https://docs.langchain.com/oss/python/langgraph/persistence

  4. LangGraph — Interrupts
    https://docs.langchain.com/oss/python/langgraph/interrupts

  5. LangGraph — Time Travel
    https://docs.langchain.com/oss/python/langgraph/use-time-travel

  6. LangGraph — Functional API
    https://docs.langchain.com/oss/python/langgraph/functional-api

  7. Microsoft Agent Framework — Workflow Concepts
    https://learn.microsoft.com/en-us/agent-framework/concepts/workflows/

  8. Microsoft Agent Framework — Checkpoints
    https://learn.microsoft.com/en-us/agent-framework/workflows/checkpoints

  9. Microsoft Agent Framework — Human-in-the-loop
    https://learn.microsoft.com/en-us/agent-framework/workflows/human-in-the-loop

  10. Temporal Documentation
    https://docs.temporal.io/

  11. Dapr Documentation
    https://docs.dapr.io/

  12. Dapr Agents — Durable Agent
    https://docs.dapr.io/developing-ai/dapr-agents/dapr-agents-why/

  13. Restate Documentation
    https://docs.restate.dev/

  14. DBOS Documentation
    https://docs.dbos.dev/

  15. DBOS Architecture
    https://docs.dbos.dev/architecture

  16. DBOS Queues
    https://docs.dbos.dev/python/reference/queues

  17. Restate Architecture
    https://docs.restate.dev/references/architecture

  18. Restate Retention
    https://docs.restate.dev/services/configuration