Repository navigation
feat(agents): add BrowserSessionConnector for persistent named browsers - #2371
Merged
ben-reitz merged 4 commits intoOct 1, 2026
Merged
Conversation
🦋 Changeset detectedLatest commit: 084e77f The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
ben-reitz
added this pull request to stack #2373
September 25, 2026 08:21
Contributor
|
✅ agents import sizes: no significant changes ( |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
This was referenced Sep 25, 2026
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
from
September 25, 2026 09:13
8a9cdaf to
cd7cf17
Compare
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
4 times, most recently
from
September 25, 2026 13:48
a21df5c to
acc8261
Compare
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
3 times, most recently
from
September 27, 2026 22:56
bc7768d to
f56913a
Compare
ben-reitz
marked this pull request as ready for review
September 27, 2026 22:56
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
from
September 28, 2026 09:40
75337c3 to
49b5dcb
Compare
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
2 times, most recently
from
September 28, 2026 12:29
300f8b9 to
a7e93cc
Compare
ben-reitz
removed this pull request from stack #2373
September 29, 2026 13:34
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
from
September 29, 2026 13:36
a7e93cc to
173cd66
Compare
ben-reitz
added this pull request to stack #2412
September 29, 2026 13:36
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
from
September 30, 2026 09:25
173cd66 to
3f4e955
Compare
A raw Target.attachToTarget sent through cdp.send now returns the stable target:<id> handle, so replays after an approval pause and later runs keep working. Target.detachFromTarget accepts a handle. An expired raw CDP session id gets an error that points at "active" or cdp.attachToTarget. newTabs now counts only tabs with a Chrome openerId, so a tab another execution creates with Target.createTarget on the same browser is no longer reported as a popup.
cdp.send now returns Chrome's own sessionId for a raw attach again, instead of swapping in a stable handle. The stable handles stay on cdp.attachToTarget. The instructions say a raw id only lasts for the current run, and a stale one still gets a hint. The fake browser now drops CDP sessions when their socket closes, like Chrome.
ben-reitz
force-pushed
the
feat/browser-session-connector
branch
from
October 1, 2026 10:08
779eb5f to
419e054
Compare
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR: this actually adds the new codemode connector that the model uses.
BrowserSessionConnectoris a codemode connector (cdp) over oneBrowserthat persists between executions. The model drives it with raw CDP and never manages sessions. It's internal; #2372 wires it intobrowserTool.Model surface (compared with
BrowserConnector)cdp.send({ method, params, sessionId }) cdp.attachToTarget({ targetId }) // → { sessionId: "target:<id>" } cdp.spec() · cdp.getDebugLog() · cdp.clearDebugLog() -cdp.startSession() · sessionInfo() · closeSession() · resetSession() -cdp.getLiveViewUrl() // bearer URL — host-only via browser.liveView()sessionId: "active"One pass
The
{ restarted, newTabs }report is held perexecutionIduntil the tool reads it; at most 100 unread reports are kept. Within one connector,newTabscovers every pass of an execution, minus tabs that closed again. Carrying the report across an approval resume (which may use a fresh connector) is left for when the browser tool gets approvals; nothing pauses today.Errors
A page command sent without
sessionId, or an event sent as a command, gets an error that tells the model what to do instead (usuallysessionId: "active"). These are detected by CDP error code (-32601), not message text.Browser.closeandBrowser.crash*are refused, since the host owns the browser's lifetime. Arguments are validated before any browser is touched.The instructions warn the model that the browser can still be replaced between runs, or between the passes of a paused run, and to check where it is before an action that matters.
Reviewing
session-connector.ts(~600 lines) plus 23 tests inbrowser-session-connector.test.ts, run against a fake Browser Run binding and CDP socket. Eight more run against real Chrome insrc/browser-tests(pnpm run test:browser, not in CI): persistence across executions, popups, pause/resume, detach and reattach, teaching errors,Browser.close, and restart.Architecture diff
Green-filled boxes are new, with one box per part. Grey boxes are unchanged, and dashed boxes arrive later in the stack.
flowchart TB classDef ctx fill:none,stroke:#8c959f,color:#8c959f classDef changes fill:#dafbe1,stroke:#1a7f37,color:#1f2328 classDef removed fill:#ffebe9,stroke:#cf222e,color:#1f2328 classDef later fill:none,stroke:#8c959f,stroke-dasharray:4 3,color:#8c959f Sandbox["sandbox code: cdp.*<br/>(via the codemode runtime)"]:::ctx subgraph Conn["BrowserSessionConnector · session-connector.ts (new)"] direction TB K1["+ cdp.send, attachToTarget, spec, debug log"]:::changes K2["+ sessionId #quot;active#quot; → the stored active tab"]:::changes K3["+ reports restarted and newTabs per execution"]:::changes K4["+ one CDP socket per pass; the browser persists"]:::changes K1 ~~~ K2 ~~~ K3 ~~~ K4 end Val["validateConnectorArgs · connector-validation.ts"]:::ctx BS["Browser · browser.ts"]:::ctx BR["Browser Run"]:::ctx Next["browserTool (next PR)<br/>wraps it in an AI SDK tool"]:::later Sandbox --> Conn Conn --> Val Conn -->|"connect(), setActiveTarget(), spec()"| BS BS --> BR Next -.-> Conn style Conn fill:#dafbe1,stroke:#1a7f37,stroke-width:2px,color:#1f2328