How do I prevent duplicate sends?
AI agents can sometimes retry requests due to network errors, timeouts, or logic bugs. Without safeguards, this can cause the same email to be sent multiple times. Here is how to prevent that.
Idempotent resource creation with client_id
AgentMail supports idempotency for all create operations via the clientId parameter. When you provide a clientId, AgentMail checks if a resource with that ID already exists. If it does, it returns the existing resource instead of creating a duplicate.
This works for creating inboxes, pods, webhooks, and drafts:
Preventing duplicate email sends
The clientId parameter is for resource creation, not for messages.send. Sends are made idempotent with an Idempotency-Key HTTP header instead.
Pass a unique key per logical send. A retry carrying the same key returns the original message and sends no second email; reusing a key with a different request (different content, inbox, or endpoint) returns 409 Conflict. Keys expire 24 hours after the send completes.
See the Idempotent Requests guide for the full semantics. The application-side patterns below still help when you want to dedupe on your own business state (e.g. “have I already replied to this thread?”).
Track sent messages with labels
Use labels to mark messages that your agent has already processed, so it does not reply twice:
Use drafts for critical sends
For high-stakes emails, use drafts instead of sending directly. Create a draft, verify it has not been sent already, then send:
Since drafts support clientId, creating the same draft multiple times is safe. And once a draft is sent, it is deleted, so calling drafts.send again will fail rather than send a duplicate.
Best practices
- Use an
Idempotency-Keyheader on sends (messages.send, replies, forwards,drafts.send) so retries never duplicate an email - Use
clientIdon all create operations (inboxes, pods, webhooks, drafts) to make them safe to retry - Generate
clientIdfrom your business logic (e.g.,order-${orderId}-confirmation), not random UUIDs - Track state with labels to prevent your agent from processing the same message twice
- Use drafts for critical sends where duplicates would be harmful
For more details, see the Idempotent Requests guide.
