When an agent should send one email instead of nine
An agent that emails on every event is easy to build and unpleasant to receive. Nine messages about one shipment, four about a document being edited, a notification per line item. The recipient's response is not to read faster, it is to filter your domain, which costs you the one urgent message that mattered.
4 min read
Choosing the delivery rhythm is a design decision, and it belongs in the architecture rather than in the prompt.
Three rhythms
Immediate. One message, sent now. Correct when the recipient can act on it and the value decays: a customer reply, an approval request, a failure that blocks someone.
Batched. Hold for a short window, then send one message covering what happened. Correct when events cluster and any individual one is uninteresting alone. A few minutes is usually enough, and it is the rhythm most agents should default to.
Digest. A scheduled summary, daily or weekly. Correct for awareness rather than action: what happened, what is outstanding, what needs attention eventually.
The test for immediate is whether the recipient would want to be interrupted for this specific event. Most events fail it, and the ones that pass are usually the ones where a person is waiting.
| Event | Rhythm |
|---|---|
| A customer replied to a thread you own | Immediate |
| An approval is blocking work | Immediate |
| A document was edited three times in five minutes | Batched |
| Six items shipped from one order | Batched into one |
| Nothing is blocked and nothing changed | Send nothing |
| Weekly account status | Digest |
That fifth row is the one people forget to implement. Not sending is a valid outcome, and a digest that arrives saying nothing happened trains people to stop opening digests.
Batching without losing urgency
The naive batch holds everything for the window, which delays the urgent thing along with the noise. The fix is to classify first and hold only what is holdable.
async function onEvent(e: Event) {
if (urgent(e)) return sendNow(e); // a person is waiting
await pending.add(e.recipientId, e); // everything else accumulates
await scheduleFlush(e.recipientId, 5 * 60); // reset the window on each new event
}Resetting the window on each new event, rather than flushing on a fixed timer, is what makes the output read naturally: a burst of activity produces one message after the burst rather than three messages carving it into arbitrary slices.
The same debounce solves a related problem in conversational threads, where three messages from one person in two minutes should produce one reply rather than three, per what happens when forty messages arrive at once.
Write the digest so it can be skimmed and ignored
A digest that requires reading in full to find out whether anything needs you is a digest people stop opening. Lead with the exceptions.
Needs you: the tagline sign-off, waiting since Tuesday.
Everything else: 3 designs shipped, 2 in review, nothing blocked.Two sections, the actionable one first, and a clear statement when there is nothing. If the top section is empty for a week, consider whether the digest should exist at all, which is a question worth asking honestly rather than defending the artefact.
Threading and the digest problem
Individual notifications thread naturally: they belong to a conversation about one thing. Digests do not, since they cover several conversations at once, and the honest handling is to send them as their own thread rather than attaching them to whichever conversation happened to be involved.
The corollary matters: a reply to a digest is ambiguous by nature. "Yes, go ahead" against a message covering four items needs a clarifying question rather than a guess, and the agent should ask which one rather than picking the most likely, per the escalation discipline in the system prompt.
Keep the digest subject stable week to week so the series groups and stays findable, per subject lines an agent should write.
The deliverability angle
There is a self-interested reason to batch beyond politeness. Nine near-identical messages to one recipient is the shape that trips duplicate-content detection, drives complaint rates up, and burns your daily allowance on mail nobody wanted. One well-formed message does none of that, per deliverability for agent senders.
Batching also improves the engagement signal, since one message people open beats nine they delete unread, and engagement is the strongest positive signal a mailbox provider observes.
Letting recipients choose
Where the volume is meaningful, let people pick their rhythm and honour it. Three options is enough: everything as it happens, batched, or a daily digest. Record the preference on the contact so it survives across conversations, per giving an email agent memory.
The important half is honouring it in code rather than in a prompt, since a preference that depends on the model remembering will eventually be forgotten at the least convenient moment.
Questions
- Should an AI agent email on every event?
- No. Immediate delivery is for events a person would want to be interrupted for, which is a small subset. Cluster the rest into one message, and send nothing when nothing changed.
- How long should the batching window be?
- A few minutes for most workflows, with the window reset on each new event so a burst produces one message after it rather than several slices of it.
- How do I keep urgent things fast while batching?
- Classify before queueing. Urgent events send immediately; everything else accumulates. Holding everything for the window is what makes batching feel slow.
- Should digests thread with existing conversations?
- No. A digest spans several conversations, so it belongs in its own thread with a stable subject, and a reply to it usually needs a clarifying question.
- Does batching help deliverability?
- Yes. Repeated near-identical messages to one recipient trip duplicate-content detection and push complaints up, while one message people actually open improves the engagement signal.
- Should recipients choose their own rhythm?
- Where volume justifies it, offer immediate, batched, or daily, record the choice on the contact, and enforce it in code rather than relying on the model to remember.
Give your agent an address it can answer from.
Create an inbox