Durable Execution:长任务为什么不能只靠 while 循环
一个 Agent 能连续运行十分钟,不代表它能可靠运行十小时。
进程会升级,机器会重启,网络会超时,第三方 API 会限流,人工审批可能第二天才回来。只要任务跨越故障和等待,普通 while 循环就不再足够。
Durable Execution 解决的不是“怎样让模型更坚持”,而是:当执行环境中断以后,系统怎样从已经发生的事实继续,而且不重复造成副作用。
这是一类分布式系统问题。
一、最危险的故障窗口
Section titled “一、最危险的故障窗口”假设退款流程执行两步:
- 调用支付系统退款;
- 把任务状态写成完成。
如果第一步已经成功,进程却在第二步之前崩溃,重启后会看到“任务未完成”。它如果直接重试,可能重复退款。
反过来,如果先把任务写成完成,再调用支付系统,第二步失败时系统又会错误宣称成功。
这就是副作用与状态提交之间的故障窗口。
任何会付款、发信、建单、删文件、提交代码的 Agent 都会遇到它。
二、Durable Execution 的核心对象
Section titled “二、Durable Execution 的核心对象”Workflow
Section titled “Workflow”描述长期业务过程和状态转移。Workflow 代码应尽量确定,方便重放历史。
Activity / Step
Section titled “Activity / Step”真正访问外部世界的操作,例如调用模型、执行工具、发邮件。Activity 可以失败和重试。
Event History
Section titled “Event History”记录已发生的事件、结果、定时器和信号。恢复时,运行时依据历史重建 Workflow 状态。
Checkpoint
Section titled “Checkpoint”保存任务当前可恢复位置和必要状态。不同框架可能采用快照、事件历史或数据库事务。
Signal / Human Input
Section titled “Signal / Human Input”外部事件和人工审批可以在未来到达,唤醒暂停的 Workflow。
Retry Policy
Section titled “Retry Policy”明确哪些错误可重试、间隔、最大次数和超时。重试不是统一的“再来一次”。
三、“Exactly Once”为什么要谨慎
Section titled “三、“Exactly Once”为什么要谨慎”跨网络和外部系统时,很难简单承诺每个副作用恰好发生一次。
更常见的工程方法是:
- Workflow 状态可靠保存;
- Activity 可能至少执行一次;
- 有副作用工具使用 Idempotency Key;
- 超时后查询外部终态;
- 重复请求被外部系统去重;
- 无法去重的动作需要补偿或人工处理。
Retry safely, not blindly.能安全重试,才允许自动重试。Agent 提供的自然语言总结不能填补故障窗口。幂等和状态查询必须写进工具契约。
四、Temporal 的思路
Section titled “四、Temporal 的思路”Temporal 将长期过程写成 Workflow,把外部副作用放进 Activity。平台持久化事件历史,Worker 崩溃后可以重新执行 Workflow 逻辑并恢复到一致状态。[1]
Workflow 重放要求确定性:同一历史应得到同样控制结果。因此模型调用、随机数、当前时间和网络访问通常不能随意写在 Workflow 逻辑里,而应封装为 Activity 或受控 API。
这与 Agent 结合时很自然:
Durable Workflow:决定生命周期、等待、重试和补偿Agent Activity:执行一次模型决策或开放任务Tool Activity:执行外部副作用模型可以非确定,Workflow 的恢复语义仍然明确。
五、DBOS 的数据库路线
Section titled “五、DBOS 的数据库路线”DBOS 使用数据库支持 Durable Workflow 与事务式执行,强调把持久化和应用状态放在熟悉的数据基础设施中。[2]
它与 Temporal 的实现路线不同,但解决的核心问题相近:任务不能因为进程故障丢失,已经完成的步骤需要被记住。
选择时要看团队基础设施、语言、运维和事务需求,而不是只看 API 是否简短。
六、Agent 框架里的持久化
Section titled “六、Agent 框架里的持久化”LangGraph 提供 Checkpoint、Interrupt、Time Travel 等能力,使图运行可以暂停、恢复和检查。[3]
PydanticAI 支持与 Temporal、DBOS、Prefect 等 Durable Execution 方案结合。[4]
Google ADK、Microsoft Agent Framework 也提供 Session、Workflow 和状态能力。框架内持久化适合保存 Agent 状态,外部 Durable Runtime 更擅长跨服务、定时器和长期业务事务。
两者可能同时使用。关键是避免双重权威:谁拥有 Workflow 生命周期,谁只是保存 Agent 节点状态,必须写清楚。
七、人工审批是长任务,不是弹窗装饰
Section titled “七、人工审批是长任务,不是弹窗装饰”很多 Agent Demo 显示一个“Approve”按钮,却没有处理:
- 用户隔夜才点击;
- 审批前资源状态已变化;
- 同一动作被批准两次;
- 审批者身份和范围;
- 用户拒绝后怎样补偿;
- 请求超时后怎样结束。
真正的 Human-in-the-loop 需要一个持久化等待状态。恢复时还要重新校验环境,而不是执行昨天生成的旧参数。
approval grants permission;it does not freeze the world.批准给予权限,不会让外部世界停止变化。
八、Checkpoint 应保存什么
Section titled “八、Checkpoint 应保存什么”一份可恢复状态通常包含:
{ "run_id": "run_demo", "workflow_version": 3, "current_step": "awaiting_approval", "goal": "refund order_demo", "artifacts": ["policy-check.json"], "pending_action": { "tool": "refund", "arguments_hash": "...", "idempotency_key": "refund-order_demo" }, "budget": {"attempts_remaining": 2}, "last_evidence_version": "order-state-18"}不要把完整 Secret 和无关上下文写入 Checkpoint。恢复需要的是事实、引用和安全凭据句柄。
九、Workflow 升级为什么麻烦
Section titled “九、Workflow 升级为什么麻烦”长任务运行期间,代码可能从 v1 升到 v2。新代码删除了旧节点,正在等待的任务该从哪里继续?
Durable 系统需要版本兼容策略:
- 保留旧 Workflow 代码直到旧 Run 完成;
- 在历史中记录版本分支;
- 对状态执行显式迁移;
- 新旧 Worker 分流;
- 无法迁移时暂停并人工处理。
Agent Prompt、Tool Schema 和验证规则同样属于版本。只迁移状态结构,不记录行为版本,仍然无法解释恢复后的差异。
十、CI Sweeper 为什么需要持久化
Section titled “十、CI Sweeper 为什么需要持久化”旧稿的 CI Sweeper 是一个很好的长任务案例:CI 失败触发,Agent 在隔离 Worktree 中修复,Verifier 跑测试,随后等待人工审查。[5]

