Launch-Free 3 months Builder plan-
Pixel art lobster working at a computer terminal with email — WebSocket real-time email notifications agents

real-time email notifications for AI agents: polling, webhooks, and WebSockets compared

Your agent shouldn't poll for email every 30 seconds. Here's how WebSockets, webhooks, and polling compare for real-time agent notifications.

8 min read
Ian Bussières
Ian BussièresCTO & Co-founder

Your agent just signed up for a service. A verification code landed in its inbox four seconds ago, but the agent won't find out for another 26 seconds because it's polling on a 30-second interval.

That delay sounds trivial until you're watching it happen. The agent sits idle, burning compute on repeated API calls that return empty arrays, while the email it needs is already waiting. For verification codes and time-sensitive alerts, the gap between "instant" and "half a minute from now" is the gap between a smooth workflow and a user staring at a spinner.

There are three approaches to real-time email notifications for agents: polling, webhooks, and WebSockets. Each comes with real tradeoffs, and the right choice depends on where your agent runs and how fast it actually needs to react. If you'd rather skip the infrastructure decisions and let your agent handle email out of the box, .

polling: the default everyone starts with#

Polling is straightforward. Your agent calls the email API on a fixed interval, checks for new messages, and processes anything that arrived since the last check.

import { LobsterMail } from '@lobsterkit/lobstermail';

const lm = await LobsterMail.create();
const inbox = await lm.getInbox('my-agent');

setInterval(async () => {
  const emails = await inbox.receive({ unread: true });
  for (const email of emails) {
    console.log(email.subject, email.from);
  }
}, 30_000);
It works. It's easy to debug. For many use cases, it's the right call.

The problems show up at scale. A 30-second polling interval means 2,880 API calls per inbox per day, whether or not a single email arrived. With 10 inboxes, that's 28,800 calls. The vast majority return nothing.

Tighter intervals reduce latency but multiply the overhead. A 5-second poll hits 17,280 calls per inbox per day. Your agent spends most of its time asking "anything new?" and hearing "no."

There's also a latency floor you can't eliminate. Even at a 5-second interval, the average delay between email arrival and agent notification is 2.5 seconds. For verification codes with 60-second expiry windows, those seconds count.

Polling makes sense when you're dealing with low-volume inboxes (a few emails per day), doing batch processing where latency is irrelevant, prototyping during early development, or running in an environment that can't receive inbound HTTP requests. Outside those cases, you're paying for a lot of empty responses.

WebSockets: persistent connections, instant notifications#

WebSockets solve the latency problem by keeping a bidirectional connection open between your agent and the email server. When a new message arrives, the server pushes a notification down the existing connection immediately.

const ws = new WebSocket('wss://mail-provider.example/v1/ws');

ws.on('message', (data) => {
  const event = JSON.parse(data);
  if (event.type === 'email.received') {
    console.log('New email:', event.payload.subject);
    processEmail(event.payload);
  }
});

ws.on('close', () => {
  setTimeout(() => connect(), 5000);
});

Notification latency drops to milliseconds. For workflows where timing is everything (two-factor auth codes, real-time customer support), that speed matters.

But WebSockets bring operational weight that polling doesn't.

Connection management is the biggest challenge. WebSocket connections drop when networks hiccup, servers restart, or load balancers time out idle sockets. Your agent needs reconnection logic with exponential backoff. It also needs to handle the gap: any emails delivered while the connection was down have to be fetched through a separate API call. You end up implementing polling as a fallback anyway.

Scaling introduces its own friction. Each connected agent holds an open socket on the server. Hundreds of connections are fine. Tens of thousands require careful connection pool management and fan-out architecture. If your agent runs in a serverless environment (Lambda, Cloud Functions, edge workers), maintaining a long-lived socket isn't practical at all.

State synchronization adds yet another layer. When your agent restarts, it needs to know which emails it already processed. WebSocket notifications are fire-and-forget by design. If the client missed one, it's gone. You need to track a cursor or timestamp on your side and reconcile on every reconnect.

Some email providers, including AgentMail, offer WebSocket connections for real-time events. The approach works well for always-on agents running on dedicated infrastructure. For agents that spin up on demand or live in serverless contexts, it's a harder fit.

webhooks: the server calls you#

Webhooks flip the model entirely. Instead of your agent reaching out to the email server, the server sends an HTTP POST to your agent's endpoint whenever something happens.

import express from 'express';

const app = express();
app.use(express.json());

app.post('/hooks/email', (req, res) => {
  const event = req.body;

  if (event.type === 'email.received') {
    console.log('New email from:', event.data.from);
    processEmail(event.data);
  }

  res.status(200).send('ok');
});

app.listen(3001);

No persistent connections to manage. No polling loops burning API quota. The server only calls your endpoint when there's actually something to deliver.

Latency is comparable to WebSockets in practice. The email server fires the webhook within seconds of delivery. The difference between a WebSocket notification at 50ms and a webhook at 1-3 seconds rarely matters for verification codes or payment confirmations.

Where webhooks pull ahead is reliability. Unlike WebSocket notifications, webhook systems include built-in retry logic. If your endpoint returns a 500 or times out, the email server retries with exponential backoff. Notifications don't vanish because your agent had a brief hiccup. LobsterMail's webhook system retries failed deliveries automatically, so your agent can survive short downtime without losing messages.

