Should multiple AI agents share one email inbox?
By Naol Ketema, founder · · Markdown
SHORT ANSWER
Usually no: give each AI agent its own inbox and its own credential. Separate inboxes keep one agent from reading or answering another's mail, make it clear which agent sent what, and let you suspend or rate-limit one agent without touching the rest. A shared inbox only makes sense when one logical role is served by several workers, and even then a single agent identity with a routing layer is cleaner than several agents on one mailbox.
The short version
An inbox is an identity boundary. Whoever can read it can see every conversation in it, and whoever can send from it speaks for it. Sharing one inbox between agents means sharing that boundary, which is the opposite of what you want from autonomous software that can be confused, prompt-injected or simply wrong.
One inbox per agent: what you get
- Isolation: an agent's credential reaches only its own mailbox. If one agent is compromised by a malicious email, the blast radius is that agent's mail.
- Attribution: every sent message is from one agent's address, so the audit trail and the recipient both know who said it.
- Clean threading: inbound replies are matched to threads within one mailbox, so two agents never end up in the same thread by accident.
- Per-agent controls: allow and block rules, webhooks, event filters and suspension can all target one agent.
- Clear reputation signals: a spike in bounces or complaints points at the agent that caused it.
One inbox per agent: what it costs
- More addresses to manage, and plan limits on how many agents an organization can hold.
- Cross-agent views need an extra step, such as searching across mailboxes with an admin key.
- Customers may see several addresses from your company, which can be confusing if the agents overlap in purpose.
A shared inbox: when it makes sense
Sharing fits when one public role, such as support@ or billing@, is served by several processes that are really one agent: a pool of workers handling the same queue with the same instructions and the same permissions. In that case, model it as one agent with one mailbox, and scale the workers behind it. Each worker uses the same agent key and the same event stream.
What does not work well is several agents with different jobs and different instructions all reading one mailbox and deciding among themselves who answers. You get races, duplicate replies, and no way to tell from the outside which agent did what. If a message needs a specialist, have the front agent forward it, or delegate the task to another agent directly, rather than letting every agent read everything.
Concurrency on a shared mailbox
If several workers do share one agent's mailbox, make replies idempotent. Derive the idempotency key from the inbound message id, so whichever worker answers first wins and the others get the original result back instead of a second email. Same key with a different body returns 409, which tells a worker someone else already answered differently.
await client.mail.send({
identityId,
to: [event.payload.from!],
subject: `Re: ${thread.subject ?? ""}`,
text: reply,
inReplyToMessageId: event.payload.messageId,
idempotencyKey: `reply-${event.payload.messageId}`,
});How Agent Identity is shaped around this
In Agent Identity the mailbox and the agent are the same thing. Creating an agent provisions its mailbox, and there is no separate mailbox resource to share. The isolation comes from two kinds of key:
- An agent key acts as one agent. Another agent's mailbox returns 404 to it, and its events and webhooks are limited to its own.
- An org key administers the organization and can see across agents, for example client.mail.searchOrganization searches every mailbox and needs an org key.
const support = await admin.identities.create({ handle: "support", displayName: "Support" });
const billing = await admin.identities.create({ handle: "billing", displayName: "Billing" });
const { key: supportKey } = await admin.apiKeys.create({ name: "support runtime", identityId: support.id });
const { key: billingKey } = await admin.apiKeys.create({ name: "billing runtime", identityId: billing.id });
// A person or a supervising process with the org key can still search everything.
const hits = await admin.mail.searchOrganization({ q: "invoice 1142" });When a person needs to see what an agent is doing, keep them out of the agent's credential. Bcc them on sends, forward specific messages to them, or have the agent save drafts for approval. Each of those keeps the person informed without giving them, or another agent, the agent's identity.
A simple rule
One role, one identity, one inbox. Scale workers behind an identity, not identities behind an inbox. If two agents would need different instructions, different permissions or a different person to answer for them, they need different inboxes.
The same rule applies to customers. If you run an agent on behalf of each customer, give each one its own agent and mailbox rather than one shared inbox with a routing table. Each customer's mail then stays behind its own key, and closing one account is a suspension, not a data cleanup.
FAQ
Can several worker processes use the same agent's inbox?
Yes, if they are the same agent with the same job. Give them the same agent key and derive idempotency keys from the inbound message id so only one reply is sent.
How do I see all agents' mail in one place?
Use an org key. client.mail.searchOrganization searches every mailbox in the organization by subject, body, address and name.
Is one inbox per agent more expensive?
Each agent counts against the plan's agent limit. Email is on every plan; check client.usage() for how many agents your organization can hold.
Related guides
Give your agent its own identity in a couple of minutes. Get started free → · Docs · All guides