Repository navigation
Conversation
🦋 Changeset detectedLatest commit: 73ef9d3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 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 |
commit: |
ben-reitz
force-pushed
the
browser/browser-module
branch
from
November 4, 2026 10:47
9f56716 to
af42aa2
Compare
ben-reitz
changed the base branch from
browser/module-hooks
to
browser/codemode-module-fixes
November 4, 2026 10:47
ben-reitz
force-pushed
the
browser/browser-module
branch
2 times, most recently
from
November 4, 2026 12:03
050b4c2 to
d3ee669
Compare
ben-reitz
force-pushed
the
browser/browser-module
branch
from
November 4, 2026 12:09
d3ee669 to
3760a07
Compare
An agent with an agents `Browser` can drive it through `browserTool`,
but code running in a Workspace can't: it has to stop, call the tool,
and start a new run to use what it saw. That rules out building a
site, opening it, taking screenshots and comparing them in one run.
`createBrowserModule({ browser, scope })` from
`@cloudflare/computer/modules/browser` is a codemode module that
exports the browser's `browser.*` functions, the same ones
`browserTool` gives its code, so code imports it as a namespace and
the browser's docs and rules read the same. The session is a scoped
context: a run opens one on its first call and closes it when the run waits
for a person or ends, which saves its active tab for the next run or tool
call. When the run ends, the session's notices, and how long the run
waited for its turn, go to its stderr; nothing is written while the
code runs, so replay's output check holds. `cdp` is marked unsafe to
repeat, as pi marks `browserTool`.
The browser scope, which tab a run drives, defaults to "shared" and
can be picked from the run's metadata, so a pi app can put `exec` and
`browserTool` in the same conversation's tab. Runs in one browser
scope take turns through the session's lock, since pi and the AI SDK
run a message's tool calls in parallel. A run gives up after
`lockTimeoutMs`, 45 seconds by default, with its own error rather
than a timed-out run. A run that browsed and is waiting for a person
keeps its browser scope: others fail at once rather than wait for an
answer that may take hours, including a run that got its turn while
the one ahead of it paused. Every function needs Workspace write
access, since browsing can change things on sites the browser is
logged in to.
Computer types the agents contract by shape and takes no dependency
on agents.
ben-reitz
force-pushed
the
browser/browser-module
branch
from
November 4, 2026 14:21
3760a07 to
73ef9d3
Compare
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.
An agent with an
Browsercan drive it throughbrowserTool, but code running in a Workspace can't. Building a site, opening it, taking screenshots and comparing them takes several model turns instead of oneexec.createBrowserModule()installs the browser ascodemode:browser. Its exports are the samebrowser.*functionsbrowserToolgives its code, so the docs and rules read the same:It keeps its browser session in a scoped context, from
createCodemodeModule()(#301). A run opens one session on its first call and closes it when the run waits for a person or ends, which saves its tab for the next run orbrowserToolcall. When the run ends, the session's notices go to its stderr, so nothing is written while the code runs and replay still matches.cdpis markedunsafeToRepeat(), (the same thing pi marks onbrowserTool).Scope
The browser
scopepicks the tab. It defaults to"shared", and can be a string or a function of the run's metadata (#291, #292), so runs started for one user can share a tab. Runs in one browser scope take turns, because pi and the AI SDK run a message's tool calls in parallel and would otherwise see each other's navigation. A run gives up waiting afterlockTimeoutMs, 45 seconds by default, with its own error before the run times out. A run that browsed and is waiting for a person keeps its browser scope, so other runs fail at once instead of waiting hours for an answer. That includes a run that gets its turn just as the one ahead of it pauses, so it checks again once it has the lock. The module remembers which runs browsed in memory, so after a Durable Object restart a waiting run holds nothing until it resumes.Every function needs Workspace write access. The browser keeps its logins, so browsing can change things on other sites, and a read-only backend refuses it, as it refuses
codemode:container'sexec.Computer types the agents contract by shape and takes no dependency on agents. The module needs
agents0.33.0 or later, which addedfunctionDocs(),session.functions, the session lock and its notices.The model is told, in the module's description, to save screenshots with
node:fsand open them withread, to take about eight per run because host calls share 8 MiB, and to work on several pages in one run. It's also told not to callbrowserToolthroughcodemode:tools, which would wait for its own turn. That case isn't caught automatically, since neither module can see the other.Unit tests cover the browser scope options, the paused-run check, the lock timeout, both kinds of close and the description, against a fake browser shaped like the agents one. Two end-to-end tests run it through the real backend: one session per scope, closed on pause, with notices logged at the end; and a second run failing at once while a waiting run holds the browser scope.
agentscan't be a dev dependency yet: its optional peer range for pi conflicts with the version this repository uses.docs/17_isolate_javascript.mdhas a newcodemode:browsersection, which notes that an app writingexec's description by hand must include the module's.