ConnectOnionAll Posts
Remote Browser

The Model Was Holding the Browser

Separate model waiting from the browser execution lane so spending-cap retries cannot freeze unrelated browser sessions.

By ConnectOnion Team · 2 min read · 397 words

Remote BrowserReleaseTesting

2026-08-19

Three browser sessions stopped making progress for roughly forty minutes. The browser itself was mostly idle.

One session had asked co browser do to extract page data while its model provider was over a spending cap. Each model call retried and waited. A single attempt took more than four minutes; another took about a minute. Other agents could not even ask the browser for status, and one eventually disconnected before the daemon replied.

The queue was working exactly as written. That was the problem.

One request contained the whole agent

The browser daemon deliberately executes one Playwright action at a time. Patchright's synchronous driver belongs to one thread, and serializing short clicks, navigations, and screenshots keeps two callers from corrupting the same browser context.

But do was not a short browser action. The daemon received one request and ran the entire agent loop inside it: think, call the model, drive the page, think again, up to two hundred times. Model latency held the browser lane even though no browser work was happening. The safety boundary around Playwright had grown into a lock around the network.

The agent became a client

The model loop now runs in the co browser do process. It receives a proxy with the same tool signatures as BrowserAutomation, so the model sees the same forty browser operations. Each proxy call is serialized into one ordinary daemon request and releases the lane when that action finishes.

model thinks locally
  → go_to request
  → daemon navigates and replies
model thinks locally
  → get_text request
  → daemon reads and replies

Tab ownership remains in the daemon and is checked on every action. Moving the agent did not make two tasks safe on one page; named tabs are still the unit of isolation. It only means an agent waiting on a provider no longer prevents work on other tabs.

Screenshots needed one extra wire detail. Human shell commands should print the saved image path, but the agent's vision formatter needs the original data URL. Agent tool requests now ask for raw results, preserving vision without dumping base64 into a person's terminal.

Proving the absence of a lock

A regression test starts a fake model call and deliberately leaves it waiting. While it waits, another client sends status through the real daemon transport and receives an immediate answer. The test then releases the model and confirms the do run completes. That is the behavior the incident lacked: model time is caller time; only browser time belongs to the browser lane.

Star us on GitHub

If ConnectOnion saves you time, a ⭐ goes a long way — and earns you a coffee chat with our founder.