Agents retry. Queues retry. Tool calls time out. Without idempotency, the same agent decision can send two emails. Idempotent sending makes the intended email outcome happen once, even when the system tries more than once.
last updated 2026-05-074 sections
section 01
Why duplicates happen
Duplicate sends usually come from partial failure. The provider accepts the email, but the agent runtime times out before recording the result. The queue retries, the tool call runs again, and the recipient receives the same message twice.
failure point
symptom
control
Provider accepted send, app timed out.
Same content sent twice.
Provider idempotency key or local send ledger.
Queue retried after worker crash.
Second worker repeats the tool call.
Unique job key and atomic status transition.
Model run restarted.
Agent recreates the same email.
Deterministic action ID from source event and recipient.
Webhook replayed.
Inbound event triggers another outbound reply.
Inbound event dedupe before action generation.
section 02
Idempotency key design
A good key identifies the intended action, not the specific attempt. Build it from stable fields such as tenant ID, source event ID, recipient, action type, and template or content hash. Do not use a random UUID generated inside the retrying worker.
field
why it belongs
tenant_id
Prevents cross-tenant collisions.
source_event_id
Ties the email to the inbound message or product event.
recipient
Keeps one action per intended recipient.
action_type
Separates reply, escalation, invite, and receipt sends.
content_hash or template_id
Distinguishes materially different messages from the same event.
section 03
Provider support
Some email APIs support idempotency keys directly. When a provider does not, the application should keep a send ledger with a unique constraint on the idempotency key, a pending state, provider response, and final message ID.
okPrefer provider idempotency keys where available.
okCreate a send ledger before calling the provider.
okUse a database unique constraint on the idempotency key.
okRecord provider request ID and message ID.
okReturn the original result when a retry finds an existing completed send.
okRequire manual review for ambiguous pending sends after timeout.
section 04
Agent-specific guardrails
Agent systems should separate decision idempotency from email idempotency. The same inbound event may produce a support ticket, a CRM update, and an email reply. Each tool action needs its own stable key and audit trail.