Give your AI agent its own email inbox – MailKite MailKite launched a service that gives AI agents their own email inboxes on custom domains, enabling autonomous email handling without IMAP or MIME parsing. Developers can either run agents themselves via webhooks or let MailKite manage the agent loop, with inbound emails arriving as parsed JSON and replies sent through the Send API. Give your AI agent its own email inbox Give an AI agent a real, scoped address on a domain you control. Inbound mail arrives as parsed JSON to an event.received loop and the agent replies over the Send API, or MailKite runs the agent for you on a route with action: agent. Working code, the security caveat, and the honest DIY alternatives. An AI agent with its own email inbox is an autonomous program that owns a real address on a domain you control, so it can receive verification codes, be handed work by email, and reply on its own without a human in the loop. This post is for a developer wiring an agent to an inbox for the first time, and it shows two ways to build one: run the agent yourself inbound mail arrives as parsed JSON, your handler calls your model, the agent answers with one mk.send , or let MailKite which we build run it for you with a route whose action is agent . Either way there’s no IMAP, no MIME parsing, and no personal Gmail account quietly wired into a bot. Here’s the bring-your-own-agent loop, whole. 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 = { // signature check, 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; // Treat the body as untrusted INPUT, never as 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 ; That’s a fully autonomous email agent: it hears, it thinks, it answers. mk.send returns { id, status } so you can log the outbound message, and the identical handler shape exists for Python, Ruby, Go, PHP, and Java; see the receiving docs /docs/receiving and sending docs /docs/sending . Raw HTTP works too if you can’t take a dependency, but you’d be hand-rolling the HMAC verify that verifyWebhook does in one line; prefer the SDK. What actually lands at your handler MailKite decodes the message at the edge, so runAgent gets fields, not MIME. This is the same inbound webhook /docs/receiving from the pillar: decoded text and html , a resolved threadId , attachments as short-lived signed URLs, and an auth block: { "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": "