MailKite
Start free
All posts
Gabe 16 min read

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.

AM AgentMail vs MailKite
AgentMail vs MailKite — the same job (an inbox for your AI agent), two approaches.

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.

AM AgentMail email in@agentmail.to their inboxhosted store hook/ws/pollmessage.received your agentyour model .send()reply out Clean API · inbox on the shared agentmail.to domain by default · own-domain inboxes on paid plans · a tool scoped to agent inboxes MailKite email inyour own domain MX edgeparse + auth signed hookverifyWebhook your agentyour model mk.send()reply out Blue = operated by MailKite. Inbox on a domain you own, free and unlimited · the same platform also runs your product's other mail.
Two clean agent-email paths. Both give the agent its own inbox and a receive-to-reply loop. They differ on whose domain the address lives on, and on how much of your email the tool covers.

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):

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 and sending docs. A companion repo, demo-agentmail-ai-agent, has this running with a signed sample event you can fire; open it in StackBlitz.

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.

  • It owns the category and is funded to. AgentMail raised a $6M seed led by General Catalyst in March 2026, with Y Combinator (S25), Paul Graham, and Dharmesh Shah among the backers. It has a real developer following and a single-minded roadmap.
  • The inbox is the primitive. `client.inboxes.create()` returns a working address in one call, with threads, labels, drafts, attachments, and search as first-class objects. If you want an opinionated agent-inbox and nothing else, that focus is the point.
  • Three ways to receive, including WebSockets. Webhook, WebSocket, or poll. The WebSocket path lets a local agent receive mail with no public URL and no ngrok, which is genuinely nice for development and for agents that don't host an endpoint.
  • OTP capture is the headline use case. AgentMail leans hard into verification-code and magic-link flows for browser agents: the code lands in the agent's inbox, fires an event, and the agent finishes the signup itself. It's built around that story.
  • An official hosted MCP server. AgentMail ships a hosted MCP endpoint with OAuth and roughly 17 tools. So does MailKite; on the MCP question these two are at parity, and I'm not going to pretend otherwise.

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):

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:

  • The default address is on a domain you don't own. Out of the box the agent is `something@agentmail.to`. AgentMail does support custom domains on your own DNS with SPF, DKIM, and DMARC, and the setup is straightforward. It's a paid-plan feature: none on Free, up to 10 domains on Developer ($20/mo), up to 150 on Startup ($200/mo). So "the agent replies from your brand, aligned to your DNS" is real, it just isn't the free or default path.
  • It's a second vendor, scoped to agents. AgentMail handles agent inboxes. Your product's transactional mail (receipts, password resets), your support inbox, and reply-by-email still need somewhere to live, which is usually a separate ESP. That's a fine architecture. It's also two providers, two dashboards, and two bills for what is all just email.

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.

Two vendors, scoped by tool AMAgentMailagent inboxes A second email vendor (an ESP)product transactional mailsupport inboxreply-by-emailtwo dashboards, two bills One platform MailKiteagent inboxesproduct transactional mailsupport inboxreply-by-emailall on domains you own, one quota If the agent inbox is the only email you need, one focused tool is simpler. If you also run the other 90%, that's the difference.
The email surfaces most products need, mapped to vendors. AgentMail is excellent at the agent-inbox lane; MailKite trades some focus for covering the whole surface on your own domains.

The comparison, no adjective inflation

AgentMailMailKite
Agent gets its own inboxYes, its core primitiveYes, on a domain you own
Default address domainShared agentmail.toYour own domain, always
Own-domain inboxesPaid plans ($20/mo+), SPF/DKIM/DMARC on your DNSBaseline, free, unlimited domains
Inbound deliveryWebhook, WebSocket, or poll; message.receivedSigned JSON webhook; email.received
ScopeAgent inboxesGeneral email infra (also transactional/support)
SPF/DKIM/DMARC verdict in payloadNot in the documented event shapeauth block in every payload
MCP serverHosted, OAuth (~17 tools)Hosted, OAuth
Free tier3 inboxes, 3,000 emails/mo, no custom domainUnlimited inboxes + domains, 3,000 msgs/mo (in + out)
Who runs the model loopYouYou, 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 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.

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 (or run it in your browser), then point a domain at MailKite 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.

Discuss this post: Hacker News Share on X

Related posts