Skip to content

feat(env): name the website browser Playwright MCP, let a run choose its browser, and set the default infra env ids in config.toml - #398

Merged
earakely-scale merged 5 commits into
mainfrom
edgararakelyan/fd-4653-playwright-mcp-browser
Oct 30, 2026
Merged

earakely-scale merged 5 commits into
mainfrom
edgararakelyan/fd-4653-playwright-mcp-browser

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The website browser gets a name of its own, Playwright MCP, and which browser a deploy gets becomes something a run or a config file can choose.

  • The rename. The env a deploy with websites adds is now playwright-mcp, after the server it runs, Microsoft's Playwright MCP (@playwright/mcp).
    • Its id, its environment_name, and so its compose service, Postgres schema, card and gateway path (/svc/mcp-playwright-mcp/…) all change.
    • Image ghcr.io/scaleapi/agentenv-playwright-mcp, folder env/envs/playwright_mcp/, put_playwright_mcp_env, constants PLAYWRIGHT_MCP_*.
    • "Website browser" stays the name of the slot: default_website_browser_env_id, and the bootstrap kind website-browser.
    • Agents see the same tools, browser_navigate and the rest, since their names come from the image.
  • A run override, website_browser_env_id, like the gateway's and service-db's (feat(task): a run's gateway and service-db env overrides travel with it to any runner #255).
    • It goes through run_env_ids and a website_browser_env_id(config) getter, which both deploy readers use: the VM deploy and the snapshot reload.
    • agent-env task run --website-browser-env-id sets it, and agent-env env deploy --website-browser sets the default.
    • task run doesn't set up the browser in local stores when the run names its own.
  • [envs] keys in config.toml for the three default infra env ids: default_gateway_env_id, default_service_db_env_id and default_website_browser_env_id.
    • Declared in RESOLVED_KEYS like [agents] default_a2a_agent_id: an id set in code, by configure(...) or the attribute, beats the file, which beats the built-in id.
    • They stay Config constructor arguments and attributes, so Config(default_gateway_env_id=...) and code reading config.default_gateway_env_id keep working.
    • Documented in AGENTS.md and .agentenv/config.example.toml.
  • No put command of its own. agent-env env website-browser put goes, with no replacement. The browser is an ordinary MCP server env, so agent-env env mcp-server put writes it.
    • When a store that isn't local lacks it, the hint names that command over the image this install's release publishes:
      agent-env env mcp-server put --id playwright-mcp --environment-name playwright-mcp --image-ref ghcr.io/scaleapi/agentenv-playwright-mcp:src-….
      It names the shipped Dockerfile instead when the release published none.
    • put_playwright_mcp_env stays, for local stores' setup and AgentEnvHub's promotion.
    • agent-env sets up the browser only under playwright-mcp, the id of the one it ships. A slot naming another browser the store lacks is refused, in local stores too, with a generic mcp-server put hint that shows the shipped browser's values as the example. An env that exists under any id is left alone.
    • A guard test keeps env website-browser and env playwright-mcp from coming back.
  • No browser name is reserved. The reserved names are the services every gateway deploy runs: gateway, servicedb, pgweb and db-mcp. The website browser can be named anything. Rendering the compose file now refuses two of a deploy's services sharing a name, which catches an env named like whichever browser the deploy got. A website's services are suffixed, so a website can still share an MCP server's name.
  • Release build. The browser's image is put in the build group after the protocol by its Dockerfile, not by matching its name, so a later rename can't move it to the wrong group.

Why

AgentEnvHub will promote the browser from agentenv-framework pin bumps, the way it promotes the gateway and service-db. It checks each release's browser under a candidate env through this override before serving it (FD-4648). There's more than one website browser too: synthetic-pipelines has its own Playwright-based one, and a browser-use one is likely. So each is named after its source, and the slot says which one a deploy gets.

Upgrading

  • Remote stores: a deploy with websites now reads env playwright-mcp. Put it first with agent-env env mcp-server put as above, or keep the old env with [envs] default_website_browser_env_id = "website-browser". AgentEnvHub's dev and prod stores already hold playwright-mcp v1, a copy of what each serves today.
  • Local stores build playwright-mcp on the first run that needs it. A slot naming another browser needs that env put first.
  • Recording steps: a start_computer_recording that names environment_name: "website-browser" should name playwright-mcp once the browser it records runs the renamed image.

Testing

  • Unit tier: 10,907 passed. One failure is tst/unit/agents/hermes/test_hermes_bridge.py::test_the_event_pipe_is_not_left_open_in_the_server, which reads /proc/self/fd; macOS doesn't have it, and this PR doesn't touch that code.
  • New and changed tests:
    • each [envs] layer, and configure();
    • concurrent runs keeping their own browser override;
    • the task run flag;
    • task run not setting up the browser when a run names its own;
    • the deploy reading the override;
    • a browser of any name, and an env named like it refused;
    • the reserved names refused at render time;
    • the put hint, with and without a published image, and the dropped command;
    • a browser agent-env doesn't ship: refused when missing, left alone when present, reported once by preflight;
    • the renamed put and recorder;
    • the config report knowing the new keys.
  • Slow gateway integration tests for websites, on local Docker on a Mac: the two that don't open a browser passed. The two that do, test_gateway_with_single_website_env and test_gateway_with_multi_env_including_website, can't run on an arm64 Mac: the test builds the browser for linux/amd64, and Chromium crashes at launch under qemu (qemu: uncaught target signal 6, after the GPU process fails). CI runs them natively.
  • Against AgentEnvHub's dev store, with this branch: dev's playwright-mcp v1 is the copy of website-browser that the bot's pin will first meet. On Modal VM:
    • gate-website, the framework's test site: the browser listed its tools, navigated, and read "Slack Workspace".
    • psi-stayncook-multi, a real multi env: 43 tools, and the browser read its site's title.
    • Both were torn down.
  • agentenvhub-sdk 0.37.1's suite against this branch: 2,876 passed. Five CircleCI config tests couldn't run, because they import a helper from the scaleapi repo's root, which wasn't in the copy I tested.
  • Image tags: the gateway keeps src-33deb10f…, which prod serves, so the release republishes no gateway. The browser becomes agentenv-playwright-mcp:src-347ea6d9….
  • The renamed image: built for amd64 and arm64, and the release's smoke check passed on both. Run natively on arm64:
    • the recorder served its card as playwright-mcp with computer-recording/v1;
    • the browser served 24 tools and navigated to example.com.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the earlier constructor break is fixed and no new blocking issues were found.

Summary

The PR names the shipped browser playwright-mcp, adds browser choices for individual runs, and lets config files set the default infra env IDs.

  • The shipped website browser is now named playwright-mcp.
  • A task run can choose the browser used by its website deploys.
  • Config files can set the default IDs for all three infra envs.
  • Compose checks service names against the services in each deploy.

Reviews (5) · Last reviewed commit: "fix(env): set up only the website browse..." · Reviewed by Greptile

…its browser, and set the default infra env ids in config.toml

The env a deploy with websites adds is now playwright-mcp, after the server it runs, Microsoft's Playwright MCP:
its id, environment_name, image (agentenv-playwright-mcp), folder, put and CLI. "Website browser" stays the slot's
name: default_website_browser_env_id and the bootstrap kind.

A run's user_overrides can name its browser (website_browser_env_id), like the gateway's and service-db's, read by
the VM deploy and the snapshot reload, and set by task run --website-browser-env-id; env deploy takes
--website-browser.

[envs] default_gateway_env_id, default_service_db_env_id and default_website_browser_env_id are config.toml keys:
an id set in code beats the file, which beats the built-in id. The attributes read as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@earakely-scale
earakely-scale marked this pull request as ready for review October 29, 2026 22:21
@earakely-scale
earakely-scale requested a review from a team as a code owner October 29, 2026 22:21
Comment thread src/agent_env/config/runtime.py Outdated
Comment on lines +238 to +240
default_gateway_env_id = _DefaultEnvId()
default_service_db_env_id = _DefaultEnvId()
default_website_browser_env_id = _DefaultEnvId()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Existing config construction fails

Replacing these dataclass fields with unannotated descriptors removes their constructor arguments. Existing calls such as Config(default_gateway_env_id="candidate") now raise TypeError before the caller can use the config. The same break affects default_service_db_env_id and default_website_browser_env_id, and Config remains publicly exported.

Preserve these constructor arguments while adding file-backed reads, and add a test for each one.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent_env/config/runtime.py
Line: 238-240

Comment:
**Existing config construction fails**

Replacing these dataclass fields with unannotated descriptors removes their constructor arguments. Existing calls such as `Config(default_gateway_env_id="candidate")` now raise `TypeError` before the caller can use the config. The same break affects `default_service_db_env_id` and `default_website_browser_env_id`, and `Config` remains publicly exported.

Preserve these constructor arguments while adding file-backed reads, and add a test for each one.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Cursor Fix in Claude Code Fix in Codex

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit. The three ids are dataclass fields again, typed through the same descriptor, so Config(default_gateway_env_id=...) and the other two are accepted as before. A value passed in counts as an id set in code, and None leaves the [envs] key or the built-in id in effect. A new test covers each argument, both beating the config.toml key and passing None.

earakely-scale and others added 4 commits October 29, 2026 15:41
It's an MCP server env, so `agent-env env mcp-server put` writes it. A store that isn't local and lacks it now gets
a hint naming that command over the image this install's release publishes (--image-ref), or the shipped Dockerfile
when there is none. put_playwright_mcp_env stays for local stores' setup and AgentEnvHub's promotion.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…uments

They're dataclass fields again, typed through the same descriptor, so Config(default_gateway_env_id=...) and the
other two work as before: a value passed in is the id set in code, and None leaves the config.toml key or the
built-in id in effect.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rvices of one name when rendering

The reserved names are the services every gateway deploy runs (gateway, servicedb, pgweb, db-mcp). The website browser
a deploy adds can be named anything: rendering the compose file refuses two of a deploy's services sharing a name,
which catches an env named like whichever browser the deploy got, and an env named like one of the reserved services.
A website's services are suffixed, so a website may still share an MCP server's name.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…its own for any other

A slot naming a browser agent-env doesn't ship, say browseruse-mcp, used to get the Playwright image built under that
id in local stores, and a hint to put the Playwright image under it in others. Now agent-env sets up the website
browser only under playwright-mcp, the id of the one it ships. A missing env under any other id is refused before
anything is built, with a generic mcp-server put hint that shows the shipped browser's values as the example. An env
that exists under any id is left as it is.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@earakely-scale
earakely-scale merged commit 3796d4c into main Oct 30, 2026
25 of 26 checks passed
@earakely-scale
earakely-scale deleted the edgararakelyan/fd-4653-playwright-mcp-browser branch October 30, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant