Handling inbound email

Operations

Three ways to receive mail in your agent. They compose — you can use more than one.

The three options

WebSocketHTTP webhookPolling
LatencyReal-time (sub-second)Real-time (sub-second)Whatever your interval is
Needs public URL?NoYesNo
Durable / retried?No — push only while connectedYes — delivery retried on failureYes — you own the cursor
Best forAgent turns waiting inline for a reply or 2FA codeServer-side workers, background processing, persistent storageBatch jobs, scheduled digests

WebSocket — in-line intake

The simplest pattern for an agent that's actively reasoning about email. Open a socket, subscribe, wait for the event, act on it, close. No webhook receiver to deploy.

import WebSocket from "ws";

const ws = new WebSocket("wss://myagentmail.com/v1/ws", {
  headers: { "X-API-Key": process.env.MYAGENTMAIL_KEY }
});

ws.on("open", () => {
  ws.send(JSON.stringify({
    type: "subscribe",
    event_types: ["message.received"],
    inbox_ids: [process.env.INBOX_ID]
  }));
});

ws.on("message", (raw) => {
  const frame = JSON.parse(raw.toString());
  if (frame.type === "event" && frame.event_type === "message.received") {
    console.log("New reply from", frame.message.from);
  }
});

See Receiving 2FA codes inline for the full signup-and-wait-for-code flow.

HTTP webhooks — durable fan-out

When you want guaranteed delivery to a long-running service — crm sync, support ticket creation, logging — register a webhook. Every event is POSTed to your URL with an HMAC signature header.

curl -X POST https://myagentmail.com/v1/webhooks \
  -H "X-API-Key: tk_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/myagentmail",
    "events": ["message.received", "message.bounced"]
  }'

Response includes a secret. Verify incoming payloads with HMAC-SHA256 using that secret.

Polling — when you own the schedule

Simplest path. Good for batch jobs, daily digests, or environments where you can't open WebSockets and don't have a public URL.

curl "https://myagentmail.com/v1/inboxes/INBOX_ID/messages?direction=inbound&limit=50" \
  -H "X-API-Key: tk_your_key"

Track the most recent message ID you've processed and filter client-side, or rely on isRead flipping to true after you fetch each message.

Using them together

Nothing stops you from using all three. A common setup: an HTTP webhook writes every inbound message to your database (durable), a WebSocket powers the agent's in-line "wait for reply" turns (fast), and nightly polling reconciles any gaps (safety net).