持久 Agent 需要两份独立合同:一份决定什么时候醒,另一份决定醒来后能做什么。一次唤醒只授予观察机会,不授予副作用权限。把这两个判断塞进同一个自治循环,会让合理的状态检查被误读成持续有效的行动授权。
证据核验时间:2026 年 9 月 5 日。Wake Contract 与 Action Contract 是本文提出的架构框架,不是 OpenAI 的官方协议名称。
持久运行首先是一组离散激活
Cloudflare 的长运行 Agent 文档给出明确模型:Agent 是带持久状态的身份;HTTP、RPC、定时 alarm 或邮件到达后,平台唤醒它、加载状态并交付事件,处理完再休眠。
OpenAI 源码中的 persistent_mode.md写的是 if you are sampled again。模型可以建议检查时间,scheduler、wait 机制或完成事件负责再次采样。源码还要求保存检查点、保持静默、优先使用完成通知,并明确持久性不扩大授权范围。
闹钟属于运行时,任务边界属于用户委托。两者需要分别验收。
时机判断与授权判断会以不同方式出错
ProAgentBench把主动协助拆成时机与内容。数据集含 28,528 个事件,其中 7,222 个与 LLM 有关,覆盖 500 小时以上会话。纯提示法基线最高为 64.4%,记忆方法达到 67.3%,真实数据微调达到 74.0%。样本以学生为主,不能直接外推。
Anthropic 的 Claude Code auto mode 工程报告显示,内部用户批准约 93% 的权限提示。分类器在 10,000 条内部工具调用上的误阻率为 0.4%,在 52 条真实过度行动上的漏检率为 17%。后者样本很小,典型错误是高估已有同意的范围。
两组数据来自不同任务,不能相乘为事故概率。何时介入与能否行动需要两套测试、证据和失败出口。
第一份合同:Wake Contract
Wake Contract 回答本次激活为何合理。最小清单如下:
| 字段 | 要回答的问题 |
|---|---|
task_id、mandate_version |
哪个任务、哪版用户委托仍有效? |
wake_sources |
接受哪些 alarm、webhook、队列事件、回复或完成信号? |
event_freshness、dedupe_key |
事件多久过期,重复投递如何合并? |
checkpoint_ref |
最近一次已验证状态、证据和待决条件保存在哪里? |
observation_scope |
行动判断前允许读取哪些资源? |
next_check_or_event |
什么信号或时间点值得再次激活? |
backoff_policy |
状态不变时怎样降低轮询频率? |
silence_policy |
哪些变化值得通知用户? |
terminal_conditions |
成功、取消、过期和阻塞怎样判定? |
monitoring_window、wake_budget |
何时结束,最多消耗多少次唤醒和调用? |
优先使用完成通知或 webhook,其次是确定性 schedule,最后才是带退避的轮询。检查点保存目标、状态、证据、停止规则和下一事件。Agent Sandbox 状态模型解释了不同持久层。
第二份合同:Action Contract
Action Contract 回答本次激活提出的具体副作用能否执行:
| 字段 | 要回答的问题 |
|---|---|
principal、authorized_goal |
使用谁的权限,服务哪项已批准目标? |
allowed_actions |
允许读取、起草、编辑、部署、发送中的哪些能力? |
resource_scope、target_constraints |
哪个仓库、分支、账号或对象在范围内? |
normalized_parameters |
收件人、金额、环境、参数和开关的最终值是什么? |
risk_tier |
动作属于只读、可逆写入、高影响、不可逆或受监管哪一级? |
credential_ttl |
哪个短期凭据只服务本次任务? |
approval_rule、action_hash |
谁需批准,怎样绑定到精确动作? |
idempotency_key |
重试怎样避免重复付款、部署或发信? |
postconditions |
从哪个事实源读回结果,证明业务状态已经成立? |
revocation、audit_refs |
如何撤销授权并追溯动作? |
行动门应放在模型外。策略组件判断动作并签发短期凭据或请求批准。执行器拒绝过期、重放或参数不匹配的决策。
这与提交门控采用同一原则:上下文帮助推理,外部 gate 强制执行。它也继承委托保持的边界:Agent 可以调整计划,用户授权只能由有权主体修改。
两套时钟,一条执行路径
Wake Contract 管事件新鲜度、监控窗口、节奏和任务过期。Action Contract 管批准期限、凭据有效期和撤销状态。两套时钟经常不同步。
Agent 醒来时凭据可能已过期;凭据有效时任务也可能已结束。每次行动前都要重新校验两份合同。
收到 wake event
-> 校验任务状态、事件来源、新鲜度和预算
-> 恢复用户委托与最近检查点
-> 只读观察当前状态
-> 生成具体行动提案
-> 用最新参数校验 Action Contract
-> 使用短期凭据与幂等键执行一次
-> 从事实源读回并验证结果
-> 更新检查点
-> 重新调度、保持静默、升级或结束
四条不变量应写进测试:醒来不等于发消息;发消息不等于可修改;此前获批不等于新目标获批;凭据有效不等于任务有效。
用 CI 场景验收两份合同
Agent 修完偶发失败的测试后等待 CI。Wake Contract 只接受正确 run ID 的完成事件,允许只读查看流水线和日志,pending 时保持静默,六小时后结束。没有 webhook 时才按退避策略轮询。
失败事件到达后,Agent 可以读日志。编辑原授权分支可能获准,修改 CI 配置、强推或改动其他仓库需要新的动作判断。检查全绿后,它核对 commit 与 run ID,保存终态证据,取消 schedule,再发送一次获准的完成通知。
上线前的可执行检查
- 重放同一 webhook,确认只产生一次逻辑激活和一次可见结果。
- 投递过期事件,确认已结束任务不会复活。
- 外部状态长期不变,确认 Agent 退避并保持静默。
- 两次唤醒之间撤销写权限,确认下一次只能只读观察和升级。
- 将旧批准换成新目标或新参数,确认 action gate 拒绝。
- 外部 API 已提交但检查点未更新时制造崩溃,确认对账与幂等可阻止重复副作用。
- 监控结束后,确认 schedule、临时凭据和临时状态全部清理。
常见问题
长运行 Agent 怎样醒来?
运行时通过 alarm、webhook、队列或工作流事件、HTTP/RPC、消息和完成通知唤醒。模型可以建议下次检查时间,基础设施负责真正的再次激活。
Trigger 与 Permission 有什么区别?
Trigger 说明现在值得检查状态。Permission 允许针对具体对象、参数和期限执行具体动作。前者不能充当后者的证据。
怎样防止 Agent 无限循环?
在 Wake Contract 中写明停止条件、监控期限、唤醒与 token 预算、无进展阈值、退避和 schedule 清理,并尽量用模型外检查强制执行。
应该用 cron 还是事件触发?
完成事件和 webhook 可以减少空检查与延迟,应当优先。来源无法发出事件时再使用 cron 或轮询,并补齐退避、过期、去重和终止窗口。
持久运行会扩大 Agent 权限吗?
合理设计下不会。持久性增加观察与提出建议的机会,每个外部副作用仍要通过当前 Action Contract。
参考资料
- OpenAI Codex:
persistent_mode.md - OpenAI Developers:Run long horizon tasks with Codex
- Tang 等:ProAgentBench
- Anthropic:How we built Claude Code auto mode
- Anthropic:How we contain Claude across products
- Cloudflare:Long-running agents
- Auth0:Why AI Agents Need Their Own Permission Model