Skip to content

Zapdev-labs/openagentmail

Repository files navigation

OpenAgentMail

Self-hosted, open-source email infrastructure for AI agents — an AgentMail-compatible API that gives autonomous agents their own real email inboxes they can send from, receive into, search, label, and reply to, entirely over a REST API.

Inspired by AgentMail. This is an independent, MIT-licensed reimplementation you can run on your own infrastructure.

Why

Traditional email (Gmail, IMAP/SMTP) is built for humans: OAuth flows, per-seat pricing, rate limits, no clean programmatic identity. Agents need the opposite — spin up an inbox in milliseconds, a first-class address on the internet, two-way threaded conversations, webhooks, and search, all via an API key. OpenAgentMail provides that, self-hosted.

Features

  • Inboxes — create thousands of programmatic inboxes (name@your-domain), each a real mailbox.
  • Send / receive / reply — full two-way email with RFC-correct threading.
  • Threads & messages — conversation grouping, extracted_text (quoted history stripped), attachments.
  • Drafts — human-in-the-loop: create → review → send.
  • Labels + AI auto-labeling — classify inbound mail with natural-language rules.
  • Semantic search — vector search over all messages (pgvector + embeddings).
  • Webhooks — signed (HMAC-SHA256), retried event delivery. message.received, message.sent, message.delivered, …
  • Realtime — Server-Sent Events stream for live agents and the console.
  • Web console — Next.js + shadcn/ui with the sidebar block.
  • TypeScript SDK — AgentMail-compatible client.
  • Local-first — runs fully offline (MailHog relay, local embeddings). Flip env vars to go to production.

Architecture

apps/
  api/     Hono REST API + inbound SMTP server + webhook worker + SSE   (@oam/api)
  web/     Next.js + shadcn/ui console                                  (@oam/web)
packages/
  core/    types, crypto, email parsing/threading/extraction, AI        (@oam/core)
  db/      Drizzle schema + Postgres/pgvector client + migrations       (@oam/db)
  sdk/     TypeScript client SDK                                        (@oam/sdk)

Data model mirrors AgentMail: organization → inbox → thread → message → attachment, plus drafts, labels, webhooks, and vector embeddings.

Quickstart (Docker)

cp .env.example .env
docker compose up --build

This starts Postgres+pgvector, MailHog (outbound capture, UI at http://localhost:8025), the API (http://localhost:3001), and the console (http://localhost:3000). On first boot the API migrates the DB and seeds a root API key — copy it from the api container logs:

docker compose logs api | grep "am_live_"

Open the console at http://localhost:3000, go to Settings, and paste the key.

Quickstart (local dev)

Requires Bun 1.3+, Node 20+ (for tsx/drizzle-kit), and a pgvector Postgres (e.g. docker compose up -d postgres mailhog). Tasks are orchestrated with Turborepo.

bun install
cp .env.example .env

bun db:generate      # generate SQL migrations from the schema
bun db:migrate       # apply them (also creates the pgvector extension)
bun db:seed          # prints your root API key — save it

bun dev              # turbo: api on :3001, web on :3000, inbound SMTP on :2525

Using the API

export KEY=am_live_...

# Create an inbox
curl -X POST localhost:3001/v0/inboxes -H "authorization: Bearer $KEY" \
  -H 'content-type: application/json' -d '{"username":"support"}'

# Send a message
curl -X POST localhost:3001/v0/inboxes/<inbox_id>/messages/send \
  -H "authorization: Bearer $KEY" -H 'content-type: application/json' \
  -d '{"to":"someone@example.com","subject":"Hi","text":"Hello from my agent"}'

Or with the SDK (see examples/agent.ts):

import { AgentMailClient } from "@oam/sdk";

const client = new AgentMailClient({ apiKey: process.env.AGENTMAIL_API_KEY! });
const inbox = await client.inboxes.create({ username: "support" });
await client.inboxes.messages.send(inbox.inbox_id, {
  to: "customer@example.com",
  subject: "Welcome",
  text: "An AI agent will reply here.",
});

Receiving mail locally

The inbound SMTP server listens on :2525. To test receiving, point a sender at it (e.g. swaks --server localhost:2525 --to support@agentmail.local) or configure your domain's MX record to your host in production.

API reference (v0)

Resource Endpoints
Inboxes POST/GET /v0/inboxes, GET/PATCH/DELETE /v0/inboxes/:id, POST /v0/inboxes/:id/api-keys
Messages GET /…/messages, GET /…/messages/:id, POST /…/messages/send, POST /…/messages/:id/reply, PATCH /…/messages/:id (labels)
Threads GET /…/threads, GET /…/threads/:id, GET /v0/threads (org-wide)
Drafts POST/GET /…/drafts, GET/DELETE /…/drafts/:id, POST /…/drafts/:id/send
Attachments GET /…/attachments/:id
Labels GET/POST /v0/labels, DELETE /v0/labels/:id
Webhooks GET/POST /v0/webhooks, PATCH/DELETE /v0/webhooks/:id
Search POST /v0/search (semantic)
Events GET /v0/events/stream (SSE)

Auth: Authorization: Bearer <api_key>. Keys are org-level or inbox-scoped.

Going to production

  • Resend (recommended): set OUTBOUND_DRIVER=resend, INBOUND_DRIVER=resend, RESEND_API_KEY, verify EMAIL_DOMAIN in Resend Domains. Point API_BASE_URL at a public HTTPS URL, run bun run register-resend-webhook, set RESEND_WEBHOOK_SECRET. Agents use the OpenAgentMail API; Resend sends/receives mail.
  • SMTP fallback: INBOUND_DRIVER=smtp + MX to your host; OUTBOUND_DRIVER=smtp + SMTP_OUTBOUND_*.
  • AI: set OPENAI_API_KEY to use real embeddings + LLM labeling/extraction (falls back to local otherwise).
  • Storage: set STORAGE_DRIVER=s3 with S3_* for attachment storage.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages