AI agents frequently perform external side effects: send an email, publish a post, create a ticket, call a webhook or initiate a payment. These actions are vulnerable to a classic distributed-systems problem. The agent may persist its internal state and then crash before the external call, or complete the external call and crash before recording success. Retrying blindly can create duplicates.

Persist intent before delivery

The outbox pattern writes the intended external action into durable storage in the same transaction as the agent’s workflow state. A separate dispatcher later sends the action to the external service.

This creates a clear record that the workflow committed to the action even if the process dies before the network request begins.

Give every action an idempotency key

The outbox item should carry a stable operation ID that the external integration or adapter uses during retries. If the same item is delivered twice, the receiver can recognize it as one logical action.

Where the external API lacks native idempotency support, the adapter may need a local deduplication table or post-send verification step.

Separate planned from delivered state

An agent should not mark an email “sent” merely because it generated the content. The outbox can represent queued, delivering, delivered, failed and uncertain states explicitly.

Uncertain is important when the network times out after the remote system may have accepted the request. The recovery path should query status before sending again whenever the provider allows it.

Keep payloads bounded and reviewable

Persist the exact parameters needed for the action rather than a vague instruction asking the model to reconstruct them later. Recipient, content version, amount and destination should be stable once the action enters the outbox.

If a material parameter changes, create a new action and retire the old one. This makes approval and audit records line up with what was actually delivered.

Use retry policy by error type

Temporary rate limits and network failures can retry automatically with backoff. Invalid credentials, policy rejection or malformed parameters should stop and route to repair instead of looping.

Retry count, age and last error should be visible to operators so a stuck outbox does not become an invisible backlog of intended side effects.

Connect outbox state to deterministic checkpoints

When an agent resumes after a crash, it can inspect the outbox and know which actions are committed, delivered or unresolved rather than reasoning from chat history.

Our article on deterministic agent checkpoints explains the workflow-state side. The outbox provides the corresponding guarantee for external side effects.

Reliable agents need a boundary between deciding to act and successfully causing the real-world effect. A durable outbox, stable operation identity and explicit delivery states make retries predictable and keep a transient worker failure from turning one user instruction into several emails, payments or records.

The outbox also creates a clean place for policy checks that must happen immediately before delivery. An action may have been planned minutes earlier, but account permissions, approval status or external context can change while it waits in the queue. Revalidating those conditions at dispatch prevents a durable queued action from becoming a stale command that executes after its authority has disappeared. This is particularly important for scheduled agents: persistence should guarantee that valid work is not lost, not guarantee that an outdated decision will execute regardless of what changed afterward.

The outbox also creates a clean place for policy checks that must happen immediately before delivery. An action may have been planned minutes earlier, but account permissions, approval status or external context can change while it waits in the queue. Revalidating those conditions at dispatch prevents a durable queued action from becoming a stale command that executes after its authority has disappeared. This is particularly important for scheduled agents: persistence should guarantee that valid work is not lost, not guarantee that an outdated decision will execute regardless of what changed afterward.

The outbox also creates a clean place for policy checks that must happen immediately before delivery. An action may have been planned minutes earlier, but account permissions, approval status or external context can change while it waits in the queue. Revalidating those conditions at dispatch prevents a durable queued action from becoming a stale command that executes after its authority has disappeared. This is particularly important for scheduled agents: persistence should guarantee that valid work is not lost, not guarantee that an outdated decision will execute regardless of what changed afterward.