AI agents
Agents need a browser that behaves like the web actually behaves: JavaScript, logins, redirects, and pages that only render on a real engine. BrowserGen gives each agent task a disposable Chromium it can drive with the tooling you already use, plus a live view for the human in the loop.
The session-per-task pattern
Treat sessions like processes: create one when a task starts, end it when the task ends. Isolation comes free (fresh browser, no shared cookies between tasks) and a crashed task never poisons the next one.
import { chromium, type Browser } from "playwright";
// One session per agent task: isolated state, isolated failure domain.
export async function withBrowser<T>(run: (browser: Browser) => Promise<T>) {
const session = await fetch("https://api.browsergen.com/v8/web/sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BROWSERGEN_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ timeout: 900 }),
}).then((r) => r.json());
console.log("Watch this run live:", session.liveViewUrl);
const browser = await chromium.connectOverCDP(session.connectUrl);
try {
return await run(browser);
} finally {
await browser.close();
// Free the slot immediately instead of waiting out the grace period.
await fetch(`https://api.browsergen.com/v8/web/sessions/${session.id}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.BROWSERGEN_KEY}` },
});
}
}liveViewUrl in your agent traces turns every browser step into something a human can open and watch, mid-run or after the fact while the session is alive.Exposing the browser as a tool
Most agent frameworks share the same shape: a named tool with a schema and an async handler. Wrap your browser actions in tools and keep the session handling inside the helper:
// LangChain-style tool wrapping a BrowserGen-backed browser action.
import { tool } from "@langchain/core/tools";
import { z } from "zod";
const readPage = tool(
async ({ url }) =>
withBrowser(async (browser) => {
const page = browser.contexts()[0].pages()[0];
await page.goto(url, { waitUntil: "domcontentloaded" });
return await page.innerText("body");
}),
{
name: "read_page",
description: "Open a URL in a real browser and return its visible text.",
schema: z.object({ url: z.string().describe("The page to open") }),
},
);The same pattern maps to any framework with function/tool calling: define the action, run it inside withBrowser, and return text the model can reason over.
Practical guidance
- Set tight timeouts. Agent steps are short; a
timeoutof 300 to 900 seconds keeps runaway loops from holding concurrency. - Use geo targeting for localized tasks. Price checks, availability checks and consent walls often depend on the exit country; pass
countryat creation. - Escalate to a human via the live view. When the agent detects a captcha or an unexpected login, pause and hand the live-view URL to a person: they solve it in the browser, the agent continues in the same session.
- Watch your quota.
GET /web/usagereports used and available slots so a scheduler can queue tasks instead of hitting denials.