Your agent can reason, call tools, and hold a conversation. Then you ask it to handle email, and everything gets awkward. Email was built for a human sitting in front of a mail client, not for software. To make an agent "do email" today, most teams reach for one of two bad options: screen-scrape a Gmail account a human set up by hand, or bolt SMTP for sending onto IMAP for receiving and hope the OAuth tokens survive the night.
This post first appeared on the AgenticEmail blog.
The problem: email was built for humans, not agents
The moment you need two-way email - an agent that emails a customer and then reads the reply - you are wiring together three protocols that were never meant to be glued: SMTP to send, IMAP to poll, and OAuth to keep a borrowed human account alive.
That stack breaks in predictable ways. OAuth tokens expire and a refresh fails at 3am. IMAP is pull-based, so your agent sits in a polling loop diffing message lists instead of reacting to events. Inbound mail arrives as raw MIME - nested multipart bodies, quoted-printable encoding, base64 attachments - so your agent needs a MIME parser before it can read a single sentence. And because everything hangs off one shared mailbox, you cannot give each agent, or each of your users' agents, its own address without provisioning real mailbox seats.
None of this is the interesting part of your product. It is undifferentiated plumbing standing between your agent and the thing you actually want it to do.
The fix: an inbox is an API resource
AgenticEmail treats an inbox the way you already treat a database row. You create one with an API call, it has a stable id, and you send and receive through plain REST. No mail server to run, no IMAP loop, no OAuth dance. Inbound mail arrives already parsed into JSON, threaded into conversations, and pushed to you over a webhook or a WebSocket - or exposed to your model directly through a hosted MCP server.
Here is the whole loop.
1. Create an inbox
One POST gives your agent a live, addressable inbox:
curl -X POST https://api.agenticemail.dev/v1/inboxes \
-H "Authorization: Bearer $AGENTICEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "username": "billing-agent" }'
The response carries an id and a working address like billing-agent@inbox.agenticemail.dev. On paid plans you attach your own domain and it becomes billing-agent@yourcompany.com. Because provisioning is a single call, you can mint an inbox per agent, per user, or per task at runtime. Identity stops being a bottleneck.
2. Send
Sending is one call against the inbox. Pass recipients and a body; threading headers are handled for you:
curl -X POST https://api.agenticemail.dev/v1/inboxes/ibx_123/messages/send \
-H "Authorization: Bearer $AGENTICEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["customer@example.com"],
"subject": "Your July invoice",
"text": "Hi - your invoice for July is attached. Reply here with any questions."
}'
3. Receive parsed, threaded JSON
When someone replies, you never touch MIME. List the inbox and every message comes back as a flat object with from, to, subject, text, html, and attachments, already grouped into threads:
curl https://api.agenticemail.dev/v1/inboxes/ibx_123/messages \
-H "Authorization: Bearer $AGENTICEMAIL_API_KEY"
{
"data": [
{
"id": "msg_456",
"thread_id": "thr_789",
"direction": "inbound",
"from": "customer@example.com",
"subject": "Re: Your July invoice",
"text": "Got it, thanks. Can you resend with the PO number?",
"created_at": "2026-07-05T12:00:00Z"
}
],
"next_page_token": null
}
The thread_id ties the reply back to what you sent, so your agent gets the whole conversation as structured context - not a screenshot, not a raw .eml file it has to decode.
4. React over a webhook or an MCP tool call
Polling is optional. Register a webhook once and every inbound message is delivered to your endpoint as a signed JSON payload the instant it lands:
curl -X POST https://api.agenticemail.dev/v1/webhooks \
-H "Authorization: Bearer $AGENTICEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://your-app.com/hooks/email", "event_types": ["message.received"] }'
If your agent has no public URL - a local script, a serverless job, a notebook - subscribe to the WebSocket stream at wss://api.agenticemail.dev/v1/events instead and get the same payloads pushed to an outbound connection. Both paths are covered in the email webhook guide.
Or skip the plumbing entirely and let the model drive. The hosted MCP server exposes the whole API as native tools:
{
"mcpServers": {
"agenticemail": {
"url": "https://api.agenticemail.dev/mcp",
"headers": { "Authorization": "Bearer ${AGENTICEMAIL_API_KEY}" }
}
}
}
With that in place, your agent calls create_inbox, send_message, get_thread, and reply_to_message the same way it calls any other tool. "Create an inbox for onboarding, email new@example.com a welcome, and reply when they respond" becomes a single turn.
Scoped keys keep the blast radius small
An agent should never hold god-mode credentials. AgenticEmail keys are scoped: you can pin a key to a single inbox and a specific set of permissions, so a key that leaks - through a prompt injection, a logged header, a compromised dependency - can at worst read and send from its own inbox. It cannot touch your other inboxes or your account. Give each agent its own inbox and its own scoped key, and a bad day stays contained to one address.
Works with any MCP client
Because the integration is REST plus a standard MCP server, it is framework-agnostic. Claude, Cursor, and any other MCP-compatible client pick up the tools from the config above. In agent frameworks like LangChain, use the official SDKs or call the REST endpoints directly. There is nothing email-specific for your stack to support - it is just HTTP and a tool list.
Give your agent a real inbox
Two-way email should not be the hardest part of shipping an agent. Create an inbox with one call, send and receive as parsed JSON, react over a webhook or an MCP tool call, and scope the key so a leak is a shrug instead of an incident.
Start free at agenticemail.dev, connect the MCP server from the MCP docs, or read the full endpoint reference in the docs.
Top comments (0)