← Chrome Relay

Fewer round trips, checked steps

The approach behind chrome-relay do. Alexey Indeev, October 2026.

Chrome Relay lets coding agents (Claude Code, Codex, Cursor, Paseo) use your own Chrome, signed in as you, in background tabs. It was already fast: about 0.15 s per command. Agents still felt slow in the browser, and not always reliable. This page explains why, what chrome-relay do changes, and which decision models it uses and why.

The browser isn't the slow part

We measured both ends.

WhatTime
One agent-browser command through the relay (agent-browser's own headless Chrome: 13–15 ms)15–20 ms
One page script round trip through the relay and the extension~1 ms
Filling a 7-field form with a script, reading the page before every step77 ms total
Gap between two actions of a real agent (median; 4,742 actions in 181 sessions on one Mac)2.8 s
Same, 90th percentile17 s

97% of the agents' time in a session went into gaps longer than a second: the agent reading the page, thinking and choosing one click. The driving itself is about 10 ms a step. One more number: 8% of clicks were repeated at the same spot within 15 seconds, because the first one didn't take and the agent had to look again.

So the way to make agents faster in a browser is not a faster browser. It's fewer model round trips, and steps that check themselves so the agent doesn't have to.

The approach: say the goal once

agent-browser --cdp "$(chrome-relay url you@company.com)" open https://app.example.com/team/invite
chrome-relay do "Invite the new teammate as an admin" \
  --data "Email=ada@example.com" --data "Role=Admin" --until "text:Invitation sent"

The agent states the goal, gives the values it already knows, and says how to tell it's done. Chrome Relay then carries it out in the agent's tab. For each step, it uses the cheapest thing that works:

  1. A flow that worked before. When a run ends with its --until check met, its steps are saved for that site (element roles and labels, and which data key went where, never the values). The same kind of goal on that site replays at browser speed with the new data: no model at all.
  2. The agent's data. A --data key that names a field ("Email" finds "E-mail address") fills it, picks the dropdown option or ticks the box. No model. Values can be 1Password references, which the relay types without the agent or any model seeing them.
  3. A fast decision model for the rest: it chooses the next operation and target from a shortlist of the page's controls, and which of the agent's values goes into a field. It can't invent text, selectors or code.
  4. Hand back. Whatever it isn't sure of goes back to the agent with what was done, the page it's on, and what it was choosing between: low confidence, a field with no value, a consequential click the goal doesn't name (delete, send, pay, deploy, authorize, …), a covered button, going in circles, leaving the site. "Done" only counts when --until holds.

Steps that check themselves

Before every action the relay checks that the element is still the one the decision was about, that it's enabled, on screen and not covered by something else (open shadow roots included). After the action it waits for the page to settle, by watching the DOM rather than polling, and reads back what changed. The click or the typing goes through the same path as the agent's own commands, so the audit trail and 1Password handling apply unchanged.

Choosing the decision model

The idea of a small, fast "System 1" model choosing the next browser action came from browser-use/jev-ultrafast, which drives Google Flights with TypeSafe's Jev in about 7 seconds. Jev doesn't generate text: it returns a probability for each allowed answer to typed questions. Cloudflare's Clef models answer the same request format, and several small open models do too. We compared them on the job chrome-relay do gives them.

The test. Next-action decisions, in jev-ultrafast's request format (which operation, and for each operation which element):

DeciderRunsLiveMind2WebMedian per decision
TypeSafe Jev 1.13cloud91%67%0.15 s
Claude Haiku through Claude Code (one process kept running)cloud, your plan96%65%1.3–1.6 s
Cloudflare Clef (27B), Workers AIcloud83%67%0.53 s
Cloudflare Clef-flash (9B), Workers AIcloud83%47%0.62–0.79 s
Gemini 3.8 Flashcloud96%82%1.9 s
Gemini 3.5 Flash-Litecloud91%71%0.95 s
LiquidAI d1-3B, 4-bit (1.7 GB)on the Mac74%52%0.8 s
Decision models under 1B (Kev-0.8B, d1-omni-600M, Laya)on the Mac9–30%14–19%0.2–0.5 s
No model: best word match (operation given)on the Mac67%20%~0

Latency is measured from a MacBook (M4 Max) over the public APIs, not model time in a datacenter: Cloudflare quotes 39 ms and 209 ms for the Clef models on its own GPUs. The request format and rules were written for Jev, which may favour it. Local models ran in llama.cpp on the Mac's GPU, except Laya, which ran in PyTorch. Haiku was measured on the shortlisted requests (15 elements) that chrome-relay do sends; the others on the full ones.

What we took from it

In practice

In a real Chrome, through the extension, with Jev:

GoalHowTime
Fill and submit a 7-step order form3 fields from data, 4 Jev decisions, the result checked2.5 s
The same goal with other datareplayed as a flow, no model1.2 s
Find and open a Wikipedia article through the search suggestions2 Jev decisions2.0 s

Step by step, the agents we measured took a median of about 3 seconds per action, before counting the clicks they had to repeat.

Limits

Thanks

browser-use/jev-ultrafast (MIT), whose page snapshot and rules chrome-relay do adapts; TypeSafe for Jev; Cloudflare's Clef, LiquidAI's d1, Kev and Laya, all open models we tried; Mind2Web for the benchmark; and agent-browser, which agents still use for everything else.

Code and docs: github.com/aindeev/agent-chrome-relay.