# The AgentMail alternative for AI agents

> Source: <https://mailkite.dev/blog/agentmail-for-ai-agents/>
> Published: 2026-07-04 00:00:00+00:00

# The AgentMail alternative for AI agents

AgentMail is a purpose-built, well-funded email provider for AI agents: create an inbox over an API, receive by webhook, WebSocket, or poll, and let the agent read verification codes and reply. MailKite (which we build) gives an agent its own inbox too, on a domain you own with no per-inbox cap, as one capability of general email infrastructure. For developers deciding between a dedicated agent-inbox tool and an email platform that also gives agents inboxes.

Both products agree on the hard part, and it’s worth saying plainly: an autonomous agent should have its *own* address, not a human’s mailbox bolted onto a bot with IMAP and a refresh token. AgentMail is built for exactly that, does it well, and owns the “email for AI agents” headline. So this isn’t a post about a capability AgentMail lacks. It’s about two honest differences: whose domain the inbox lives on, and whether the tool is scoped to agent inboxes or is general email infrastructure that also gives agents inboxes. Here’s the split in one picture.

Here’s the whole MailKite receive-think-reply loop. Email in, verify the signature, hand the body to your model, reply through the same client. It runs as pasted on Node 18+ (`npm install mailkite express`

):

``` python
import express from "express";
import { MailKite } from "mailkite";

const app = express();
const mk = new MailKite(process.env.MAILKITE_API_KEY);
const SECRET = process.env.MAILKITE_WEBHOOK_SECRET;

app.use("/hooks/agent", express.raw({ type: "application/json" }));

app.post("/hooks/agent", async (req, res) => {
  // HMAC signature, replay window, constant-time compare — one call
  if (!MailKite.verifyWebhook(req.headers["x-mailkite-signature"], req.body, SECRET)) {
    return res.sendStatus(401);
  }
  res.sendStatus(200); // ack fast; run the agent out of band

  const event = JSON.parse(req.body);
  if (event.type !== "email.received") return;

  // The body is untrusted INPUT, never instructions (see the security section).
  const answer = await runAgent({
    task: event.text,
    from: event.from.address,
    trusted: event.auth.spf === "pass" && event.auth.dmarc === "pass",
  });

  await mk.send({
    from: event.to[0].address,   // reply from the address it was sent to
    to: event.from.address,
    subject: `Re: ${event.subject}`,
    inReplyTo: event.id,         // threads the reply
    html: answer.html,
  });
});

app.listen(3000);
```

The message arrives fully decoded and the inbox lives at `agent@yourco.dev`

