Repository navigation
feat(multi): a multi env names its website browser (browser_envs), a browser computer on a sandbox of its own - #598
Merged
earakely-scale merged 15 commits intoNov 11, 2026
Conversation
…puter runs on a sandbox of its own browser_envs on a multi env names its website browser: left out, the run's selector picks one as before; [] is none; one entry deploys, two and a non-browser env are refused at put. An MCP server env such as playwright-mcp runs among the gateway's MCP servers; a browser computer such as chromium deploys as one more computer child, sized by child_envs, its tools under its name, routing the synthetic sites unless its entry says, and its network held to the gateway's host and the live sites' hosts where the provider enforces an allowlist (reach_only). The gateway no longer reads an image off whatever the selector names, and a lone website env refuses a browser computer as the run's browser. CLI multi put --browser/--no-browser; the bundle plan and browser steps see it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wser its record holds reset_env reads the multi env from the store, whose browser slot is empty, so the browser computer was skipped and stayed down. The reset now finds it in the record, the record of a name none of the multi env's own computers has, as reattaching does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…host until its image can be pulled under an allowlist A Modal VM's Docker pulls a container's image through the sandbox's own allowlist, which leaves the registry out, so chromium held to the gateway couldn't pull itself there. SandboxProvider.PULLS_UNDER_ALLOWLIST says which providers can; modal_vm can't, and a reach_only network falls back to allowing every host there, as logged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the scheme the deploy reaches the gateway at Modal's tunnel terminates TLS and sends no X-Forwarded-Proto, so the gateway handed out http:// CDP addresses there, which don't connect. The deploy now tells the gateway its tunnel URL (AGENTENV_GATEWAY_PUBLIC_URL), and a request to that host takes its scheme; X-Forwarded-Proto still wins, and any other host keeps the connection's own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…CP browser's name is checked, and only Modal containers pull under an allowlist Review fixes: stored_browsers counts the browser computer a multi env resolves, the run's too, so browser steps pass preflight when the run names chromium; an MCP server browser's name is checked beside the computers and MCP servers, so a clash refuses rather than stopping the gateway; and PULLS_UNDER_ALLOWLIST is off by default, since the default VM path pulls under the allowlist, on only for Modal containers, whose platform pulls outside it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts own process made, as main's tests now do Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd leaves the earlier one for close Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ny computer child's Edgar's call on review: holding chromium's network to the gateway was in force only on Modal containers (local Docker can't enforce an allowlist, and on every VM-path provider the image pull is cut off by it), so it is taken out for now: reach_only, the fallback and SandboxProvider.PULLS_UNDER_ALLOWLIST go, and a browser computer's network is its env's, widened to the gateway's host and the live hosts only when that is an allowlist, as M5.6 does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…with a reattach, a load and the run's browser They share its composed chromium, so CI composes it once. The deploy test now also reattaches the browser from the instance store and loads a universe that sets its cookies through the multi env; a new test deploys a multi env naming no browser while the run names chromium. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ti env's browser at its gateway A browser in one of a multi env's computers was refused. The step now asks its cdp through the multi env's gateway, on its /svc route to that computer with the computer's control token, so the address it hands the agent is the gateway's relay, rebased for the agent's sandbox as deploy_agent rebases the gateway's MCP URL; the env's tools are hidden at the gateway the agent connects to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss the gateway didn't relay The gateway's CDP relay tells apart one website browser per computer; for a computer with several, its cdp answer came back unrewritten, naming the computer's own address, which the step would have handed the agent. The step now refuses an address that isn't at the gateway's relay, before the agent gets it or any tool is hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…name for its address public_url was the same value as the deploy record's gateway_url (the gateway's tunnel URL), so it takes that name: the compose parameter, AGENTENV_GATEWAY_URL, Gateway(gateway_url=...) and the CDP relay's argument. No change in behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale
force-pushed
the
edgararakelyan/fd-4960-m813-the-browser-alone-in-a-multi-env
branch
from
November 11, 2026 02:34
6688cb3 to
6b2495c
Compare
…gin the agent's named, on containers too browser_connect_cdp names the agent's origin on the cdp call it asks through the multi env's gateway too, as #608 has it name it of a browser asked directly, and the gateway keeps the https or wss of an address the browser minted under it. So behind a tunnel that ends TLS, as Modal's, the address and its discovery are https and wss on a VM and on Modal containers alike, where a container gateway's tunnel URL isn't known until it runs. The deploy no longer tells the gateway its gateway_url (AGENTENV_GATEWAY_URL), which only a VM deploy could. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, is refused with word to compose it again browser_connect_cdp refused such a browser's address as one the gateway didn't relay, blaming a computer with several browsers. It is at the relay, in http where the gateway is reached by https: the browser, composed before agentenv-framework 0.9.1505, takes no origin. The step now says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ere it runs MultiEnv.website_browser() gives the browser a deploy adds and where it runs, a WebsiteBrowser: a browser computer on a sandbox of its own, an MCP server env among the gateway's MCP servers, or the run's, which the gateway looks up as it deploys when the store doesn't hold it yet. It replaces browser_env, browser_computer and _browser_computer, and the gateway's topology reads it instead of choosing again (_named_browser_server goes). A run's MCP server browser the store holds is now handed to the gateway rather than looked up a second time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale
deleted the
edgararakelyan/fd-4960-m813-the-browser-alone-in-a-multi-env
branch
November 11, 2026 05:15
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.
What
A multi env can now name its website browser:
browser_envs = ["chromium"], a list of env ids. Named chromium, the browser computer, deploys on a sandbox of its own as one more of the multi env's computer children, fronted by its gateway. This is M8.13 (FD-4960), built to the settled design note: https://claude.ai/artifact/PgPaL5AvTaSmbFcAdGKaoqwebsite_browser_env_id: config,user_overrides,--website-browser), for a multi env with websites.[]means no browser. One entry deploys; two are refused at put, as is an entry that isn't a website browser env (an MCP server env, or a computer env with a website browser app).playwright-mcpruns among the gateway's MCP servers, as today. A browser computer takes the computer-child path. So M8.27's switch of the default stays a config change for multi envs.child_envs.chromium(sandbox_type,cpu,memory_mb,disk_size_gb,env_params). It stays out ofcomputer_envs, so a stored multi env reads and writes as before.chromium_computer_screenshot,chromium_computer_navigate, and so on.site_routing = true) unless its entry'senv_paramssay whether it does. Its start tabs load them by name.domainsandallow_hosts; otherwise it allows every host. Holding it to the gateway alone was built and then taken out on review (below).docker_image_artifactoff whatever the selector names. A lone website env whose run names a browser computer is refused with a message pointing at a multi env.The gateway keeps the scheme of the agent's origin.
browser_connect_cdpnames the agent's origin, where its sandbox reaches the multi env's gateway, on thecdpcall it asks through the gateway, as #608 (FD-5470) has it name it of a browser it asks directly. The browser mints the address under it, and the gateway keeps that address's https or wss when it puts its own host and/browser/<key>before/cdp/<token>/, in thecdpanswer and in discovery alike. Modal's tunnel ends TLS and sends noX-Forwarded-Proto, so the gateway alone would sayhttp://, which doesn't connect. This works on a VM and on Modal containers alike, where a container gateway's tunnel URL isn't known until it runs. It takes effect where the gateway image of this release runs, for a browser composed with #608'sorigin; one composed before it getshttpbehind Modal, which the step refuses. It is the gateway's half of what #608 left for a follow-up.browser_connect_cdpreaches a multi env's browser. It used to refuse a browser in one of a multi env's computers. It now asks that browser'scdpthrough the multi env's gateway, on its/svc/<computer>/route with the computer's control token, so the address it hands the agent is the gateway's CDP relay, rebased for the agent's sandbox asdeploy_agentrebases the gateway's MCP URL. It names the agent's origin there too, as above. The env's tools are hidden at the gateway the agent connects to, by the step's existing rule.One place picks the browser.
MultiEnv.website_browser()gives the browser a deploy adds and where it runs, aWebsiteBrowser: a browser computer on a sandbox of its own, an MCP server env among the gateway's MCP servers, or the run's, which the gateway looks up as it deploys when the store doesn't hold it yet. The gateway's topology reads it rather than choosing again (Edgar, on review Nov 11).Also:
agent-env env multi put --browser IDand--no-browser; the bundle plan tells a browser computer apart from the computers by name, as it does them; the browser task steps count a named browser computer among a multi env's browsers; AGENTS.md and the browsers README.Fixed on the way: a computer app deployed alone, such as chromium, lists itself as its one app, so the multi env's app-name check would have refused it for "sharing" its own name.
Decisions (FD-4960, Nov 10)
browser_envs. Left out, the run's selector picks it;[]is none; one entry for now.chromium_.child_envs.chromium; the gateway's VM is unchanged.Decided on review (Nov 10): the browser's CDP address takes its scheme from the agent's origin (above; first the deploy told the gateway its
gateway_url, which only a VM deploy could, so on Nov 11 it moved to #608's origin), and the browser's network is its env's, as any computer child's, so it deploys, resets and reloads onmodal_vmas anywhere else.Decided on review (Nov 11), no change: until this release's gateway is promoted, a browser composed with #608 behind an older gateway image is refused with the generic "didn't put the CDP address at its relay" message (left as is); the gateway keeps the https or wss the browser's answer names, its host and path always its own; and real-Modal coverage stays the runs below, CI covering the tunnel with a local front that ends TLS.
Fixed in a follow-up commit:
reset_envreads the multi env from the store, whose browser slot was empty, so the browser computer was skipped and stayed down. The reset now finds it in the record, as reattaching does.Tests
browser_envsat put: left out,[], one entry, two (refused), not a browser env (refused), a name a computer has (refused);chromium_, defaultsite_routing,child_envssizing);[]gives no child and no gateway browser; an MCP server browser runs among the gateway's servers, in container mode too;--browser/--no-browser, the bundle plan's names,stored_browsers.tst/integration/computer/browser_computer_test.py, sharing its composed chromium; local Docker on an agent-environments-admin amd64 VM): 4/4, beside the module's site-routing tests, 2/2.https://shop.test/by name through the gateway; an agent'schromium_computer_*tools drive it through/mcp; its CDP address and discovery answer, asked through/svc/chromium/, name the gateway; a CDP agent there loads the site by name; a later process reattaches it from the instance store; a universe loaded into the multi env sets its cookies;reset_envbrings it back after its container is killed and after the gateway restarts.browser_envs = []deploys no browser.browser_connect_cdpon the multi env: the echo test agent openshttps://shop.test/over the address it was handed, through the gateway's relay (its trajectory records the connection), with the multi env's tools hidden from its role; the module's ownbrowser_connect_cdptest still passes beside it.gateway_test.py -k website4/4 again; 1,113 gateway unit tests.ubuntu-24.04-browser, headful), on a fresh agent-environments-admin amd64 VM: the browser tests 2/2,multi_env_computers_test.py4/4,gateway_test.py -k website4/4,browser_computer_test.py -k routing_sites2/2; unit tier 14,440 pass, the same 3 failures unrelated to this change.multi_env_computers_test.py4/4,gateway_test.py -k website(playwright-mcp) green,browser_computer_test.py -k routing_sitesgreen. Unit tier 14,368 pass, 3 failures unrelated to this change (two intest_mcp_cli_builder, one version lookup that needs.git).browser_computer_test.py -k 'multi_env or browser_connect_cdp or front or routing_sites'passed 9/9 (Node 22). That includes a new multi env test behind a front that ends TLS, as Modal's tunnel does, which fails on the old gateway line.browser_computer_test.py9/9 (multi env,browser_connect_cdp, both fronts that end TLS, site routing),multi_env_computers_test.py4/4, andgateway_test.py -k website4/4, which takes the run'splaywright-mcp.m813-office-mcp: the mail MCP server andm813-chromium, recomposed with fix(browser): CDP addresses through a TLS-ending tunnel are https and wss (FD-5470) #608, no websites; this branch's gatewaym813-gateway): passed 9/9 with the gateway on Modal containers (Greptile's case) and 9/9 with it onmodal_vm, chromium onmodal_vmin both. Asked asbrowser_connect_cdpasks, through the gateway under the agent's origin, the address ishttps/wssat the gateway's relay, and discovery answers the samewss. A CDP client connects there and runs a script in a tab. Asked without an origin, the gateway sayshttp, which the step refuses. Both deploys were closed.browser_computer_test.py -k 'multi_env or browser_connect_cdp or routing_sites'7/7, and fix(browser): CDP addresses through a TLS-ending tunnel are https and wss (FD-5470) #608's TLS-front test 1/1 (Node 22). Affected unit tiers (tst/unit/task_step,tst/unit/env/gateway, the multi env computers, the gateway provider, the protocol's CDP tests): 3,771 pass.m813-): chromium composed on a modal_vm builder and made ready by gate 3 there.modal_vm(the default beside a modal_vm gateway), on this branch's gateway image (registered asm813-gateway, through the run'sgateway_env_id), 13/14: it deploys; its start tab loads the site by name through the gateway; the gateway runs no playwright-mcp; an agent drives it underchromium_; its CDP address ishttps:///wss://at the gateway, the discovery answer names the gateway, and a CDP client connects and the browser answers; it allows every host, its env declaring no network; after a snapshot reload's recreate of every gateway service but the database it still drives;reset_envbrings it back. Its VM has the 4 GiB asked for; the one check not passing is its CPU count, 18 vCPUs, since Modal'scpuis a reservation, not a cap.http://and not connecting.modal(child_envs.chromium.sandbox_type), beside a modal_vm gateway: it deploys; its start tab loads the site by name; an agent drives it; from inside it the gateway's host answers and the internet is refused; 2 CPUs. Not passing: the CDP address, the gateway VM's other address reachable, and reset (open items 2 to 4).modal_vmheld to the gateway, before the decision: FD-5430, its image pull cut off in 21 s, closed cleanly.On Modal (decided Nov 10)
FD-5430: no longer bites, since the browser's network isn't held to the gateway.Reset on: decided, left as is. A computer on Modal containers can't be reset in place, somodalreset_envfails for chromium there, with an error saying why; chromium lands onmodalonly whenchild_envs.chromium.sandbox_typeputs it there, and every computer onmodalhas the same limit.The gateway's CDP address on Modal is: decided, fixed here (the agent's origin's scheme, above).http://SandboxProvider.effective_network_policy),*.modal.hostfor Modal, so a computer held to an allowlist there reaches any Modal tunnel, the gateway VM's pgweb tunnel included. With item 1, chromium onmodal_vmallows every host anyway; this bites chromium onmodaland any computer with its own allowlist, as it did before this PR.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; no new blocking issue was found.Summary
Adds
browser_envsso a multi env can choose its website browser, deploy a browser computer separately, and reach it through the gateway.Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD M[Multi env] --> S{Selected browser} S -->|Computer| C[Separate computer sandbox] S -->|MCP server| P[Gateway MCP service] S -->|Empty list| N[No added browser] A[Agent] --> G[Gateway] G -->|Tools and CDP relay| C G --> PReviews (15) · Last reviewed commit: "refactor(multi): one place picks a multi..." · Reviewed by Greptile