Browser Use is one of the fastest-growing open-source projects in the agent space. It hands an LLM the keys to a real Chromium instance — plan a goal in natural language, and the model clicks, types, and scrolls its way through the web. It works beautifully on read-only sites. It falls apart the second it hits an email verification wall.

The email wall that stops 80% of agent flows

Go to almost any modern web service and the first thing you hit is a signup screen. Enter an email. Click a verification link. Enter a 6-digit code. Maybe pass 2FA. This is the single biggest blocker for autonomous browser agents today. Browser Use can navigate the form, but it has no inbox to receive the code.

The naive fix is to pass your own Gmail credentials to the agent and poll IMAP. That breaks immediately:

  • Collision: run two signups in parallel, you get two OTPs in one inbox — which one belongs to which browser session?
  • Identity leak: every account the agent creates is tied to your personal email. Spam, flags, bans.
  • Rate limits: Gmail throttles aggressive IMAP polling. Your agent stalls.

Lumbox solves this by giving every Browser Use session a disposable, fully-isolated email address with a long-poll API that blocks until the code arrives.

The pattern: inbox per agent run

The rule of thumb: one Lumbox inbox per Browser Use task. Create it when the agent starts, destroy it (or let it expire) when the task finishes. No sharing, no cross-contamination.

import { Lumbox } from "lumbox";
import { Agent } from "browser-use";

const lumbox = new Lumbox({ apiKey: process.env.LUMBOX_API_KEY });

async function runSignup(taskDescription: string) {
  const inbox = await lumbox.inboxes.create({ displayName: "signup-bot" });

  const agent = new Agent({
    task: `Sign up for example.com using email ${inbox.address}.
           When asked for a verification code, wait for it and enter it.`,
    llm: "anthropic/claude-opus-4-7",
    tools: [
      {
        name: "wait_for_otp",
        description: "Block until the verification OTP arrives",
        execute: async () => {
          const { otp } = await lumbox.inboxes.waitForOtp(inbox.id, {
            timeout: 120,
          });
          return otp;
        },
      },
    ],
  });

  const result = await agent.run();
  await lumbox.inboxes.delete(inbox.id);
  return result;
}

Why long-poll beats a tool-loop

A common mistake is asking the LLM itself to poll. "Check the inbox, if no email, check again." You burn tokens, hit rate limits, and the agent still times out half the time. Lumbox's waitForOtp endpoint holds the HTTP connection open server-side for up to 120 seconds and returns the parsed code the instant an email arrives. One tool call, deterministic, agent-loop friendly.

Verification links and magic links

const { link } = await lumbox.inboxes.waitForLink(inbox.id, { timeout: 120 });
await agent.execute(`navigate to ${link}`);

Scaling to many concurrent agents

When you need to run 50 signups in parallel — building a dataset, stress-testing, auditing competitors — each Browser Use session gets its own Lumbox inbox and nothing collides. With a shared Gmail, 50 near-simultaneous OTPs are impossible to route correctly. Per-session inboxes are the only answer.

Grab an API key at lumbox.co. First 1,000 inboxes free.