Skip to content

Add AgentMail as an alternative email channel #7

@mcheemaa

Description

@mcheemaa

Summary

Add AgentMail as an alternative email channel for inbound email and two-way conversations, alongside the existing channels.

Phantom already has outbound email via Resend (one API key, works out of the box). For inbound email and two-way conversations, the current option is IMAP/SMTP via ImapFlow + Nodemailer, which requires 8 credentials and manual IMAP configuration.

AgentMail provides a simpler alternative: one API key for both sending and receiving, with native threading, webhook-based inbound delivery, and automatic deliverability (SPF/DKIM/DMARC).

Current email capabilities

Capability Current solution Setup complexity
Outbound email Resend (already built, one API key) Easy
Inbound email IMAP via ImapFlow (8 credentials) Hard
Two-way threads IMAP + SMTP + manual header threading Hard

AgentMail would replace the IMAP/SMTP path with a single API key for both directions, while Resend remains the default for outbound-only use cases.

Why

The IMAP/SMTP channel requires IMAP host/port/user/pass, SMTP host/port/user/pass, plus configuring your email provider to allow IMAP access. AgentMail reduces two-way email to one API key and handles deliverability automatically.

This is additive. Resend stays as the default outbound channel. IMAP/SMTP stays for users who want full control. AgentMail adds an easier path for two-way email conversations.

What to build

Create src/channels/agentmail.ts implementing the Channel interface from src/channels/types.ts. Use the agentmail npm package (TypeScript SDK, works with Bun).

Requirements

  1. Implement AgentMailChannel class with all Channel interface methods
  2. Use the AgentMail SDK for sending and receiving emails
  3. Add a handleWebhook() method for inbound email via webhooks
  4. Wire the channel in src/index.ts (follow the pattern used for EmailChannel)
  5. Add a webhook route in src/core/server.ts at /agentmail/webhook
  6. Add a config section in config/channels.yaml (disabled by default)
  7. Write tests in src/channels/__tests__/agentmail.test.ts

Reference files

File What to learn from it
src/channels/types.ts The Channel interface to implement (4 methods)
src/channels/email.ts Existing IMAP/SMTP email channel (reference for email patterns)
src/channels/webhook.ts Webhook handling pattern
src/index.ts (channel registration block) How channels are wired at startup
src/core/server.ts Where to add the webhook route
CLAUDE.md Project standards, the Cardinal Rule, what NOT to do

AgentMail resources

Configuration

# config/channels.yaml
agentmail:
  enabled: false  # opt-in only
  api_key: \${AGENTMAIL_API_KEY}
  inbox_id: phantom@agentmail.to
  webhook_secret: \${AGENTMAIL_WEBHOOK_SECRET}

Environment variables

Variable Description
AGENTMAIL_API_KEY API key from agentmail.to dashboard
AGENTMAIL_WEBHOOK_SECRET Webhook verification secret (Svix-based)

Acceptance criteria

  • AgentMailChannel implements all Channel interface methods
  • Inbound email via webhooks converts to InboundMessage correctly
  • Outbound email sends via AgentMail SDK
  • Threading works (replies go to the correct thread)
  • Config-driven (disabled by default, enabled via channels.yaml)
  • Tests pass with mocked AgentMail client
  • bun run lint clean, bun run typecheck clean, bun test passes
  • No any types, no @ts-ignore, files under 300 lines
  • Existing email channels (Resend, IMAP/SMTP) are unchanged

Estimated scope

  • ~150-200 lines for agentmail.ts
  • ~100-150 lines for tests
  • ~15 lines in index.ts (registration)
  • ~10 lines in server.ts (webhook route)
  • ~5 lines in channels.yaml (config section)
  • 1 line in package.json (bun add agentmail)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions