Handling inbound email
Three ways to receive mail in your agent. They compose — you can use more than one.
The three options
| WebSocket | HTTP webhook | Polling | |
|---|---|---|---|
| Latency | Real-time (sub-second) | Real-time (sub-second) | Whatever your interval is |
| Needs public URL? | No | Yes | No |
| Durable / retried? | No — push only while connected | Yes — delivery retried on failure | Yes — you own the cursor |
| Best for | Agent turns waiting inline for a reply or 2FA code | Server-side workers, background processing, persistent storage | Batch 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).