图 1:CI Sweeper starter 把触发、状态和适配文件外置。来源见文末。

图 2:CI 事件负责交付事实,不应直接把“失败”解释成“必须自动修复”。来源见文末。
这个 Loop 可能跨多个 CI Run 和人工审查。若状态只存在聊天里,重复触发、证据过期和并发修复很难避免。
十一、真实实验:副作用以后崩溃,恢复时不重复
Section titled “十一、真实实验:副作用以后崩溃,恢复时不重复”本讲的 durable_checkpoint.py 模拟最危险的窗口。
第一次运行:
- 写入 Checkpoint;
- 执行
refund-order-demo副作用; - 在完成状态提交前模拟进程崩溃。
恢复以后,脚本再次请求同一动作。因为使用相同 Idempotency Key,结果为 deduplicated,副作用列表仍然只有一项。
{ "side_effects": ["refund-order-demo"], "events": [ {"phase": "first_run", "effect": "created"}, {"phase": "crash"}, {"phase": "resume", "effect": "deduplicated"} ]}完整结果与 Checkpoint 见 experiment-result.json。
实验是文件级模拟,不具备真实数据库事务,却清楚展示了 Durable Agent 的基本原则:恢复不是重做全部步骤,而是根据历史安全地继续。
十二、长任务检查表
Section titled “十二、长任务检查表”- 进程崩溃后任务会不会丢;
- 外部副作用是否幂等;
- 超时后能否查询终态;
- Checkpoint 是否包含版本;
- 人工审批能否隔夜恢复;
- 取消和补偿是否明确;
- 重试是否按错误分类;
- 同一目标是否有锁或租约;
- Workflow 升级是否兼容在途任务;
- Trace 是否跨越多次 Worker 执行。
十三、这一讲的结论
Section titled “十三、这一讲的结论”长时 Agent 的可靠性,来自持久化历史、幂等副作用、可恢复状态和明确的版本,不来自模型“记得继续”。
while True 可以表达循环,不能替系统承担故障。
下一讲进入最具行动感、也最危险的环境:浏览器、终端和桌面。Computer Use 与 Coding Agent 为什么必须和沙箱、权限及终态验证一起设计?
[1] Temporal, Durable Execution. https://docs.temporal.io/
[2] DBOS, Durable Workflows. https://docs.dbos.dev/
[3] LangChain, LangGraph Persistence. https://docs.langchain.com/oss/python/langgraph/persistence
[4] PydanticAI, Durable Execution. https://pydantic.dev/docs/ai/integrations/durable_execution/overview/
[5] cobusgreyling, CI Sweeper. https://github.com/cobusgreyling/loop-engineering/tree/main/starters/ci-sweeper