An AI agent is enterprise ready when its limits hold without the model's cooperation. Every buyer's question at scale comes down to the same one: when this thing is wrong, what happens? Not if. Any answer that starts with "we prompt it to" is not a control, because a prompt is a request and a control is a constraint.
- Whitelisting names what the agent may reach.
- Authentication proves where an input came from.
- Prompt injection screening stops hostile text from becoming instruction.
- Permissioning puts authorization in infrastructure, not a prompt.
- Multi-tenancy isolates one customer's agent from another's data.
- Auditability proves what the agent did afterwards.
- If a control depends on the model's cooperation, it is not a control.
Jump to a section:
- What is whitelisting for an AI agent?
- How does an AI agent verify where an input came from?
- What is prompt injection, and how do you stop it?
- How should AI agent permissions work?
- What does multi-tenancy mean for AI agents?
- What should an AI agent audit log capture?
- What to ask your provider
Below is what each control is, why agents change it, and how we implement it at AgentMail. Run your own stack against the list.
What is whitelisting for an AI agent?
Deny everything, then name the exceptions. It is how firewalls worked before the cloud hype, how OAuth scopes work, and how a guest list at a door works.
Think about how a new engineer gets access in their first week. Someone opens a console, grants them the three systems they need, and a manager signs off. Nobody writes them a paragraph explaining which databases to stay out of and calls that access control.
Now think about how the agent you shipped got its access. Did it get the paragraph? A prompt, an md file, a line in the system message? That holds until the model reads it generously, or you swap models and the new one reads it differently, or someone sends a message convincing enough to talk it out of its own instructions.
What a reviewer wants is the boundary written where the agent cannot reach it: which repos it pushes to, which channels it posts in, which rows it reads.
We do this with Lists. An allow list decides exactly who your agent may email and who may email it. A block list is the inverse: everyone gets through except the addresses or domains you name. They are set separately for sending, receiving and replying, at your org, a pod or a single inbox. An agent that files expenses gets a receive list holding your finance domain and a send list holding one accountant, and that is its entire surface. Set the reply lists too: replies are checked against those rather than the receive lists, and they start empty. The allowlist and blocklist walkthrough covers all three.
How does an AI agent verify where an input came from?
Your agent trusts whatever it reads, so something upstream has to prove the thing it read came from where it claims. Every channel it listens on needs this: a webhook signature checked before the payload is parsed, a tool result that came from the service it says it did, a session that belongs to the user named inside it. An agent has more of these channels than a normal service, and it acts on them without a person in between.
git log will tell you a commit was authored by anyone you like. The author field is set by whoever ran the command, which is why signed commits exist and why some repos refuse anything unsigned. The name attached to the work and the proof that the name is real are two separate things. The failure mode is a system that treats the claim as the proof, which is most systems, because the claim is right almost every time.
On the email channel, this was answered twenty years ago with SPF, DKIM and DMARC, which check whether the sending server was authorized for the domain, whether the signature holds, and whether the authenticated domain matches the From address a human reads. We run all three on the way in and tag failures as unauthenticated. What matters is what you do with the tag: deny that label on the agent's key and the failures stop existing for that agent, excluded from listings, not found on direct access, and not delivered as an event. Worth checking your forwarding paths first, since forwarding breaks SPF and mailing lists break DKIM, and failed authentication is the most common reason inbound mail goes missing.
What is prompt injection, and how do you stop it?
Prompt injection is when text an agent reads gets treated as instruction it should follow. Authentication tells you where content came from and nothing about what it is for. A verified sender can inject, and so can a document, a scraped page, or a tool response. Anything your agent reads is a candidate instruction.
Most teams have not built this control, because the content that matters does not look wrong. A line addressed to the assistant, parked at the bottom of a quoted thread where nobody scrolls, inside a reply about an invoice. You would have approved that email. So would the model, which is the problem.
Email is the worst surface for it, because it is open and asynchronous. Anyone can put text in front of your agent, and it arrives while nobody is watching.
We do this with Agent Armor. It asks whether a model would be steered rather than whether a person would be fooled. Rules catch the hidden signals, a model reads the whole message for intent, and it screens after receipt rather than in front of your MX record, so nothing is bounced at the edge. With enforcement on, the webhook waits while a flagged message is held. Underneath it, viruses are rejected at the gateway and never stored, and spam is stored but excluded from API results unless you ask for it.
How should AI agent permissions work?
This is the control buyers care about most, and the only one that assumes everything above it already failed.
Authorization belongs in infrastructure, not instructions, so the blast radius holds no matter what the agent decided. Scoped tokens, database roles, spend caps, a person in front of anything that commits. The test: can an agent that has been fully convinced still do the damage? If the answer depends on the model, you do not have this control.
Ours is the API key. A key with no permissions set has full access inside its scope, which is the default and worth knowing before you hand one to an agent. Pass a permissions object and it flips to a whitelist, where only what you set to true is allowed:
key = client.api_keys.create(
name="contract-reader",
permissions={
"message_read": True,
"draft_create": True,
# no message_send, no draft_send
# no list_entry_create, so it cannot edit its own allow list
"label_unauthenticated_read": False,
},
)That agent reads the thread and writes a reply for a human to send. It cannot send, it cannot add an address to the list that gates it, and it cannot route around either by issuing itself a better key, because a restricted key cannot create a child key with more permissions than its parent. The convincing email still lands. The send is refused by the key.
What does multi-tenancy mean for AI agents?
A good number of our customers are not running one agent. They provision inboxes for their own customers, so every account signing up to their product gets an agent with an address. Our tenant boundary is holding up theirs.
All those customers sit on the same infrastructure. That is the deal with SaaS, and it is fine until one query goes out without a filter, or a key reaches further than you thought, and customer A is reading customer B's mail. Nothing breaks. You find out from customer B.
Agents raise the odds. A human tenant has to go looking for the door. An agent makes its own calls, fast, based on text that came from outside, and it only has to get lucky with your boundary once.
We do this with Pods. A Pod is a sealed workspace with its own inboxes, domains, threads and drafts, created against the customer ID you already have, so nothing sits in between translating your IDs into ours. Everything customer A needs lives inside theirs, one agent or a whole department, and a key scoped to that Pod cannot see out of it. A Pod isolates data rather than sending reputation, which is what custom domains are for. The multi-tenancy guide covers pods, scoped keys and webhook filtering together.
What should an AI agent audit log capture?
The other five decide what your agent can do. This one decides whether you can prove what it did.
It is the question legal asks rather than security, and it lands hardest when the actor is autonomous. Something went out at 3am, nobody approved it, and the answer cannot be that you are fairly sure the agent had good reasons. A human tenant leaves a trail through your UI. An agent leaves one only if you kept it.
Today we expose two pieces of this. Message events, sent, delivered, bounced, complained and rejected, come through webhooks and the metrics API. And every inbox keeps a label event log, an ordered record of every label added or removed with its message ID and timestamp, which is what you reach for when you need to reconstruct what state a message was in and when. Pair it with idempotency keys so a retry cannot double-send and leave you explaining two identical emails.
What to ask your provider
- Can I restrict exactly which addresses my agent sends to and receives from?
- Do you check SPF, DKIM and DMARC, and can I keep failures out of my agent's context?
- What screens inbound content for instructions aimed at the model, and can a flagged message be held before my agent sees it?
- Can I issue a key that reads but never sends, and can that key change its own restrictions?
- Is my data isolated from your other customers, and is my sending reputation isolated too?
- Where are my messages processed, who can access them, how long are they kept, and are they used for training?
Ask all six. Not whether they take security seriously, because everyone says yes to that. Ask, and watch which get answered with a control and which get answered with a paragraph about their approach.
Most email APIs were built to send campaigns to people who asked for them. None of these six mattered, because nothing on the other end could act. An inbox attached to an agent with tool access is a different object, and the controls have to be underneath it rather than bolted on after.
We built all six because email is the only thing we work on.
Start at agentmail.to.
AgentMail gives your agents real inboxes. Create inboxes via API. Send and receive Emails with 0 complexity. Free to start.


