When two agents answer each other: stop email loops between bots
Two email agents can reply to each other forever. Stop it with Auto-Submitted checks, one reply per thread, a daily cap and a duplicate hold. A practical list.

On this page(9 sections)
- How does a loop between two email agents start?
- Layer 1: Do not answer mail that says it is automatic
- Layer 2: One automatic reply per thread
- Layer 3: A daily cap on sends
- Layer 4: Hold identical messages
- What about the other side of the loop?
- A pre-flight checklist for any email agent
- Test it before it matters
- Bottom line
An email loop between two agents happens when each one treats the other's reply as a new message that needs an answer. You stop it with four layers: never answer mail that marks itself automatic, answer each thread at most once without a human, cap sends per day, and hold identical messages. Any one layer alone is not enough.
Classic auto-responders looped for years. AI agents make it worse because their replies look like real prose, vary in wording, and no longer match a fixed template that a filter could spot. This post covers the agent-specific version. For plain auto-replies, read an auto-reply that never loops.
How does a loop between two email agents start?
A loop starts when agent A sends a message, agent B reads it as inbound mail, and B's reply is read by A as inbound mail in turn. Nothing in the content has to be wrong. A "thanks, got it" answered by "you're welcome, let me know if you need anything else" answered by another "thanks" is already a loop.
Typical triggers:
- Two agent mailboxes on one thread. Your support agent and a customer's own assistant both answer everything addressed to them.
- An agent that answers a vendor's no-reply robot (receipts, alerts) that happens to accept replies.
- An out-of-office or ticket system on the other side that acknowledges every message and gets acknowledged back.
- A forward or alias that points back at the mailbox, so the agent answers itself. See forwarding rules gone wrong.
Mail servers have their own brake. A loop through forwarding eventually trips the hop count and bounces, as described in 554 5.4.14 hop count exceeded. But a reply loop is not a routing loop: each reply is a fresh message with a fresh hop count, so no server stops it for you.
Layer 1: Do not answer mail that says it is automatic
RFC 3834 defines the Auto-Submitted header. A value other than no means the message was generated by a process, and the RFC says automatic responders must not reply to it. Your agent should apply the same rule as a hard filter before any model call:
| Signal in the inbound message | What the agent does |
|---|---|
Auto-Submitted: anything except no |
No reply |
Precedence: bulk, list or junk |
No reply |
Empty Return-Path (<>) |
No reply (bounces and many robots use it) |
List-Id or List-Unsubscribe present |
No reply to the list; handle as a newsletter |
From a no-reply, mailer-daemon or postmaster address |
No reply |
Do the same for your own outbound mail: set Auto-Submitted: auto-generated on anything the agent sends without a person writing it, so a well-behaved system on the other end stays quiet. That header protects the other side of the conversation, and it costs nothing.
Header checks are cheap and deterministic, which is why they come first. Do not leave this to the model. A prompt that says "do not reply to automated mail" will be followed most of the time, and a loop needs only one miss.
Layer 2: One automatic reply per thread
The header check misses agents that do not label their mail. So add a rule that does not depend on the other side's behavior: an agent may send at most one automatic reply per thread, then a human takes over.
In practice:
- Store a flag on the conversation:
agent_replied_at. - When a new inbound message arrives on a thread that already has an agent reply, do not draft a second automatic answer. Route it to a person, or to an approval queue.
- Reset the flag only when a human sends something on the thread.
This turns an infinite loop into a loop of length two. It costs you very little, because a real customer who writes back after the first reply usually wants a person anyway.
Layer 3: A daily cap on sends
A cap is the layer that limits the damage when the first two fail. Pick it deliberately. A good starting number is a small multiple of what the agent legitimately sends on a normal busy day, not a round number that feels safe.
How to choose:
- Count the agent's real sends on your busiest recent day.
- Set the cap at roughly twice that, so normal spikes pass but a runaway stops within hours.
- Decide what happens at the cap: stop sending and queue the rest for a person. A silent drop is the wrong behavior, because the customer's message would vanish.
In Koltrix, Auto mode is a per-agent setting that is off by default, is in Beta, and requires a daily cap greater than zero before it can be turned on. At the cap, further replies are held for human approval instead of being sent. The cap resets at midnight in the mailbox's timezone. See what an approval step should show and when it expires for what a held item should look like.
Layer 4: Hold identical messages
Loops often repeat nearly the same text. A duplicate hold catches that: if the same mailbox has sent an identical message on the same thread to the same recipients with the same subject and body within a short window, do not send it again without a person.
Koltrix applies this to automatic sends: an identical message sent automatically in the last 10 minutes is held as an approval item instead of going out. This is a safety net, not the main defense. An agent that varies its wording slightly gets past an exact match, which is why layers 1 to 3 exist.
If your own code sends through an API, add an idempotency key as well, so a retry after a timeout cannot deliver the same message twice.
What about the other side of the loop?
You only control your own agent. If the other party's bot has no brake, your layers still protect you, but their side keeps sending. Do these:
- Stop answering that sender. After the one automatic reply, the thread goes to a human. Keep a list of senders that never get automatic replies and add the looping address to it.
- Do not reply to bounces or delivery notices. They come from
mailer-daemonwith an empty return path, which layer 1 already filters. - Keep a human-visible log. Every automatic send should be recorded with the thread and the reason, so you can see a loop forming in the first hour, not the next morning.
- Have a single off switch. If you run several agents, one switch that turns them all off beats hunting for the right mailbox during an incident. Koltrix has one for all agents.
A pre-flight checklist for any email agent
Before you let an agent send mail without a person, check each line:
- Inbound mail with
Auto-Submittedother thanno, bulk precedence, an empty return path or a no-reply sender never gets an automatic reply. - Outbound automatic mail carries
Auto-Submitted: auto-generated. - Only one automatic reply per thread; later inbound mail goes to a person.
- A daily send cap, and at the cap messages are held, not dropped.
- Identical messages in a short window are held.
- Every automatic send is logged with thread and reason.
- One switch turns automatic sending off everywhere.
- Someone gets an alert when the cap is hit, because hitting it means something is wrong.
Test it before it matters
Create two test mailboxes, point an agent at each, and send one message between them. If your layers work, you should see at most one reply and then silence. If you see a third message, find which layer failed. Run the same test with a message that has Auto-Submitted: auto-generated and confirm no reply at all.
You can run this safely on Koltrix agent mailboxes, which start in suggest mode where nothing is sent without a person. See give an AI agent its own email address for setup, and human-in-the-loop email automation patterns for where a person belongs in the flow.
Bottom line
Two agents answering each other is a predictable failure, not a rare one. Filter automatic mail by header before the model sees it, allow one automatic reply per thread, cap daily sends and hold duplicates. Then test the loop on purpose with two mailboxes, so you find out in a sandbox instead of from a full inbox or a blocked domain.
Start with Koltrix
Your domain, one inbox, and an API that sends.
A team inbox where AI sorts and drafts (nothing is sent without your click), plus the transactional API and SMTP relay your product sends with. 7 days free, no card.


