How do I stop an AI agent sending the same email in a loop?
An agent that retries or re-runs can email the same person again and again. The fix is not a better prompt; it is sending through something that refuses the repeat.
Direct answer. Put the guard below the agent, not inside it. Let the agent build and launch the work, and let something it cannot argue with do the sending: a system that enrolls each person once, sends each step once, applies daily caps the agent cannot change, and has a stop a person can reach. A rule in the prompt is a request. A guard in the sending path is a refusal.
Agents repeat themselves for ordinary reasons. A call times out and the agent retries it. A scheduled run wakes up with no memory of yesterday and does the same job again. A second script holds a copy of the same credential. None of that is the model misbehaving; it is how automation fails. The damage is what the recipient sees: the same message, again and again, and a complaint rate that moves the way it would for a bad list.
Key takeaways
- Do not give the agent a raw sending credential. Give it tools that write campaigns, and let a scheduler send.
- Deduplicate at the point of sending. One enrollment per person per campaign, one send per sequence step, enforced where the send happens.
- Turn on cross-campaign exclusion yourself. Keeping the same person out of two campaigns is a setting, and it is off until you switch it on.
- Send an idempotency key with every write, so a retry is recognised as the same request.
- Know where the stop is before you need it. Pausing a campaign halts its scheduled sends; pausing your mailboxes stops every campaign they send for.
- Mail your app sends when an agent triggers it needs its own guard: a transactional email API that refuses repeats and holds them for a person.
Why an agent sends the same email twice
Most repeat sends come from four places, and only one of them involves the model making a bad decision:
- Retries. A request times out, the agent cannot tell whether it went through, and it sends again. This is the most common cause, and the most innocent.
- Re-runs without memory. An agent on a schedule starts fresh each time. If it does not check what already happened, "email everyone who signed up this week" runs again tomorrow for the same people.
- More than one sender. Two agents, or an agent and a script, holding the same credential. Each is careful on its own; together they double every send.
- A trigger that keeps firing. An alert or a detector that decides the same condition is still true and sends the same note to the same person every time it checks.
The general risk of letting agents send is covered in can AI agents send cold email safely. This page is about one failure: the loop.
Why a rule in the prompt is not enough
You can tell the agent "never email anyone twice", and it will usually comply. But a prompt is guidance the model can lose across a long run, and a retry does not consult the prompt about whether it counts. A guard written into the agent's own code has a quieter problem: it only protects the path that runs it. A second client, a copied key or a new script never sees the check.
The guard has to live where every send passes through it, whoever started the send. That means below the agent, in the system that actually delivers the mail.
Outreach: let the agent build, let the scheduler send
When an agent runs your outreach through WarmySender, it works through tools. Claude, ChatGPT, Cursor, Codex, OpenClaw, Hermes Agent and any agent that speaks MCP can create, launch and manage campaigns, enroll prospects and verify emails in plain language. The agent never sends a message directly. Creating or starting a campaign writes it and hands it to the scheduler, and the scheduler does the sending. Several guards sit in that path:
- One enrollment per person per campaign. Enrolling someone who is already in the campaign is skipped, and a second copy is refused even if two requests arrive at once.
- One send per step. Each person receives each step of a sequence at most once. A re-run or a retry cannot queue a second copy of a step that already went out.
- Stop on reply. A reply ends that person's sequence. It is on by default. An agent building a campaign can switch it off, so check the setting on anything an agent created. Here is how stop-on-reply works across channels.
- Daily caps the agent cannot change. Each mailbox sends at most the lower of the campaign's cap and the mailbox's own daily limit, with a per-domain cap on top. No agent tool can change a mailbox's daily limit, and the caps only ever delay a send, never speed one up.
Put together, a loop in the agent turns into a campaign that already exists and people who are already enrolled, not into a second wave of email.
The same person in two campaigns
The per-campaign guards do not stop an agent from putting the same person into two different campaigns. That is a legitimate thing to do sometimes, so it is a choice, not a default. If you want it blocked, turn on the audience exclusion rules in the campaign builder:
- Skip anyone who's in any of your other campaigns keeps a person in one campaign at a time.
- Recently contacted cooldown skips anyone you emailed within the window you choose.
Both rules are off by default, and an agent cannot switch them on for you. Once you have, they apply to every enrollment, including the ones an agent makes.
Retries: send an idempotency key
An idempotency key is a label you attach to a request so a retry is recognised as the same request rather than a new one. WarmySender's agent tools and its API accept one on most write actions and remember it for 24 hours, so a retry inside that window does not create a second campaign or a second enrollment.
Twenty-four hours covers a timeout. It does not cover an agent that wakes up tomorrow with no record of today. For scheduled agents, the habit that matters is reading before writing: list what already exists, then create only what is missing.
Know where the stop is
When something is sending that should not be, speed matters more than precision:
- Pause the campaign. The agent can do it, and so can you. Scheduled sends are halted and queued work stays where it is, so resuming picks up without losing anyone.
- Pause your mailboxes. On the Mailboxes page, select all and choose Pause Sending. No campaign email leaves a paused mailbox, whichever campaign it belongs to. This is the fastest way to stop all outreach at once.
Mail your app sends when an agent triggers it
Outreach is one half. The other half is the mail your own product sends when an agent or a detector decides it should: receipts, alerts, sign-in codes, status notes. That mail does not go through a campaign, so it needs the same idea applied at the sending API. We covered the idea in how to hand an agent an email key without handing it your reputation, and compared how seven transactional email APIs handle it.
AgentiSend is a transactional email API built for agent-triggered sends, and its guard is in the send path itself. According to its loop detection documentation:
- Repeats are refused and held. Each send is compared with the same key's sends from the last 60 minutes. A message to the same recipient whose subject and body are both at least 85% similar counts as a repeat, and the 4th one is refused and held for a person to approve rather than lost.
- A loop that varies its wording is caught too. Once the window holds at least 20 sends, a burst going to fewer than 3 effective recipients is refused as well.
- Retries are recognised for 7 days, on every call that changes something.
- Budgets the agent can only lower. Each key has a send budget per period and a per-minute ceiling. A key can lower its own limits but not raise them.
- A stop only a person can undo. One call pauses every key on the account, and resuming takes a person signed in to the console. An API key cannot resume sending, not even the key that stopped it.
It is built for transactional mail. Cold email is not a supported use, so keep outreach where the scheduler and the ramp are.
A five-point checklist
- The agent has tools, not a raw sending credential.
- Every send passes a guard that deduplicates and caps, below the agent.
- Cross-campaign exclusion is on if you never want someone in two campaigns.
- Every write carries an idempotency key, and scheduled agents read before they write.
- You know which button stops everything, and you have pressed it once on purpose.
Frequently asked questions
Will a retry send the email twice?
Not if the retry carries the same idempotency key inside the window. WarmySender's agent tools and API remember a key for 24 hours; on top of that, a person already enrolled is skipped and a sequence step already sent is never queued again.
Can an agent enroll the same person in two different campaigns?
Yes, unless you turn on the audience exclusion rules. "Skip anyone who's in any of your other campaigns" and the recently contacted cooldown are off by default, and once you switch them on they apply to enrollments an agent makes as well.
Can the agent turn stop-on-reply off?
Yes. Stop-on-reply is on by default, but it is a campaign setting an agent can change when it builds or edits a campaign. Review it on any campaign an agent created before you start it.
How do I stop everything quickly?
Pause your mailboxes from the Mailboxes page: select all and choose Pause Sending. No campaign email leaves a paused mailbox. To stop a single campaign, pause that campaign; queued work stays in place for when you resume.
Can the agent raise my sending limits?
No agent tool can change a mailbox's daily limit, and every send still waits for the daily caps and the ramp, whoever started it. Raising a limit is a person's decision.
How do I test an agent's email workflow without emailing real people?
For outreach, keep the campaign in draft and review what the agent built before you start it. For app mail, AgentiSend accepts sends to its simulator addresses, such as [email protected], which reach nobody and cost nothing.