Skip to content

feat(website_browser): record the browser with computer-recording/v1 (FD-4497) - #360

Merged
sarah-chitty-1 merged 4 commits into
mainfrom
sarahchitty/browser-recording
Oct 28, 2026
Merged

sarah-chitty-1 merged 4 commits into
mainfrom
sarahchitty/browser-recording

Conversation

@sarah-chitty-1

@sarah-chitty-1 sarah-chitty-1 commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

What

Website-browser runs can now be recorded with computer-recording/v1 (#346), the same way a computer env's display is. Linear: FD-4497.

  • Recorder in the browser image (website_browser/recorder.py):

    • It runs idle beside Playwright MCP, which starts exactly as before, and serves a card that declares only computer-recording/v1.
    • When a recording starts, it streams the page the agent is on (DevTools Page.startScreencast) into the protocol's Recordings, which encodes, uploads and seals it the same way it does for a computer env.
    • It finds Chromium through the localhost debugging port that Playwright MCP 0.0.41 already opens in --isolated mode.
  • Gateway: MCPServerConfig.card_port (optional) lets the browser's REST_PROXY_URLS entry point at the recorder. MCP traffic and the health check are unchanged. With an image that has no recorder, the browser is left off the card, as it is today.

  • start_computer_recording: a new optional environment_name targets a child env of the deployed env, for example website-browser inside a gateway. Steps that don't set it serialize and run exactly as before.

  • Release: the browser image now builds with the agents' images, after the release publishes the protocol, because its recorder installs it. As an infra image it would build before the protocol was published, and a failed infra image keeps the release off PyPI. The build retries while PyPI's index doesn't yet list a protocol floor, the same way it does for a pin.

Nothing records until a task runs start_computer_recording. The idle cost is an ~85 MB process and an image that's about 38 MB larger.

How it was tested

  • Unit tests: tst/unit passes (10114 passed, 64 skipped), and ruff is clean. New tests cover finding the browser, following pages, re-sending a still frame, a full recording decoded with av, the gateway's rewritten child card, and the port constant matching across files.
  • On a laptop through this branch's gateway, with the recording started and ended via DeployedEnv.invoke(..., environment_name="website-browser"): the agent's actions over the gateway MCP produced an 8.3 s H.264 mp4. Recording the browser container directly gave 20 s over 2 segments, covering navigation, typing and opening and closing tabs.
  • With an old browser image, the card returns 200 and has no browser child. The only difference is one warning line.
  • The image builds against the published protocol (>=0.1.382 resolved to 0.1.383, since 0.1.382 was never published), and the recorder serves its card from it.
  • Not tested yet: uploading with a real grant, and a hosted deploy.

Known gap

  • When the agent switches to an open tab (browser_tabs select), the recorder doesn't see it, so the video catches up at that tab's next navigation.
  • The recording is the page viewport (scope display), with cursor: false, since a headless browser has no pointer to draw.

The hub player is scaleapi#170559.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the latest change fixes the reported popup recovery failure.

Summary

Adds on-demand browser recording through computer-recording/v1.

  • Website-browser tasks can record the page the agent is using.
  • Recording steps can target a named child environment.
  • Release builds publish the protocol before building the browser image.

The previous unnumbered finding is fixed: _show removes the failed target and resumes a remaining page. The added regression test checks this path. No new actionable issues or repository-rule violations were found.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Step[Recording task step] --> Gateway[Environment gateway]
  Gateway --> Recorder[Browser recorder]
  Agent[Agent tools] --> Gateway
  Gateway --> MCP[Playwright MCP]
  MCP --> Browser[Chromium page]
  Browser -->|Frames| Recorder
  Recorder --> Recording[Encode and upload recording]
Loading

Reviews (2) · Last reviewed commit: "fix(website_browser): a page that closes..." · Reviewed by Greptile

sarah-chitty-1 and others added 3 commits October 27, 2026 15:29
…(FD-4497)

The website-browser image runs an idle recorder beside Playwright MCP. It serves
a card declaring computer-recording/v1, and on start streams the agent's page
(DevTools screencast) into the protocol's Recordings, which encodes, uploads and
seals it as for a computer env. The gateway reads the browser's card from the
recorder's port (MCPServerConfig.card_port); an image without the recorder is
omitted from the card as before. start_computer_recording takes an optional
environment_name to target a child env of the deployed one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gent images do, not an exact pin (FD-4497)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…shed, as its recorder installs it (FD-4497)

A release builds the infra images before it publishes the protocol, and a failed
infra image keeps both packages off PyPI, so an infra image that needs the
protocol the release ships would block every release. The browser now builds in
the after-protocol group with the agents' images, and the build retries while
PyPI's index doesn't yet list a protocol floor, as it does for a pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sarah-chitty-1
sarah-chitty-1 marked this pull request as ready for review October 27, 2026 23:54
@sarah-chitty-1
sarah-chitty-1 requested a review from a team as a code owner October 27, 2026 23:54
Comment thread src/agent_env/env/envs/website_browser/recorder.py
… hands back to the newest page left (FD-4497)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sarah-chitty-1

Copy link
Copy Markdown
Collaborator Author

End-to-end test in dev

A real browser run recorded the page and a locally run hub played it. Nothing in the path was mocked: the upload, the run's metadata, the hub's artifact listing and its link signing were all real.

The run (dev stage)

  • Instance fd4497-browser-recording-e2e-pjy9euyw, task fd4497-browser-recording-e2e v2. It completed all 5 of 5 steps. The agent was claude-code on Haiku 4.5 and made 6 browser actions on the freetickets site.
  • The browser image was built from agentenv-framework#360 at f811cbc and registered in dev as website-browser-fd4497-rec. The env ran on dev's modal_vm sandbox.
  • computer_recordings.browser ended with state ended, ended_by end, 2 segments and 0 missing.
  • Uploaded segments:
    • s3://frontier-data-environments-dev/agentenv-recordings/85a3ca99deaa5bb3a997663d29f898f8/rec-6a964312adf8/0000.mp4 (18 frames, 780×492, 14.4 s)
    • …/rec-6a964312adf8/0001.mp4 (5 frames, 4.4 s)
    • and manifest.json

The hub (the frontend from scaleapi#170559 and the backend run locally against dev)

  • The run's Recording tab lists the recording, "Segment 1 of 2", and a download button for each segment.
  • Segment 0 loaded with readyState 4 and a 14.398 s duration. While playing, currentTime went from 0 to 2.99 s in 3 s.
  • At the end of segment 0 the player moved on to 0001.mp4 by itself.
  • The backend calls all returned 200: GET /api/v1/artifacts/…__recording-browser?version=1, /agents/trajectory for the manifest, and /agents/trajectory-url for each segment.
  • A download opened a presigned dev-bucket URL with attachment; filename="rec-6a964312adf8-0001.mp4", and a ranged fetch of it returned 206 with an MP4 header.
  • The local auth-gateway didn't start, because it needs an interactive SSO login, so the frontend was opened directly on :4100.

Found along the way, outside these PRs (follow-ups)

  • Starting a recording from a laptop fails. _grant in computer_recording.py asks for a 12–24 h upload grant, and laptop SSO credentials expire sooner, so the store raises GrantUnavailableError. Hosted runs aren't affected.
  • There's no way to choose a different browser env per run, because default_website_browser_env_id is fixed.
  • A failed run's stored context still marked its recording open, even though teardown had ended and registered it.
  • Segments are stored as application/octet-stream, not video/mp4. Chrome plays them anyway.

🤖 Generated with Claude Code

@sarah-chitty-1
sarah-chitty-1 merged commit 2df3443 into main Oct 28, 2026
14 checks passed
@sarah-chitty-1
sarah-chitty-1 deleted the sarahchitty/browser-recording branch October 28, 2026 00:46
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.

2 participants