长程后台 Agent:持久执行 本节摘要:生产级长程 Agent 不在 里跑。每一次 LLM 调用都变成一个带检查点、重试、重放(replay)的活动(activity)。Temporal 与 OpenAI Agents SDK 的集成在 2026 年 3 月 GA;Claude Code Routines(Anthropic)无需持久本地进程就能跑定时 Claude Code 调用。会话可在人工输入上暂停、跨部署存活、按 从最近检查点恢复。新工效背后是一个老模式——工作流编排——只有一个新输入:LLM 调用作为非确定性活动,恢复时必须确定性重放。
本节摘要:生产级长程 Agent 不在
while True里跑。每一次 LLM 调用都变成一个带检查点、重试、重放(replay)的活动(activity)。Temporal 与 OpenAI Agents SDK 的集成在 2026 年 3 月 GA;Claude Code Routines(Anthropic)无需持久本地进程就能跑定时 Claude Code 调用。会话可在人工输入上暂停、跨部署存活、按thread_id从最近检查点恢复。新工效背后是一个老模式——工作流编排——只有一个新输入:LLM 调用作为非确定性活动,恢复时必须确定性重放。本节讲透活动/工作流/事件日志/重放四件套、LLM 调用为何天然契合活动画像、按thread_id键的检查点与后端选型(PostgreSQL/SQLite/Redis/Durable Objects)、把人工输入当作一等状态,以及一个反复出现的主题:METR 观察到的「35 分钟退化」——持久执行不修复可靠性衰减,而是让你跑得比可靠性画像支持的更久,设计对了是新式的安全失败,设计错了是不安全失败。
对应原课程:Phase 15 · Lesson 12 ·
durable-execution(原英文phases/15-autonomous-systems/12-durable-execution/docs/en.md)。
阅读完本节,你应当能够:
thread_id 键的检查点 API 形态,以及 PostgreSQL / SQLite / Redis / Cloudflare Durable Objects 各自的取舍。设想一个跑四小时的 Agent:调三个工具、提示用户两次、做四十次 LLM 调用。跑到一半,宿主机重启。会发生什么?
while True 循环:一切丢失。运行从头开始。三个工具调用(带真实副作用)再执行一次。用户被再问一遍已经批准的事。四十次 LLM 调用重新计费。这是工作流引擎(Temporal、Cadence、Uber Cherami)出货十年的同一模式。新东西是:LLM 调用现在是一类活动——非确定、昂贵、带副作用——它干净地套进这个模式。
💡 本节反复主题:METR 观察到「35 分钟退化」——成功率随跨度大致平方下降。持久执行让你跑得比可靠性画像支持的更长;设计对了是新的安全失败方式,设计错了是不安全失败方式。
原课程 code/main.py 用标准库实现一个最小持久执行引擎:@activity 装饰器把输入输出记到 JSON 事件日志;一个工作流函数串起活动;run_or_replay(workflow, event_log) 重放已完成活动而不重新执行。驱动器模拟一个三活动工作流,在中途崩溃,展示 (a) 朴素重试重新执行一切 vs (b) 重放只跑缺失活动。
def activity(fn): def wrapped(ctx, *args): key = (fn.__name__, serialize(args)) if key in ctx.log: # 已完成 -> 重放,不重执行 return ctx.log[key].output ctx.log.record_start(key, args) out = fn(*args) # 真执行(非确定: LLM/工具/网络) ctx.log.record_complete(key, out) return out return wrapped def run_or_replay(workflow, event_log, thread_id): ctx = Context(log=event_log, thread_id=thread_id) return workflow(ctx) # 工作流代码必须确定性
这与 React 对虚拟 DOM 重渲染、或 Git 从 commit 重建工作树同形。编排器的确定性是让持久性便宜的关键。
LLM 调用是:非确定(temperature>0;即便 temperature=0 也跨模型版本漂移)、昂贵(钱与延迟)、可能失败(限速、超时)、带副作用(若调工具)。这正是活动画像。把每个 LLM 调用包成活动,你就得到了指数退避重试、跨重启检查点、可重放调试轨迹。
thread_id 键的检查点LangGraph、Microsoft Agent Framework、Cloudflare Durable Objects、Claude Code Routines 都收敛到同一 API 形态:一个 thread_id(或等价物)标识会话;每个状态转换持久到后端(PostgreSQL 默认,SQLite 用于开发,Redis 用于缓存);恢复读最新检查点。
后端选择要紧:
Propose-Then-Commit(第 15 节)要求一个持久的「等人」状态。工作流暂停,外部队列持挂起请求,批准从恰好那一点恢复。没有持久性这是 best-effort;有了它,隔夜批准到达,工作流早上续上。
METR 观察到,测过的每个 Agent 类别在连续运行超过约 35 分钟后都出现可靠性衰减:任务时长翻倍,失败率大致翻四倍。持久执行不修复这个;它让你跑得比可靠性画像支持的更长。安全模式是把持久性与「重进入需新 HITL」的检查点、以及「不论墙钟时间封顶总算力」的预算 kill switch(第 13 节)结合。
| 后端 | 持久 | 适合 | 风险 |
|---|---|---|---|
| PostgreSQL | 强 | 生产默认(LangGraph) | 需运维 |
| SQLite | 弱 | 本地开发 | 跨主机丢数据 |
| Redis(无 AOF) | 弱 | 缓存 | 瞬态 |
| Cloudflare Durable Objects | 强 | 分布式长程 | 供应商锁定 |
| Temporal | 强 | 企业工作流 | 重基础设施 |
⚠️ 关键认知:持久执行让运行更长,但不让运行更可靠。它必须配「重进入需新 HITL」与「预算 kill switch」,否则它放大的是失败窗口,不是成功概率。
outputs/skill-durable-execution-review.md 审查一个拟部署的长程 Agent 是否有正确的持久执行形态:活动是否包住所有非确定步骤、编排器是否确定性、检查点后端是否合适、有没有持久的「等人」状态、恢复时的 HITL 策略。
code/main.py 把崩溃点做成可调,适合演示「崩溃点变,重放的活动数跟着变」——给团队建立「重放只跑未完成」的直觉。
跑 code/main.py:观察朴素重试与重放的活动执行数差异。改崩溃点,展示重放数相应变化。
把玩具引擎显式用 thread_id:模拟两个并发会话共享引擎,确认它们的事件日志不冲突。
在玩具引擎的一个活动里引入非确定性(工作流决策里的墙钟时间戳),演示重放时的分歧。解释真实引擎如何处理(副作用注册、Workflow.now() API)。
读 LangChain「Runtime behind production deep agents」,列出运行时持久化的每个状态,说出每个覆盖哪种失败模式。
为一个 6 小时自主编码任务设计检查点策略:在哪检查?崩溃恢复长什么样?什么需要新 HITL?
thread_id 键检查点是行业收敛形态:后端 PostgreSQL(默认)/SQLite(开发)/Redis(缓存)/Durable Objects(分布式)。下一节,我们处理长程运行的成本维度——动作预算、迭代上限与成本治理,看如何在墙钟时间之外封顶总算力开销。