facebook pixel
Skip to content

toolBrowser Control6 min read

agent-browser

Our take
The browser tooling in most agent setups was built for test scripts and then handed to an agent, and the context bill is why teams quietly turn it off. This one was built for the agent. If you run the Browser Verification Loop and it feels too expensive to leave on, this is the fix.

Vercel Labs' Rust CLI that drives Chrome for coding agents. Accessibility snapshots with stable refs instead of DOM dumps, React fiber introspection, Core Web Vitals, an embedded axe-core audit, and isolated sessions so parallel agents each get their own browser. Works as a plain shell command, with an MCP server available when you want one.

On this page9 parts
  1. 01Why It Exists
  2. 02How the Refs Work
  3. 03Setup
  4. 04The Part That Is Actually Frontend
  5. 05One Browser per Worktree
  6. 06Keeping It Safe
  7. 07Where It Fits in the Stack
  8. 08When Not to Use It
  9. 09Source

Why It Exists

The Browser Verification Loop is the highest-leverage change a Frontend team can make to its agent setup, and it has one honest weakness: it is the most expensive thing you can put in a context window. A screenshot is expensive. A full accessibility dump is expensive. Do it three times in one task and the agent has spent more of its window looking at the page than reading your code, which is exactly the failure mode The Context Budget describes.

That cost is not inherent to browser automation. It is inherited. Playwright and Puppeteer were designed for test scripts, where a human wrote the selectors ahead of time and nothing had to be summarized for a reader with a token limit. Point an agent at that API and every observation arrives at the size a machine needed, not the size a model can afford.

agent-browser starts from the other end. The consumer is a language model with a budget, so the default output is a filtered accessibility tree where every element carries a short stable ref, and the agent acts on the ref rather than re-querying the page.

How the Refs Work

This is the whole design in four lines:

bash
agent-browser open localhost:3000/pricing
agent-browser snapshot -i # interactive elements only, each tagged @e1, @e2, ...
agent-browser click @e2
agent-browser fill @e3 "[email protected]"

snapshot returns the page as structure, not pixels. -i limits it to interactive elements, -c compacts it, -d 3 caps the depth. The agent picks a ref and acts on it, so there is no second read of the DOM to resolve a selector and no vision model in the loop at all.

When it does need to find something by meaning rather than by ref, the semantic locators do it in one step:

bash
agent-browser find role button click --name "Submit"
agent-browser find label "Email" fill "[email protected]"

The project does not publish a benchmark, and the comparison numbers circulating in blog posts are not ours to repeat. The mechanism is checkable on your own project in about a minute: run snapshot -i -c against the page you actually work on and compare it against what your current browser tooling hands back for the same page.

Setup

bash
npm install -g agent-browser
agent-browser install # pulls Chrome from Chrome for Testing

That is the entire setup for any agent that can run shell commands, which is all of them. Claude Code, Cursor, Copilot and Codex need no configuration, no MCP entry, and no restart. A Rust daemon holds the browser open between commands, so the agent is not paying browser startup on every step, and batch groups a sequence into one invocation:

agent-browser batch "open localhost:3000" "snapshot -i" "screenshot out.png"

If you would rather expose it as tools than as a command, there is an MCP server with selectable profiles so you only load the surface you need:

JSON
{
"mcpServers": {
"agent-browser": {
"command": "agent-browser",
"args": ["mcp", "--tools", "core,react,network"]
}
}
}

Profiles are core, network, state, debug, tabs, react, mobile and all. Default is core. Reach for all only when you know why, because every tool you load is schema you pay for on every turn.

The Part That Is Actually Frontend