The one tradeoff: your agent needs a publicly reachable URL. During local development, that means a tunnel tool like ngrok or Cloudflare Tunnel. In production, your agent needs a stable endpoint. For most deployments this is already the case. For quick scripts running on a laptop, it's an extra step.

how LobsterMail handles real-time delivery#

LobsterMail gives agents two paths to real-time email notifications, depending on the deployment.

Webhooks are the primary mechanism. Register a URL, and LobsterMail sends a POST request whenever an email arrives at any of your agent's inboxes. The payload includes the full email content, headers, and security metadata with injection risk scoring.

import { LobsterMail } from '@lobsterkit/lobstermail';

const lm = await LobsterMail.create();

await lm.webhooks.create({
  url: 'https://my-agent.example.com/hooks/email',
  events: ['email.received'],
});

That's the full setup. Once registered, every inbound email triggers a notification. Failed deliveries retry automatically.

For cases where webhooks aren't practical, the SDK's receive() method handles polling with built-in pagination, deduplication, and filtering. Your agent calls inbox.receive(), gets back only unread messages, and moves on. No manual cursor tracking required.

The two approaches aren't mutually exclusive. A common pattern is using webhooks for time-sensitive emails (verification codes, payment confirmations) while running a periodic polling job for batch tasks like daily digests and report generation. The receiving emails guide walks through both modes in detail.

picking the right approach#

The decision comes down to where your agent runs, how fast it needs to react, and how much infrastructure complexity you're willing to carry.

If your agent runs continuously on a server or VM, webhooks are the strongest default. Low overhead, near-instant notification, automatic retries, no connection management. Register the endpoint once and stop thinking about it.

If your agent is serverless or spins up on demand, webhooks still work when you have a stable URL through an API Gateway, Cloud Run, or similar service. Without a reachable endpoint, polling with a tight interval during active workflows and a loose interval the rest of the time keeps things manageable without wasting API calls.

During local development, polling is the fastest way to start. The SDK handles it with inbox.receive(). When you move to production, add a webhook endpoint and use a tunnel for local testing.

WebSockets make sense when you need sub-100ms latency on a persistent connection and your infrastructure supports long-lived sockets. For most agent email workflows, webhooks deliver the same practical result with fewer moving parts.

The notification mechanism isn't the point. The real goal is making sure your agent reacts to incoming email fast enough that the workflow feels instant to the person on the other end. Whether that's a webhook firing in two seconds or a poll checking every five, the end user shouldn't notice the difference.

If your agent needs its own inbox with real-time notifications baked in, and your agent handles the rest.

Frequently asked questions

What's the difference between WebSockets and webhooks for agent email?

WebSockets maintain a persistent bidirectional connection for sub-100ms notifications. Webhooks are server-initiated HTTP POST requests sent when events occur. Webhooks are simpler to operate and include built-in retry logic, while WebSockets offer lower latency but require connection management and reconnection handling.

Does LobsterMail support WebSocket connections for email?

LobsterMail uses webhooks as its primary real-time notification mechanism. Webhooks deliver comparable latency for email workflows while being simpler to deploy and more reliable across hosting environments, including serverless platforms.

How fast do LobsterMail webhook notifications arrive?

Webhook notifications fire within seconds of email delivery. For verification codes, signups, and payment alerts, the delay is imperceptible to end users.

Can I use polling and webhooks at the same time?

Yes. A common pattern is using webhooks for time-sensitive emails and polling for batch processing like daily digests. The SDK supports both approaches and they work well together.

What happens if my webhook endpoint goes down?

LobsterMail retries failed webhook deliveries automatically with exponential backoff. Your agent won't miss emails during brief outages. See the webhooks docs for retry behavior details.

How do I test webhooks during local development?

Use a tunnel tool like ngrok or Cloudflare Tunnel to expose your local endpoint to the internet. Register the tunnel URL as your webhook, and LobsterMail will POST notifications to your local machine.

How many API calls does email polling use per day?

At a 30-second interval, one inbox generates 2,880 calls per day. At 5 seconds, it's 17,280. Webhooks eliminate this overhead entirely since the server only contacts your endpoint when an email actually arrives.

Is LobsterMail free to use?

The Free plan includes send and receive with up to 1,000 emails per month and no credit card. The Builder plan at $9/month adds up to 10 inboxes, 5,000 emails/month, and custom domain support.

Can my agent create its own inbox without human signup?

Yes. The SDK's LobsterMail.create() auto-provisions an account, and createSmartInbox() generates a readable email address from your agent's name. No manual configuration needed.

Do webhook payloads include email security metadata?

Every webhook payload includes the full email content, headers, and security metadata with injection risk scoring. See the security docs for how scoring works.

Can I use LobsterMail webhooks with serverless functions?

Yes. Webhooks pair well with AWS Lambda, Google Cloud Functions, Cloudflare Workers, and similar platforms. Point the webhook URL to your function's public endpoint and it works out of the box.

What events can I subscribe to with LobsterMail webhooks?

The primary event is email.received, which fires when any email arrives at your agent's inboxes. Check the webhooks documentation for the full list of supported event types.

Related posts