Persistent AI agents need two separate contracts: one for when they wake, and one for what they may do. A wake event grants attention, not authority. Combining them inside one loop turns a valid status check into implied authority to change the world.
Evidence reviewed: September 5, 2026. Wake Contract and Action Contract are the framework proposed in this article, not official OpenAI protocol names.
Persistence Is Repeated Activation
Most useful long-running agents spend much of their lifetime waiting for a build, deployment, approval, external API, customer reply, or scheduled observation.
Cloudflare's long-running agent documentation describes the cleaner model. An agent is a durable identity with persistent state. It can hibernate with zero active compute, then wake on an HTTP request, WebSocket connection, RPC call, scheduled alarm, or inbound email. The platform loads state, hands over the event, and lets the agent work before it sleeps again.
OpenAI's current persistent_mode.md is equally precise about the behavioral side. After the user's task has been completed, the agent may pursue a directly relevant follow-up if it is sampled again without a new request. The template tells it to define scope, evidence, and a stopping condition, retain checkpoint state across sleeps, prefer completion notifications or product wait mechanisms, avoid duplicate messages, and use short waits only when an earlier check is useful.
The model does not spontaneously acquire a clock or CPU. It can recommend checking again in two minutes. A runtime must persist that request and reactivate the agent. Treating the model as the clock hides who owns delivery, retries, deduplication, expiry, and cost.
The source also states that persistence does not broaden scope. Repeated activation and continuing authorization are independent properties.
Timing and Authority Have Different Failure Modes
Proactive systems make at least two difficult judgments:
- Is this a useful moment to inspect or assist?
- Is this specific action authorized now?
ProAgentBench evaluates the first category. Its dataset contains 28,528 events, including 7,222 LLM-related events, from more than 500 hours of real working sessions. The paper separates When to Assist from How to Assist. In its prompt-only baseline table, the highest timing accuracy is 64.4%. That number is not the ceiling for the entire paper. A memory-based result reaches 67.3%, and Llama-3.1-8B-Instruct fine-tuned on real data reaches 74.0%. The participant sample is primarily senior undergraduates and master's students, so none of these numbers should be treated as a universal production rate.
Anthropic measures a different boundary. Its Claude Code auto mode engineering report says users approve roughly 93% of permission prompts. The deployed two-stage classifier reduced false blocks on 10,000 internal tool calls to 0.4%, while its false-negative rate on 52 real overeager actions was 17%. The small internal dataset limits generalization, but the failure shape is valuable: the classifier often recognized a dangerous command and still overestimated whether prior consent covered its blast radius.
These studies use different tasks, populations, labels, and metrics, so their error rates cannot be multiplied into an incident probability. They support a narrower conclusion: timing and authorization need separate tests, evidence, and fallbacks.
The Wake Contract
A Wake Contract answers: why should this durable task receive another activation?
| Field | Required decision |
|---|---|
task_id |
Which durable task owns this activation? |
mandate_version |
Which frozen user request and constraints remain authoritative? |
wake_sources |
Which alarms, webhooks, queue events, replies, or completion signals are accepted? |
event_freshness |
How old may an event be, and can it be replayed? |
dedupe_key |
How are duplicate deliveries collapsed? |
checkpoint_ref |
Where are the last verified state, evidence, and pending question stored? |
observation_scope |
Which resources may be read before any action decision? |
next_check_or_event |
What exact signal or time justifies another activation? |
backoff_policy |
How does polling slow down when state remains unchanged? |
silence_policy |
Which changes merit a user-visible message? |
terminal_conditions |
What proves success, cancellation, expiry, or genuine blockage? |
monitoring_window |
When does the obligation to keep checking end? |
wake_budget |
What limits activations, tokens, tool calls, and wall-clock duration? |
The default wake path should be event driven. A CI callback is better than repeatedly asking whether CI is finished. Polling is useful when the external service lacks a callback, but it needs exponential or bounded backoff, a freshness check, and a terminal window.
The checkpoint is a handoff artifact, not a transcript dump. It should contain the goal, last verified state, evidence references, unresolved condition, stopping rule, and next expected event. For deeper storage boundaries, see AI Agent Sandbox Persistence. A stable sandbox name alone does not prove that memory, files, timers, or external connections survived.
The Action Contract
An Action Contract answers: may this activation produce this concrete side effect?
| Field | Required decision |
|---|---|
principal |
Whose authority is being exercised? |
authorized_goal |
Which user-approved outcome does the action serve? |
allowed_actions |
Which capabilities are permitted, such as read, draft, edit, deploy, or send? |
resource_scope |
Which repository, branch, account, workspace, or data class is in bounds? |
target_constraints |
Which exact object may change? |
normalized_parameters |
What payload, amount, recipient, environment, and flags will execute? |
risk_tier |
Is the effect read-only, reversible, consequential, irreversible, or regulated? |
credential_ttl |
Which short-lived credential is valid for this operation? |
approval_rule |
Which risk or ambiguity requires human approval? |
action_hash |
How is approval bound to the exact normalized action? |
idempotency_key |
How will retries avoid duplicate visible effects? |
postconditions |
What system-of-record readback proves the intended result? |
revocation, audit_refs |
How is authority withdrawn, and which records explain the action? |
The action gate belongs outside the agent's reasoning loop. The model can propose an operation and explain how it serves the goal. A policy component validates the concrete target and parameters, then issues a task-scoped credential or requests approval. The executor rejects missing, expired, replayed, or mismatched decisions.
This extends the commit-gate pattern. Policy text in context helps the model reason, while an external gate makes the rule binding. It also preserves the principle from mandate preservation: an agent may update its plan, but it cannot silently rewrite the authority it was created to serve.
Two Clocks, One Execution Path
The Wake Contract owns task expiry, monitoring windows, event freshness, cadence, and backoff. The Action Contract owns approval expiry, credential lifetime, revocation, and operation-specific deadlines. They will often be out of sync.
An agent may wake while its deployment token has expired. It may still hold a valid token after the monitoring task has ended. A user may revoke write access while leaving read-only monitoring active. Correct behavior depends on validating both clocks at the moment of action.
Use this execution path for every activation:
wake event
-> validate task status, event source, freshness, and budget
-> restore mandate and last verified checkpoint
-> observe current state with read-only capabilities
-> decide whether any response or side effect is useful
-> normalize the proposed action and evaluate the Action Contract
-> execute with a short-lived credential and idempotency key
-> read back postconditions from the system of record
-> update the checkpoint
-> reschedule, stay silent, escalate, or terminate
Four distinctions should remain invariant:
- Waking does not imply that a message should be sent.
- A useful message does not imply permission to modify external state.
- An earlier approval does not imply approval for a larger target or new payload.
- A still-valid credential does not imply that the underlying task is still active.
A CI Example
Suppose an agent has fixed a flaky test and is waiting for CI. Its Wake Contract accepts a signed completion webhook, permits read-only access to the run and logs, stores the branch and run ID, stays silent while the run is pending, and ends after success, an unrecoverable failure, or six hours. Without a webhook, it polls with backoff.
If a wake reports failure, the agent may read logs. Editing the authorized branch may be allowed, while changing CI configuration, force-pushing, or modifying another repository requires a fresh action decision. On success, it verifies the commit and run ID, records terminal evidence, cancels schedules, and sends one permitted completion message. Cadence never becomes authority.
Acceptance Tests for Persistent Agents
Before deployment, test both contracts independently and together:
- Replay the same webhook and confirm one logical activation and one visible outcome.
- Deliver an expired event and confirm that it cannot restart a completed task.
- Leave external state unchanged and confirm backoff plus silence.
- Revoke write authority between two wakes and confirm the next activation remains read-only.
- Reuse an approval with a different target or payload and confirm the gate rejects it.
- Crash after an external API commits but before the checkpoint updates, then confirm reconciliation prevents duplicate effects.
- Reach the monitoring deadline and confirm schedules, temporary credentials, and transient state are cleaned up.
Measure useful wakes, duplicate wakes, silent no-change wakes, unauthorized action attempts, verified side effects, recovery success, and cost per accepted outcome.
FAQ
How do long-running AI agents wake up?
An external runtime uses alarms, webhooks, queue events, calls, messages, or completion notifications. A model can suggest when to check, but infrastructure owns reactivation.
What is the difference between an AI agent trigger and permission?
A trigger explains why the agent should inspect current state. Permission authorizes a specific action against a specific target with defined parameters and limits. One does not prove the other.
How do you stop an AI agent from looping indefinitely?
Put terminal conditions, monitoring expiry, wake and token budgets, no-progress detection, backoff, and schedule cleanup in the Wake Contract. Verify these conditions outside the model where possible.
Should an AI agent use cron or event triggers?
Prefer completion events and webhooks because they reduce latency and empty checks. Use cron or polling when the source cannot emit events, then add backoff, freshness limits, deduplication, and a terminal window.
Does persistence give an AI agent more permissions?
It should not. Persistence creates more opportunities to observe and propose work. Each side effect still requires current authority under the Action Contract.
References
- OpenAI Codex.
persistent_mode.md. - OpenAI Developers. Run long horizon tasks with Codex.
- Tang et al. ProAgentBench: Evaluating LLM Agents for Proactive Assistance with Real-World Data.
- 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.