Most browser automation stops at "click this, read that". These are the commands that make it worth a React team's attention:

  • React fiber introspection.react tree returns the component tree, react inspect <fiberId> returns props, hooks, state and source location, and react renders start|stop records what re-rendered. The agent stops guessing which component owns a bug from the JSX and reads the running app instead. Launch with --enable react-devtools or the react commands error. Works on React, Next.js, Remix, Vite and TanStack Start.
  • Core Web Vitals as a command.vitals reports LCP, CLS, TTFB, FCP and INP plus a hydration summary. That turns "this feels slow" into a number the agent can move and then re-measure, which is the only form of performance work an agent can honestly close.
  • Accessibility with a real engine.a11y runs an embedded axe-core audit, offline and under strict CSP, and takes --tags wcag2a,wcag2aa and --selector. Accessibility becomes something the agent checks on the change it just made rather than something a consultant finds in a quarterly audit.
  • Network control.network route <url> --body <json> mocks a response, --abort blocks it, and network har start|stop records the session. The agent can drive an error state or an empty state without you standing up a fixture.
  • Diffing built in.diff snapshot --baseline compares accessibility trees, diff screenshot --baseline b.png -t <threshold> does a pixel diff, and diff url <a> <b> compares two deployments. This repo already runs pixelmatch scripts for exactly that; the difference is that the agent can now run the comparison itself, mid-task, instead of waiting for CI to tell it.

One Browser per Worktree

Sessions are fully isolated, each with its own browser instance, cookies, storage and auth state:

bash
agent-browser --session agent1 open localhost:3000
agent-browser --session agent2 open localhost:3001
agent-browser session id --scope worktree --prefix myapp

--scope worktree is the line that matters. If you run parallel agents out of git worktrees, each one derives its own session id from its own worktree, so two agents verifying two branches never share a cookie jar or fight over a tab. Parallel execution stops being a thing you do to the editor and becomes a thing the browser understands too.

Keeping It Safe

An agent with a browser is an agent that can read anything you are logged into, so the guardrails are worth setting on day one. They are all opt-in, which means they are all off until you turn them on:

  • --allowed-domains "localhost,*.staging.example.com" keeps the loop pointed at your own surfaces.
  • --confirm-actions eval,download gates the two verbs you do not want happening unattended.
  • --max-output 50000 stops one enormous page from eating the window.
  • --content-boundaries marks page content as page content, which matters because everything the browser returns is untrusted text that an agent is about to read as instructions.
  • State files encrypt at rest with AES-256-GCM when you set AGENT_BROWSER_ENCRYPTION_KEY.

Point it at localhost or an isolated staging profile. Never at production with your own session cookies.

Where It Fits in the Stack

  • It is the fourth way to wire the Browser Verification Loop,alongside Claude in Chrome, Chrome DevTools MCP and Playwright MCP. Those three are still the right answer for interactive debugging, deep performance traces and CI-grade Playwright specs. This is the one you leave on during ordinary feature work, because it is the one whose output you can afford.
  • It gives the Agent-Readable Design System its gate.Committed context, a registry and component metadata all tell the agent what to build. diff screenshot and a11y are how it finds out whether it did.
  • It runs unattended in Continuous AI.A CLI with a domain allowlist and an output cap is a much easier thing to justify inside a sandboxed CI job than a browser MCP server with the full DevTools surface attached.
  • It changes the shape of the context bill, not just the size.Structure survives compaction as text. Screenshots do not survive anything.

When Not to Use It

  • Non-visual work.A type fix or a server-side refactor gets nothing from a browser and pays for it anyway.
  • As your regression suite.An agent comparing a snapshot to a baseline mid-task is a fast, fuzzy check that gets the change close. Deterministic pixel diffing and real Playwright specs still belong in CI, where a failure blocks a merge.
  • Against anything you would not hand an agent outright.Everything the page returns is untrusted input. Treat a logged-in production tab as out of scope, not as a convenience.
  • With --tools all by reflex.The default profile exists because loading every tool surface reintroduces the exact cost this thing was built to remove.
Private Workshop

Want to bring AI into your Frontend workflow?

We help product teams adopt AI-powered development practices, from agent workflows to custom skills and tooling, on whichever coding agent they already run.

What happens next
  1. 01

    Tell us what you are building.

    Your stack, the AI tools you use, where you are stuck.

  2. 02

    We book a 15-minute call.

    We look at how your team works with agents today.

  3. 03

    We shape the workshop.

    Private and hands-on, on your own codebase.

0/2000

Your info stays with us. That's it.