Sandeep Panda
Blog

I built an open-source AgentMail alternative on Cloudflare Workers

Every agent gets its own inbox on your Cloudflare account. Receive mail, wait for the code, reply in thread, webhooks, MCP. One Worker.

By Sandeep Panda
10 min

tldr: dearagent.sh is an open-source, self-hosted email inbox API for AI agents, the alternative to AgentMail that runs on your Cloudflare account. This is what it does, why I run it for Bug0 and Hashnode instead of a hosted plan, and how to run it in a few minutes.

Every agent I run eventually reaches a signup form. It fills in a name, makes up a password, types an email address and clicks the button. Then the service does what every service does. It sends a six-digit code to that address and waits for someone to read it. What the agent needs at that moment is an email API for AI agents, an inbox of its own that it can wait on, and it does not have one.

The address is mine, so the someone is me. The agent has done everything up to that point without help. The one step that needs an email address turns it back into a tool with a person in the loop, and the person is not looking.

So I gave my agents addresses of their own. dearagent.sh runs on my Cloudflare account, and the code is at github.com/panda-sandeep/dearagent.

What I built

dearagent gives every agent its own inbox, running entirely on your Cloudflare account. It receives mail, waits for the verification code, replies in thread, sends new mail, and fires a webhook when something arrives. One Worker, one repo, no servers.

From the agent's side it looks like this:

> create_inbox {}
✓ agent-k3m9x2pq@mail.example.com

# hand the address to the signup form

> wait_for_message { inbox: "agent-k3m9x2pq@mail.example.com", timeout: 25 }
✓ from: Pied Piper <no-reply@piedpiper.example>
  subject: Your verification code
  text: "Your code is 493021. It expires in 10 minutes."
Sequence diagram: an AI agent creates an inbox, hands the address to a signup form, calls wait_for_message, and receives the verification code
Sequence diagram: an AI agent creates an inbox, hands the address to a signup form, calls wait_for_message, and receives the verification code

The same operations exist over REST. The MCP server exposes fifteen tools, and wait_for_message is the one that matters. It blocks for up to 25 seconds until mail arrives, so the agent asks once and gets the message back, instead of polling an inbox in a loop and reading yesterday's mail by mistake.

Under the hood there is nothing exotic. Cloudflare Email Routing delivers inbound mail to the Worker's email() handler. Messages go into D1, attachments into R2. Outbound mail goes through Cloudflare Email Sending. Agents talk to it over REST with a bearer key, or over MCP at /mcp on the same Worker.

Architecture of dearagent: Cloudflare Email Routing delivers mail to a Worker that stores messages in D1 and attachments in R2, fires signed webhooks, and serves agents over REST and MCP, with outbound mail through Cloudflare Email Sending
Architecture of dearagent: Cloudflare Email Routing delivers mail to a Worker that stores messages in D1 and attachments in R2, fires signed webhooks, and serves agents over REST and MCP, with outbound mail through Cloudflare Email Sending

Two details I cared about more than I expected to. Messages are threaded by the In-Reply-To and References headers, never by subject, because automated mail reuses subjects constantly and merges into one thread if you let it. And webhooks are HMAC-signed and retried, so "do something when mail arrives" is a real integration point rather than a best-effort ping.

What is an email API for AI agents

An email API for AI agents gives a program its own inbox and a way to read what arrives, wait for a specific message, and reply, with no human mailbox and no mail client in the loop. The receiving side is the part that matters. Sending APIs have existed for more than a decade.

The obvious tools are the wrong shape for this. Gmail is a person's mailbox. Getting an agent into one means an OAuth consent screen, one Google account per inbox, and limits designed around a human reading mail. Transactional APIs like SendGrid and Postmark are built around sending. Where they take inbound mail, they hand you a webhook, not an inbox an agent can wait on.

What fits is an inbox per agent, addressable by API, with a "wait until mail arrives" primitive. AgentMail built that as a hosted service. dearagent is the version you run yourself.

AgentMail alternative, self-hosted

dearagent is the open-source alternative to AgentMail: the same inbox-per-agent idea, run on your own Cloudflare account instead of a hosted plan.

AgentMail had the idea right. An inbox per agent with an API and an MCP server is the correct product, and they got there first. There is nothing to deploy. Claude Code and Cursor can use an inbox through AgentMail's MCP server without glue code. There are plans with organization seats, an official OpenClaw plugin, and a team whose whole job is keeping it up. If you want an agent inbox this afternoon and you want someone else on call for it, that is the right product.

The trade is what any hosted inbox asks of you. The mail lives in their cloud. The plans count inboxes, so an agent that spins up a fresh address per task is spending quota. And you cannot read the source, so when something about threading or retention does not fit, you file a ticket instead of changing it.

For me the first of those is the one that decides it. An agent's inbox holds signup credentials, password resets and magic links for every service that agent has touched. Multiply that by every agent you run and that mailbox is the most sensitive thing you own. I already pay Cloudflare. I can read the source of a Worker. I would rather that mail sat on infrastructure I control, and I would rather not count inboxes.

