Mailgun is a transactional email API with a routes-based inbound system and a 50-plus tool MCP server. Inbound MIME retention is 0 to 7 days depending on plan. There is no inbox object.
AgentMail is built around the inbox as the primitive: one API call gives an agent its own inbox with persistent storage, automatic threading, real-time events over webhooks and WebSockets, per-inbox API keys, and multi-tenant Pods. On top of that primitive, AgentMail ships framework connectors (LangChain, CrewAI, LlamaIndex, LiveKit), an official OpenClaw plugin, prompt-injection defenses under Agent Armor, and BYOC deployment via Outposts.
Send-heavy workloads: Mailgun. Agent inbox workloads: AgentMail.
When Mailgun is the right call
- The workload is send-heavy or send-only: transactional notifications, password resets, receipts, marketing broadcasts at high volume.
- You need email validation before sending to reduce bounce rates without a separate third-party service.
- You want the deepest inbound routing on the market: regex-matched routes, conditional forwarding, and route composition inside a single verified domain.
- You need mature template management, mailing lists, batch sending, and campaign analytics on the marketing side, features Mailgun has iterated on for over a decade.
- The team is comfortable with a routes-plus-webhooks model and is ready to build the address-to-agent mapping, tenant isolation, threading, and durable message store on top.
- Multi-region data residency (EU or US) is a hard requirement, and Mailgun's regional endpoints fit your compliance shape.
When AgentMail is the right call
- The agent needs its own email identity: a real, addressable inbox with API-scoped credentials, not a
fromaddress on a shared sender or a matched local part on a catch-all route. - Each agent or tenant needs a scoped identity: own address, own API key, isolated data via Pods.
- Email serves as long-term agent memory and must remain queryable as a real inbox, not as a stream of past webhook deliveries with a 7-day ceiling.
- The product provisions inboxes per customer at signup and needs the operation to be a single API call, not a route configuration plus an application-side registry.
- Your agent runs on LangChain, CrewAI, LlamaIndex, LiveKit, or OpenClaw and you want a first-party connector instead of a raw HTTP client.
- The agent reads and replies in-thread across many concurrent conversations, and threading needs to work without your code assembling
In-Reply-ToandReferencesheaders on every send. - You need prompt-injection defense on inbound: per-inbox allowlists and blocklists, scoped API keys that limit blast radius, and the Agent Armor guardrails on top.
- You need enterprise deployment options like BYOC (Outposts) that run the email side of AgentMail inside your own AWS account, or EU region hosting for data residency.
- The agent needs to provision its own email capability autonomously, without a human completing the signup flow first (agent-initiated signup via x402).
What each one is built for
Mailgun is a transactional and marketing email API for developers. The send side is the core product: Email API, SMTP relay, template management with versioning, batch sending, bulk campaigns, analytics, mailing lists, dedicated IPs, an email validation API, and a 50-plus tool MCP server that exposes most of the surface to AI coding agents. Mailgun's deepest differentiator on inbound is the Routes API: on a verified domain, you configure regex-matched routes that trigger actions like forward() to a URL, store() in Mailgun-hosted storage, or stop() to end further processing. A catch_all() route accepts any local part on the domain, so you can receive at anything@yourdomain.com without creating anything ahead of time.
There is no inbox object. There is no thread model. There is no per-address provisioning API. Routes are declarative configuration, not resources you create per agent. When a message arrives, Mailgun fires a webhook to your endpoint (or drops the MIME into storage for a short window), and the mapping from address to agent, the deprovisioning path, and the durable store are yours to build.
AgentMail is built around the inbox as the API object. Each Inbox has its own address on the shared @agentmail.to domain or a custom domain you verify, with its own message store, automatic threading via In-Reply-To and References headers, webhooks, WebSocket connections for real-time inbound, and Pods that isolate one tenant's data from another at the infrastructure level. On top of that primitive, AgentMail ships tested first-party connectors for the major agent orchestration frameworks (LangChain, LlamaIndex, CrewAI, LiveKit), an official OpenClaw plugin on ClawHub, an MCP server, and an Agent Skill file for AI coding assistants. Provisioning an inbox is client.inboxes.create(). Replying in-thread is client.inboxes.messages.reply(). The Quickstart walks through the full send-and-receive loop.
The agent loop
| Step in the agent loop | Mailgun | AgentMail |
|---|---|---|
| Provision a new mailbox | Not supported. catch_all() accepts any local part on a domain; no inbox object | Native (one API call) |
| Send outbound message | Native (REST API or SMTP) | Native |
| Receive inbound message | Native (webhook via a route; MIME optionally stored 0-7 days depending on plan) | Native (webhook, WebSocket) |
| Thread reply against conversation | Customer-built; parse Message-Id, set In-Reply-To and References headers manually | Built in (messages.reply with message_id) |
| Store conversation history | 0 days Free, 1 day Foundation, up to 7 days Scale/Enterprise (default 3) | Persistent on every plan |
| Stable identity per agent | Address on your verified domain, matched by a route; no inbox object | Inbox is the identity |
| Multi-tenant isolation | Subaccounts segment sending programs and IP pools; you build per-tenant routing | Inbox Pods with scoped API keys |
| Event routing per identity | One webhook per route; per-agent routing is application code | Scoped webhooks per pod or per inbox |
| Framework connectors | None; HTTP API works with any framework | LangChain, LlamaIndex, CrewAI, LiveKit |
| Official orchestrator plugin | None | Official OpenClaw plugin on ClawHub |
| MCP for AI coding agents | Official (50+ tools, send-centric) | Official + AgentMail Skill for Claude Code, Cursor |
| Agent-initiated signup | Not supported | Supported via x402 |
| Prompt-injection defenses | Not native | Per-inbox allowlists/blocklists + Agent Armor guardrails |
| BYOC / self-hosted | Not offered as a public option | Outposts (Enterprise): runs in your AWS |
Where the products diverge
Mailgun's routes system is powerful. Regex-matched routes let you filter inbound by sender pattern, subject match, or destination address, and compose multiple actions in sequence. No transactional email API in the same category ships this depth of routing.
A route is a rule that fires when a message arrives. An inbox is a resource with an identity, a persistent history, a thread model, a scoped credential, and a set of behaviors an agent can invoke without your code assembling the plumbing. For a workflow like reply-by-email comment posting or a support ticket pipeline where each incoming message is a discrete event and your application already owns the durable store, Mailgun's routes are a strong fit. For agents that hold a conversation over days or weeks, or platforms that provision an addressable identity per tenant at signup and reason about that identity later, the inbox layer has to be built on top.
Mailgun documents its MIME storage window at 0 days on Free, 1 day on Foundation, and up to 7 days on Scale and Enterprise with a default of 3 when a domain is created. The raw message body only exists on Mailgun's side for a few days at most. If your agent needs to reference an inbound message from last month, or your handler failed and you want to replay, the MIME is already gone. Your application has to persist the body during the webhook window or lose it.
AgentMail persists message history on every plan, including Free. The Get a message endpoint returns decoded HTML and text bodies plus raw .eml access, and the inbox doubles as a durable message store the agent can query later. Replies thread automatically through messages.reply without your code building the In-Reply-To and References headers. Drafts support human-in-the-loop approvals for sensitive sends.
Agent-native features Mailgun doesn't have
Beyond the inbox primitive, AgentMail ships a set of capabilities that only make sense once the underlying platform is agent-native. Mailgun does not offer equivalents because they are outside the scope of a transactional email API.
Agent-initiated signup via x402. An AI agent can complete its own AgentMail signup and pay for the service autonomously via x402, the open payment protocol from Coinbase. An agent can provision its own account, get an API key, install the SDK, create an inbox, and start sending and receiving mail as part of one autonomous workflow. Mailgun (and every other transactional email API in the category) requires a human to complete the signup flow before an API key exists.
Framework connectors. First-party integrations for LangChain, CrewAI, LlamaIndex, and LiveKit. If your agent runs on one of those frameworks, the email layer is a first-class tool, not a raw HTTP client you wire yourself. Mailgun's HTTP API works with any framework but ships no framework-specific connectors.
Official OpenClaw plugin. AgentMail is on ClawHub as an official OpenClaw plugin. It ships a CLI-backed AgentMail Skill plus an email channel: inbound mail drives an agent turn and the agent replies in the thread, with a default-deny sender allowlist. Install with one command. Mailgun is not an official plugin for any agent orchestrator.
Email as agent memory. Because inbox history is persistent on every plan and messages are grouped into threads, the inbox doubles as a long-term memory layer the agent can query semantically. Past conversations, verification codes, receipts, and attachments remain addressable months later. On Mailgun the memory horizon is bounded by the 7-day MIME retention ceiling plus whatever you build on top.
Semantic search across inboxes. Query messages across every inbox in your organization by meaning rather than keyword. Useful when an agent needs to recall a past communication or reason across many identities. Mailgun does not offer a semantic search surface.
Structured data extraction. Pull structured data out of unstructured messages: invoices, receipts, order confirmations, verification codes. The extraction runs on the inbox rather than as a separate pipeline your application maintains.
Automatic labeling. Categorize incoming mail with user-defined prompts. The label is applied at ingest, so downstream agent routing can dispatch on category instead of parsing subject lines with regex.
Security: prompt injection defense on inbound
For agents that process inbound email, any user or automated sender can put untrusted content into a subject line, body, or attachment, and that content flows straight into the model's context. The EchoLeak vulnerability in Microsoft 365 Copilot (CVE-2025-32711) was disclosed in June 2025 and worked exactly this way: hidden instructions inside an email, exfiltrated data through a rendered image URL.
Mailgun's inbound is a pass-through: the webhook delivers the raw MIME to your handler and defense against untrusted content is entirely your application's responsibility.
AgentMail ships defenses at the inbox layer:
- Per-inbox allowlists and blocklists. Filter senders before messages reach the agent. Combined with a default-deny posture on high-trust inboxes, this eliminates whole categories of injection attempts at ingest.
- Per-inbox API keys. Scoped credentials mean a compromise in one inbox cannot affect another. Even if an injected instruction convinces an agent to act, the blast radius is one inbox rather than the whole account.
- Agent Armor screening. Inbound screening layered on top of the allowlist and API scoping. Rules catch hidden signals and a model reads the whole message for intent, so a message that would steer an agent is held for review rather than passed through. Screening runs after receipt, never in front of your MX record.
- Pod-level isolation. For multi-tenant deployments, a Pod isolates one customer's inboxes, credentials, and event streams from another's. An injection that lands inside Tenant A's Pod cannot reach Tenant B.
Per-inbox scoped credentials only work because inboxes are first-class resources. Per-tenant Pod isolation only works because inboxes group into Pods. On a routes-plus-webhooks architecture, the equivalents are code you write, keep correct, and audit against the OWASP Top 10 for Agentic Applications yourself.
MCP and framework integrations
Mailgun ships an official MCP server that exposes over 50 tools across the full Mailgun API surface: sending, receiving, domain management, DNS troubleshooting, webhooks, routes, mailing lists, templates, analytics, subaccounts, email validation, and unsubscribes. Setup is npx-based. The design keeps API keys in environment variables so credentials never pass to the model. The shape of the surface is send-centric because that is what Mailgun is; there is no inbox tool because there is no inbox resource.
AgentMail ships an official MCP server at https://mcp.agentmail.to/mcp and an open-source AgentMail Skill for AI coding agents. Install the skill with npx skills add agentmail-to/agentmail-skills and an agent gets first-class knowledge of the full AgentMail surface: provisioning Inboxes on demand, sending and replying to Messages inside Threads, managing Drafts for human-in-the-loop approvals, isolating tenants with Pods, handling Attachments, applying idempotency keys for safe retries, and subscribing to real-time events over WebSockets or webhooks.
Beyond the MCP and Skill, AgentMail ships first-party framework connectors for LangChain, LlamaIndex, CrewAI, and LiveKit, and an official OpenClaw plugin on ClawHub. If your agent runs on one of those frameworks or on OpenClaw, the email layer arrives as a tested integration rather than a raw HTTP client you wire yourself. Mailgun does not ship framework connectors for any of these, and is not an official plugin for any agent orchestrator.
Deployment options: managed, EU region, and BYOC (Outposts)
Mailgun offers managed deployment with US and EU regional endpoints. That covers the common data-residency requirements for teams in Europe. Self-hosting or bring-your-own-cloud is not publicly offered.
AgentMail offers:
- Managed hosting on the standard multi-tenant infrastructure (all plans).
- EU region hosting for data residency (Enterprise).
- Outposts, a bring-your-own-cloud deployment that runs the email side of AgentMail inside the customer's own AWS account (Enterprise). Outposts is aimed at teams that need the raw MIME to never leave an account they control, whether for compliance, contractual, or sovereignty reasons.
- SAML SSO on Enterprise for identity and access management.
For teams whose email infrastructure has to sit inside their own cloud boundary for legal or contractual reasons, Outposts is the differentiator. Building an equivalent on Mailgun means self-hosting a separate mail platform (Postfix, Haraka, or a custom SES layer) and losing the vendor entirely.
Pricing
Mailgun
| Plan | Price | Emails/month | MIME retention | Inbound routes |
|---|---|---|---|---|
| Free | $0 | 100/day (~3,000) | 0 days | Yes |
| Foundation | $35/month | 50,000 | 1 day | Yes |
| Scale | $90/month | 100,000 | Up to 7 days (def. 3) | Yes |
| Enterprise | From $1,500/mo | 2.5M+ | Up to 7 days (def. 3) | Yes |
Source: Mailgun's published pricing as of 2026. Dedicated IPs are an add-on. Email validation is billed separately from send volume. Mailgun's pay-as-you-go Flex rate doubled from $1.00 to $2.00 per 1,000 emails on December 1, 2025 with minimal advance notice, a change that generated significant discussion in developer communities.
AgentMail
| Plan | Price | Inboxes | Send limits | Retention |
|---|---|---|---|---|
| Free | $0 | 3 | 100/day; no separate 5-minute or monthly cap | Persistent |
| Developer | $20/month | 10 | 100/5 min; 1,000/day; 10,000/month | Persistent |
| Startup | $200/month | 150 | 1,500/5 min; 15,000/day; 150,000/month | Persistent |
| Enterprise | Custom | Custom | Custom | Persistent |
Dedicated IPs are available on Enterprise; contact sales. Outposts (BYOC), EU region hosting, and SAML live on Enterprise. SOC 2 Type II report on Startup and above. Persistent retention on every plan. Full pricing at agentmail.to/pricing.
A note on comparing these numbers
At the entry paid tier Mailgun's $35 Foundation gets you 50,000 emails with 1-day MIME retention and no inbox layer. AgentMail's $20 Developer gets you 10 inboxes with full send and receive, persistent storage, automatic threading, Pods, and the inbox primitive. For send-only workloads at high volume, Mailgun's per-email cost scales lower than AgentMail's per-inbox cost. For workloads that need persistent agent inboxes, framework integrations, or prompt-injection defense on inbound, the comparison is the AgentMail surface versus building each of those layers on top of Mailgun yourself.
The Flex rate change in December 2025 also shifted the low-volume economics. Side projects and small-scale AI agent workloads that were priced against the old $1.00 per 1,000 Flex rate saw a 100% overnight increase. Worth factoring in if your workload sits below the Foundation plan and above the Free tier's daily cap.
What an AgentMail subscription covers that Mailgun doesn't
Building a working receive pipeline on Mailgun means a webhook handler that catches the route delivery, a database to persist message bodies before Mailgun's 3-day (or 1-day, or 0-day) MIME window closes, threading logic that reconstructs conversations from Message-Id, In-Reply-To, and References headers, and per-tenant routing on a shared inbound endpoint. Before any of that, you need domain verification, MX record configuration, and a catch_all() route with your local-part mapping logic. That only gets you the plumbing; the memory layer, semantic search, structured data extraction, prompt-injection defense, framework connectors, and agent-initiated signup are separate builds on top.
AgentMail collapses the plumbing to one API call. client.inboxes.create() returns an inbox with an addressable identity, a persistent store, automatic threading, and a scoped API key. Per-tenant isolation is a Pod, not a code path. Threading is a method call on the inbox, not a header assembly step in your handler. Framework integration is an installed connector, not a hand-rolled HTTP client. The agent-native surface on top (semantic search, structured data extraction, automatic labeling, prompt-injection defense via Agent Armor, and x402 self-serve signup) is part of the platform, not code you write and maintain.
Every agent on a Mailgun domain shares one event stream, differentiated by whichever local part matched the route. On AgentMail, each inbox is its own address with its own API key and scoped credentials. Scoped webhooks route events for a specific pod or a specific inbox to the right endpoint, instead of one organization-level firehose your application has to sort.
Mailgun's per-domain rate limits are structured around send volume. If you are running many agents under one Mailgun account, they share the same domain reputation and event stream. AgentMail's limits are per-inbox, and the sender reputation is scoped per inbox and per domain, so one misbehaving agent cannot burn the reputation of the fleet.
Code: the full agent loop
AgentMail
import os
from dotenv import load_dotenv
from agentmail import AgentMail
from agentmail.inboxes.types import CreateInboxRequest
load_dotenv()
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
# Provision the agent's inbox in one call
inbox = client.inboxes.create(
request=CreateInboxRequest(username="sales-agent")
)
# Send outbound
client.inboxes.messages.send(
inbox_id=inbox.inbox_id,
to="lead@example.com",
subject="Quick question",
text="Hi Alex, saw your post about email infrastructure...",
)
# Reply in-thread when a message.received webhook fires
def on_inbound_email(payload):
message_id = payload["message"]["message_id"]
client.inboxes.messages.reply(
inbox_id=inbox.inbox_id,
message_id=message_id,
text="Thanks for getting back. To answer your question...",
)Mailgun
import os
import requests
MG_API_KEY = os.environ["MAILGUN_API_KEY"]
MG_DOMAIN = os.environ["MAILGUN_DOMAIN"]
# Send outbound through the Mailgun Messages API
requests.post(
f"https://api.mailgun.net/v3/{MG_DOMAIN}/messages",
auth=("api", MG_API_KEY),
data={
"from": f"sales-agent@{MG_DOMAIN}",
"to": "lead@example.com",
"subject": "Quick question",
"text": "Hi Alex, saw your post about email infrastructure...",
},
)
# One-time setup: create a catch_all route that forwards to your webhook.
# Every inbound message for the domain now lands on one endpoint,
# and your application dispatches by inspecting the recipient field.
requests.post(
"https://api.mailgun.net/v3/routes",
auth=("api", MG_API_KEY),
data={
"priority": "0",
"description": "Catch-all to app webhook",
"expression": f"catch_all()",
"action": [
f"forward('https://yourapp.example/mg/inbound')",
"store()",
"stop()",
],
},
)
# Inbound mail arrives at your webhook endpoint as multipart form data.
# You get the MIME for as few as 0 days (Free) or up to 7 days (Scale/Enterprise).
def on_inbound_email(payload):
recipient = payload.get("recipient") # who was it addressed to
sender = payload.get("sender")
subject = payload.get("subject")
body = payload.get("stripped-text") # cleaned reply text
message_id = payload.get("Message-Id") # header you build In-Reply-To from
# Dispatch to the right agent yourself: parse the local part,
# look up the tenant, load the thread state from your database.
agent = lookup_agent_by_local_part(recipient)
thread = load_or_create_thread(agent, message_id)
# Build a threaded reply manually
requests.post(
f"https://api.mailgun.net/v3/{MG_DOMAIN}/messages",
auth=("api", MG_API_KEY),
data={
"from": recipient, # send from the address that was hit
"to": sender,
"subject": f"Re: {subject}",
"text": "Thanks for getting back...",
"h:In-Reply-To": message_id,
"h:References": " ".join(thread.reference_chain + [message_id]),
},
)
# Persist the message before Mailgun's MIME window closes
save_message(agent, thread, payload)The Mailgun code works. What it carries with it is the local-part parsing, the address-to-agent mapping, the thread reconstruction from RFC 5322 headers, the persistence layer, and the tenant isolation. All of that is code you write and maintain.
Identity, multi-tenancy, and self-serve agent signup
Mailgun's identity unit is a domain plus its routes. Subaccounts exist as a segmentation primitive for sending programs and IP pools, but the address that a message arrives at is a local part on a domain matched by a route. Multi-tenant isolation means writing per-tenant routing logic on a shared inbound endpoint, running separate subaccounts for reputation isolation, and building a per-tenant durable store.
AgentMail's identity unit is the Inbox. Inboxes group into Pods, and Pods isolate tenants at the infrastructure level. API keys scope to a pod or to a single inbox, so a credential issue in one tenant's environment can't reach another's mail. Provisioning a new inbox at customer signup is one API call. Scoped webhooks send events for a specific pod or a specific inbox to their own endpoint, so your application handler isn't sorting through the whole organization's mail stream.
For fully autonomous agents that need to bootstrap their own tooling without a human in the loop, AgentMail supports agent-initiated signup via x402: an agent can complete signup, pay for a plan, get an API key, and provision inboxes on its own. Mailgun requires a human to complete the signup flow before an API key exists, which is the correct default for most business accounts but a hard blocker for autonomous agent workflows that provision infrastructure at runtime.
Migrating from Mailgun to AgentMail
Teams that started on Mailgun for outbound and added inbound through routes often end up building an inbox layer on top: a database for messages, a catch_all() route with a webhook handler, per-agent routing on the local part, and a threading job that reconstructs conversations from headers. The AgentMail migration replaces that custom layer with a real Inbox object.
Outbound is the smaller change. POST /v3/{domain}/messages on Mailgun becomes client.inboxes.messages.send on AgentMail (see the Quickstart). Inbound is the larger change: the catch_all() route plus webhook plus database plus threading code gets replaced by per-inbox provisioning, the message.received event, and client.inboxes.messages.reply for threaded replies. Mailgun and AgentMail can run side-by-side during the transition, with Mailgun continuing to handle high-volume outbound or complex regex-based routing and AgentMail handling the agent inbox surface.
For teams primarily on Mailgun for email validation before sending, that surface can stay on Mailgun independently. AgentMail focuses on the inbox side of the problem and interoperates with any pre-send validation layer.
Choosing between them
Both work for what they're built for. Pick Mailgun if your workload is send-first and you're ready to build the inbox layer on top yourself. Pick AgentMail if your workload is inbox-first and you want the platform to handle threading, persistence, per-agent identity, framework integration, prompt-injection defense, and (if you need it) BYOC deployment.
The Free plan provisions real inboxes with full sending and receiving. No credit card required.
AgentMail gives your agents real inboxes. Create inboxes via API. Send and receive Emails with 0 complexity. Free to start.

