BlogUpdated 4 November 2026 · 5 min read

Multi-tenant email for AI agent platforms

How does an AI agent platform give every client its own inboxes, domain, keys and sending reputation without one client hurting another?

The short answer

An AI agent platform gives each client its own email by putting every client in a separate container that holds their inboxes, their domains, a key that reaches only them and their own sending reputation. In Pidgeon that container is a pod: one call at a client's signup makes the pod, its first inbox and its key, and one client's bounces land on that pod and nobody else's. Inboxes are unlimited; what bounds abuse is the pace at which addresses are created and mail is sent.

What a platform owes each client

A platform's agents write to its clients' customers, in its clients' names. So the email layer has four things to keep apart, and a label in your database keeps none of them apart:

  • Addresses. Client A's agent must never read client B's mail, even by a bug in your code.
  • Domains. Each client wants mail to come from their own domain, often a subdomain such as agents.client.com, set up without a ticket to you.
  • Keys. The credential client A's agent runs with should be unable to reach client B, so a leak is one client's incident.
  • Reputation. When one client's agent mails a list of dead addresses, the damage should stop at that client.

Our first customer is an agent platform, and the order it asked in was: deliverability handled, inbound that works, a complete and documented API, and abuse filtering that protects the reputation every client shares. Unlimited inboxes is why it chose Pidgeon.

A pod per client

A pod holds addresses and domains, and it is a boundary rather than a folder. Pidgeon sends on Amazon SES and gives every pod its own SES tenant, so bounces and complaints from a pod's mail count against that pod. A domain can be in several pods at once, and mail from an address sends under its pod whichever domain it is on.

You can check the separation rather than take it on trust. GET /v1/metrics?pod_id=… answers for one pod alone: sent, delivered, bounced, complained, delivery rate and reputation.sending. That field is enabled, paused when the provider has stopped taking this pod's mail and nobody else's, or unknown for a pod that has never sent.

Provisioning a pod

The call belongs in your own signup handler, made with your admin key:

curl https://pidgeon.ai/api/v1/pods \
  -H "Authorization: Bearer $PIDGEON_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: provision-client-8812" \
  -d '{
    "name": "Client 8812",
    "client_id": "client-8812",
    "address": { "address": "client-8812@yourapp.pidgeon.email", "type": "agent" },
    "key": { "access": "send" }
  }'

The pod, the address and the key are made together or not at all. client_id is your id for the client, unique in your account, so a second call for the same client is a 409 rather than a second pod. The key's secret is shown once; a retry with the same Idempotency-Key returns the same three with "token": null, and if the first answer was lost you rotate the key with POST /v1/api-keys/{id}/rotate.

The pod key is what the client's agent runs with. It reaches every address in its pod, including ones added later, and nothing outside it. It cannot mint another key, list your keys or see another pod; asking about one gets a 403 or 404 that says nothing about what is in it. A send key can read and send, and cannot delete its address or change who reaches it.

A test key can be minted beside the live one ("test": true), so your CI runs each client's flow without sending anything out.

The client's own domain

A pod key can add, verify and remove its own pod's domains, so a client can bring theirs without your help. Adding one returns the records to publish: MX for receiving, SPF and three DKIM CNAMEs for signing, and DMARC. On a subdomain Pidgeon publishes no DMARC record, because a subdomain inherits its parent's policy and a record of ours would weaken a stricter one. If the domain already receives mail elsewhere, POST /v1/domains says who receives it and changes nothing, so you can move to a subdomain before anyone's company mail is redirected.

Domains are counted on your plan, not per pod: 1 on Free, 10 on Pro, 150 on Startup and unlimited on Enterprise.

Unlimited inboxes, and what bounds abuse

Every plan has unlimited inboxes. That is safe only because the costs are bounded somewhere else, and a platform should know where:

  • Creating addresses is paced. Up to 20 a day on Free; on a paid plan what the account's trust tier allows in 24 hours, 150 at the normal tier and 200 at trusted.
  • Sending is capped per plan, per five minutes and per day, and the daily figure is a share set by the account's trust score. Bounces and complaints lower it.
  • A loop stops by default. A message that is not a reply, to someone the address already wrote to three times in the last ten minutes, is refused with 429 and a Retry-After.
  • Bulk copies are refused. The same body to more than 20 recipients in a day is refused, with tracking parameters ignored so a newsletter cannot pass as personal mail.
  • Hard bounces and complaints suppress the address, and a later send to it is refused rather than sent.

Two of these are the account's, not the pod's, and that is the limit worth knowing. Reputation at the provider is per pod, but the daily sending caps, the trust score and the suppression list belong to the whole account. One client's volume spends your account's daily allowance, and an address one client bounced is suppressed for every client. Pods are counted too: 3 on Free, 10 on Pro, 25 on Startup and unlimited on Enterprise. All of the numbers are on limits.

Offboarding a client

To keep the record of what was said, suspend the client's addresses and revoke the pod key: nothing can send or arrive, and the mail stays. To remove them, DELETE /v1/pods/{id}?delete_addresses=true revokes the pod's keys and every key they minted, deletes each address with all of its mail, then the pod. Without delete_addresses=true a pod that holds an address is refused, and a pod that still holds a domain is refused until the domain is deleted.

The MCP server's create_pod makes a plain pod only: it never mints a key, and no tool deletes a pod. A pod key in a model's transcript is a leaked secret, and an agent deleting a pod deletes mail in bulk, so your server makes these calls and your agents do not.

Start

Pidgeon for platforms has the whole sequence: admin and pod keys, provisioning, rotation, test mode and teardown. Pods covers the reputation boundary and the metrics, domains the records a client publishes, and limits every number per plan.

01

Asked often

What is a pod in Pidgeon?

A container per customer of yours that holds their addresses and domains. Mail sent from a pod lands on that pod's own sending reputation, so one customer's bounces do not reach another's delivery.

Can a client's agent reach another client's mail?

Not with a pod key. A pod key reaches every address in its pod and nothing outside it, and it cannot mint keys or see other pods.

Are sending limits per pod?

No. Reputation at the provider is per pod, but the daily sending caps, the trust score and the suppression list belong to the whole account.

Can a client use their own domain?

Yes. A pod key can add, verify and remove its own pod's domains. Domains count against the platform's plan, from 1 on Free to unlimited on Enterprise.

02

Keep reading

All posts

Give your agents an identity

Pidgeon is building the trust layer of the agentic web.

Register your agents, it’s free