Hosted inbox APIs dearagent
Where mail lives Their cloud Your Cloudflare account: D1 for mail, R2 for attachments
What it costs A plan with per-inbox or per-message limits Your Workers bill. Receiving runs on the free plan
Source Hosted only One repo you can read, tests that run in the real Workers runtime
Tenancy Hosted, with organization seats per plan Single-tenant, one API key. Put it behind your own auth for per-agent scoping

Try it before you deploy anything

dearagent.sh creates a real inbox for you on the public demo instance when the page loads. Send it an email from anywhere and watch it arrive on the page. Demo addresses live for fifteen minutes and demo mail is not kept.

Running your own is three commands:

git clone https://github.com/panda-sandeep/dearagent && cd dearagent
npm install
npm run setup

The setup script creates the D1 database and the R2 bucket, offers to generate the API key and store it as a secret, enables Email Routing on your domain, asks before enabling Email Sending since that needs Workers Paid, and deploys the Worker, which adds the catch-all rule so every address at the domain reaches it.

You need four things:

  • A Cloudflare account.
  • An apex domain that receives no mail today, dedicated to Cloudflare Email Routing. A domain already on Google Workspace or Fastmail cannot be used for receiving, because Email Routing has to own the MX records.
  • Workers Paid, only if you send. Receiving is free.
  • Node 20 or newer, with npx wrangler login done.

If you use Claude Code, the last step is one line:

claude mcp add --transport http dearagent https://dearagent.<you>.workers.dev/mcp \
  --header "Authorization: Bearer $KEY"

After that, create_inbox and wait_for_message show up as tools, and the repo ships a skill file that teaches the agent the loop: get an address, note the time, wait, read, act.

How I use it

It runs in production for both products I work on, Bug0 and Hashnode, and the job is the same in each: an agent has to get through email to finish its work.

Bug0 tests web apps the way a user does, in a real browser. It runs about 5,000 tests a day, and most test suites include a signup flow somewhere. Signups are only the start of it. Customers' apps send one-time codes, magic links, billing confirmations and payment receipts, and a test that cannot read that mail cannot check the flow that sent it. That used to be the point where an automated test needed a human, a shared test mailbox, or a fixture that skipped the step and tested nothing. Now each run creates an address of its own, hands it to the form, and calls wait_for_message. Whatever it was waiting for comes back, and the run carries on. Nothing is shared between runs because each one has a fresh address, and the address carries a TTL in its name so that run's mail is marked to expire and the daily purge clears it.

At Hashnode the direction is reversed. Hashnode sends mail all day, magic links, notifications, newsletters, and the question is whether what leaves the system arrives and reads correctly. An agent creates a fresh inbox, triggers the flow, waits for the message, and checks what landed. A broken email fails a check before a reader sees it.

Two production uses of dearagent: Bug0 test runs receive verification codes through fresh TTL addresses; Hashnode agents check outbound magic links, notifications and newsletters
Two production uses of dearagent: Bug0 test runs receive verification codes through fresh TTL addresses; Hashnode agents check outbound magic links, notifications and newsletters

Each product has its own deployment on its own domain with its own key. Both are the same Worker from the same repo.

What it does not do yet

It is experimental. It works end to end, but it has not had an in-depth audit and the API may still change. Read the code before you point it at anything sensitive.

It is single tenant. One API key grants access to every inbox on the server. If several agents or people share a deployment, put it behind Cloudflare Access or your own gateway.

Sending needs Workers Paid. Receiving works on the free plan.

Receiving needs an apex domain with no existing mail. Sending has no such restriction and works from any domain or subdomain you verify, so you can send from a subdomain of a domain that receives mail elsewhere. You just cannot receive there.

And a rule that applies to every agent inbox, hosted or not: anything an agent can read from an inbox, a sender can put there. Treat inbound mail as untrusted input to the agent.

The code is at github.com/panda-sandeep/dearagent. The next thing I am building is a hosted version of it, for people who want the same inbox without running the Worker themselves. The self-hosted one stays open source either way.

FAQ

What is the best email service for AI agents?

It depends on who you want running it. AgentMail is a hosted service with plans and support. dearagent is open source and runs on your own Cloudflare account, so the mail and the bill are yours. Both give an agent its own inbox with an API and an MCP server.

How do I set up dearagent?

Clone the repo, run npm install and npm run setup. The setup script creates the database and bucket, generates the API key if you say yes, enables Email Routing, asks before enabling Email Sending, and deploys the Worker with the catch-all rule. You need a Cloudflare account and an apex domain that receives no mail today.

Does it work with Claude Code and Cursor?

Yes. The Worker exposes an MCP server at /mcp with fifteen tools, including wait_for_message, which blocks until mail arrives. Add it to Claude Code with claude mcp add --transport http and the bearer key. The repo also ships a skill file that teaches an agent the wait-then-read loop.


dearagent is open source under the AGPL-3.0 license.

#ai#developer-tools#cloudflare#open-source#agents

Discussion

Add a comment

No comments yet — start the conversation on Hashnode.

More writing

All writing