, an address on your DNS. The identical handler shape exists for Python, Ruby, Go, PHP, and Java; see the [receiving docs](/docs/receiving) and [sending docs](/docs/sending). A companion repo, [ demo-agentmail-ai-agent](https://github.com/mailkite/demo-agentmail-ai-agent), has this running with a signed sample event you can fire;

[open it in StackBlitz](https://stackblitz.com/github/mailkite/demo-agentmail-ai-agent?file=server.mjs).

## Where AgentMail wins for agents, honestly

AgentMail is not a send-first ESP wearing an inbound hat, and it isn’t a thin wrapper you’ll outgrow in a week. It’s a focused, well-funded product built for one job, and it does that job well.

To be fair about our own side: MailKite’s agent-inbox is *one capability of a broader platform*, not a single-purpose agent product. If your only requirement is the cleanest possible agent-inbox primitive, AgentMail is built for precisely that and MailKite is a wider tool than you need.

## What AgentMail asks of an agent builder

Nothing painful, and that’s the honest framing. The AgentMail path is clean code. Here it is in its own idiom (from the `agentmail-contrast/`

folder in [ demo-agentmail-ai-agent](https://github.com/mailkite/demo-agentmail-ai-agent)):

``` js
import { AgentMail } from "agentmail";
const client = new AgentMail({ apiKey: process.env.AGENTMAIL_API_KEY });

// Create an inbox. With no domain, the address is on the shared agentmail.to
// domain; an inbox on your own domain requires a paid plan (Developer, $20/mo+).
const inbox = await client.inboxes.create({ clientId: "support-agent-v1" });

// Receive by webhook (also available: WebSocket, or poll messages.list()).
app.post("/agentmail/webhook", async (req, res) => {
  res.sendStatus(200);
  const { event_type, message } = req.body;
  if (event_type !== "message.received") return;

  // text may be absent for HTML-only mail or payloads over 1 MB — fall back to html.
  const answer = await runAgent({ task: message.text ?? message.html });

  await client.inboxes.messages.send(inbox.inbox_id, {
    to: message.from,
    subject: `Re: ${message.subject}`,
    text: answer.text,
  });
});
```

That reads well, and for a lot of agents it’s all you need. The two things it asks of you aren’t bugs, they’re the shape of a focused product:

That second point is the one worth a picture, because it’s the real structural difference and it has nothing to do with code quality.

## The comparison, no adjective inflation

| AgentMail | MailKite | |
|---|---|---|
| Agent gets its own inbox | Yes, its core primitive | Yes, on a domain you own |
| Default address domain | Shared `agentmail.to` | Your own domain, always |
| Own-domain inboxes | Paid plans ($20/mo+), SPF/DKIM/DMARC on your DNS | Baseline, free, unlimited domains |
| Inbound delivery | Webhook, WebSocket, or poll; `message.received` | Signed JSON webhook; `email.received` |
| Scope | Agent inboxes | General email infra (also transactional/support) |
| SPF/DKIM/DMARC verdict in payload | Not in the documented event shape | `auth` block in every payload |
| MCP server | Hosted, OAuth (~17 tools) | Hosted, OAuth |
| Free tier | 3 inboxes, 3,000 emails/mo, no custom domain | Unlimited inboxes + domains, 3,000 msgs/mo (in + out) |
| Who runs the model loop | You | You, or a route with `action: 'agent'` |

The through-line is not “AgentMail is worse.” It’s scope and ownership. AgentMail is a sharp, single-purpose agent-inbox tool with a shared-domain default and per-plan inbox caps. MailKite gives the agent its own inbox on a domain you own from the free tier up, and it’s the same platform your product’s other email already runs on.

## What actually hits your agent’s webhook

MailKite decodes the message at the edge, so your handler gets fields, not MIME, and one block a bare inbox API usually doesn’t hand you:

```
{
  "id": "msg_2Hk9…",
  "type": "email.received",
  "from": { "address": "ada@example.com" },
  "to": [{ "address": "agent@yourco.dev" }],
  "subject": "Re: invoice #1042",
  "text": "Looks good — approved!",
  "html": "<p>Looks good — approved!</p>",
  "threadId": "<a1b2c3@mail.example.com>",
  "auth": { "spf": "pass", "dkim": "pass", "dmarc": "pass", "spam": "ham" },
  "attachments": [
    { "id": "msg_2Hk9…:0", "filename": "po.pdf", "contentType": "application/pdf",
      "size": 18213, "url": "https://api.mailkite.dev/att/2Hk9…/0?exp=…&sig=…" }
  ]
}
```

That `auth`

block is load-bearing. `From:`

is plain text, so a sender is trivially forged, and the moment your agent *follows* what an email says, the body is a prompt-injection vector. Whether the code arrives on `agentmail.to`

or on your own domain, the same rule holds: the verdicts let the loop weight a sender before it acts, but they’re necessary, not sufficient. Treat the body as untrusted data, bound the agent’s authority, and read [agent inbox security by design](/blog/agent-inbox-security-by-design/) before you point it at anything that matters.

## Where I won’t overclaim

MailKite, which we build, is an inbound-to-webhook platform that also sends. Its agent-inbox is one lane of that, and the honest pitch is narrow: the agent gets its own address on a domain you own, free and without a per-inbox cap, and inbound arrives already parsed with an `auth`

verdict attached, all on the same account that runs your product’s transactional and support mail. If instead you want the most focused agent-inbox primitive on the market and nothing more, AgentMail is purpose-built for that, well-funded, and good at it. On MCP the two are at parity. If you’d rather not host the loop at all, MailKite can run it: a route with `action: 'agent'`

executes the model on a durable queue and keeps a per-route transcript, described in [give your agent an inbox](/blog/give-your-agent-an-inbox/).

## FAQ

**Does AgentMail give an AI agent its own email inbox?**
Yes. That’s its core primitive: `client.inboxes.create()`

returns a working address, and the agent receives mail by webhook, WebSocket, or poll and replies over the send API. By default the address is on the shared `agentmail.to`

domain. MailKite gives the agent its own address on a domain you own, on the free tier.

**Can AgentMail put the inbox on my own domain?**
Yes, on a paid plan. You add SPF, DKIM, and DMARC records to your own DNS and AgentMail verifies them. It’s not available on the free tier (default is `agentmail.to`

), and it’s capped by plan: up to 10 custom domains on Developer ($20/mo), up to 150 on Startup ($200/mo). On MailKite, an inbox on your domain is the baseline and domains are unlimited and free.

**How is AgentMail priced?**
Per plan, not per message. Free is 3 inboxes and 3,000 emails/month with no custom domains; Developer is $20/month for 10 inboxes, 10,000 emails, and 10 custom domains; Startup is $200/month for 150 inboxes, 150,000 emails, and 150 domains. MailKite’s free tier is unlimited inboxes and unlimited domains with a shared 3,000 messages/month quota across inbound and outbound.

**Do both support MCP?**
Yes, and this is genuine parity. AgentMail ships a hosted MCP server with OAuth and about 17 tools; MailKite ships a hosted MCP server at `mcp.mailkite.dev`

with OAuth, plus a Claude Code plugin. Neither has a meaningful edge here.

**Can the agent read verification codes and reply on either?**
Yes on both. The full message reaches the agent, so it can extract an OTP, follow a magic link, or reply in-thread. The difference isn’t capability, it’s where the inbox lives (a domain you own by default on MailKite) and whether the same tool also carries your product’s other email.

If you want a single-purpose agent-inbox tool, AgentMail is built for exactly that and does it well. If you’d rather the agent’s inbox live on a domain you own, free and unlimited, on the same platform that already sends your product’s mail, clone [ demo-agentmail-ai-agent](https://github.com/mailkite/demo-agentmail-ai-agent) (or

[run it in your browser](https://stackblitz.com/github/mailkite/demo-agentmail-ai-agent?file=server.mjs)), then

[point a domain at MailKite](/docs/quickstart)and your next inbound email arrives at the agent as parsed JSON.

*Related: the pillar on giving your AI agent its own email inbox, agent inbox security by design, and the full MailKite vs AgentMail comparison.*
