Skip to content
Agent Orchestration
Skill

/e2a

Use when operating an already-connected e2a inbox over MCP: reading, composing, sending, replying, forwarding, handling attachments, managing contacts/outreach, scheduling mail, or using templates. Teaches correct threading, conversation correlation, concise multipart

BOOST
From plugin
e2a
1949 skills1 MCP
Install
$ npx -y skills add tokencanopy/e2a --skill e2a --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/e2a

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when operating an already-connected e2a inbox over MCP: reading, composing, sending, replying, forwarding, handling attachments, managing contacts/outreach, scheduling mail, or using templates. Teaches correct threading, conversation correlation, concise multipart

SKILL.md

e2a.SKILL.md
name: e2a
description: "Use when operating an already-connected e2a inbox over MCP: reading, composing, sending, replying, forwarding, handling attachments, managing contacts/outreach, scheduling mail, or using templates. Teaches correct threading, conversation correlation, concise multipart composition, and accepted/pending-review no-retry behavior."
version: 29

Using e2a

<!-- version: 29 -->

e2a is the open-source email API for applications and AI agents. This operate-well skill focuses on agent-owned inboxes: it gives an agent a real two-way address (`agent@agents.localhost` or `agent@example.com`), evaluates SPF, DKIM, and DMARC as structured evidence about the From domain, and threads conversations. That evidence does not prove a person, mailbox, or message content.

How this fits

This file is the **operate-well manual** — the mental model and gotchas. It assumes you're already connected over MCP (the tools appear as `mcp__e2a__*`).

  • **Connect, authorize, select/create an inbox, or configure a custom domain** → use `e2a-setup`.
  • **Add e2a sending, receiving, SDK, REST, or webhook code to an application** → use `e2a-integrate`.
  • **Investigate a failing connection, inbox, domain, webhook, or delivery** → use `e2a-doctor`.
  • **Exact, current tool signatures** → call `tools/list` (authoritative).

The mental model below holds regardless of surface. Tool descriptions teach the precise per-tool contract; this file teaches the model the descriptions assume.

The mental model

Six load-bearing facts. Internalize these before you start calling tools.

1. **An agent is an email address.** `support-bot@agents.localhost` is an agent. When you send mail, the recipient sees a message FROM that address — not from "the user." When you list messages, you are reading the agent's own inbox, not the user's personal mail. You are not a secretary; you are the mailbox owner.

2. **Replies preserve threads; new sends do not.** `reply_to_message` carries the `In-Reply-To` and `References` headers from the original message, so the response lands in the same email thread. A fresh `send_message` creates a new thread every time. If a user (or an inbound message) is asking you to respond to something specific, reply with the original `message_id` — even when you could synthesize an equivalent body as a new send. Thread fragmentation is the #1 visible symptom of getting this wrong.

**Email topology and application correlation do not share a key.** Gmail, Outlook, and Apple Mail thread on RFC `Message-ID` / `In-Reply-To` / `References` plus a **stable `Subject`**. `reply_to_message` sets those headers correctly. `conversation_id`, which backs `list_conversations` / `get_conversation`, is caller-owned workflow correlation: a fresh `send_message` with the same value is still a separate email thread, while a reply with a changed value stays in its parent's email thread. REST message reads may expose optional beta `thread_id`, a server-owned mailbox-local topology identity, but MCP deliberately omits it and provides no thread filter or endpoint. Within one ongoing exchange: reply, and keep the subject stable.

**Bind email to the agent runtime's conversation.** When received mail starts or resumes a coding-agent task, establish the runtime thread before replying. If the inbound `conversation_id` matches a binding your integration previously stored, resume that internal thread; otherwise create a new internal thread. When the runtime exposes a stable, non-sensitive thread/session ID, pass it as `conversation_id` on the first reply and reuse it on later sends and replies. If its native ID is sensitive or does not meet e2a's 200-character, no-CR/LF constraint, store and pass an opaque alias instead. This keeps e2a's application-conversation view aligned with the agent's memory, but it does **not** replace replying with the original `message_id`, which is what preserves the recipient's email-client thread. Treat `conversation_id` as correlation data, never authorization.

3. **`pending_review` is an accepted outcome, not a retry signal.** A send can return `{ status: "pending_review", message_id: "msg_..." }`. The server accepted the message but did not dispatch it. Do not retry: another call can create a duplicate. Report the status and message ID to the user, then stop.

4. **Account-scoped sessions need an explicit inbox.** `whoami` tells you the credential scope and returns `agent_email` only for an agent-scoped credential. An account-scoped MCP session never guesses a default, even when the account has one inbox: enumerate once with `list_agents`, then pass the tool's `email` field explicitly. Don't guess or pick at random; use the user's stated context when it clearly identifies an inbox.

5. **Most users don't need a custom domain — default to the shared one.** Every account can create agents on the shared `agents.e2a.dev` domain with zero DNS setup: call `create_agent` with the full address (for example, `support-bot@agents.e2a.dev`), and it is live immediately. This is the right default for onboarding and for anyone who doesn't already **own** a domain. Only reach for a custom domain when the user explicitly owns a domain and wants branded addresses — if they don't own one, stay on `agents.e2a.dev` and skip the domain flow entirely. Don't send a user who just wants to get started down the DNS dance.

6. **Custom domains are a two-step async dance.** `register_domain` returns DNS records (MX + TXT) to publish — it does NOT make the domain live. The user (or a DNS-provider MCP, such as [Cloudflare MCP](https://github.com/cloudflare/mcp), if one is loaded) must add those records out-of-band, wait for DNS propagation (minutes to hours), then `verify_domain`. Verification is idempotent and safe to retry. Until verification succeeds, the domain cannot send or receive mail. Don't promise the user their domain works the moment registration returns.

Common workflows

Optional: requir

Read more
Ships withe2a

Open-source email API for applications and AI agents. Managed hosting at e2a.dev, or self-host with Docker.

Get the whole plugin

Other skills on e2a.