Repository navigation
feat(browser): browser task steps for cookies, local storage and tabs (FD-4943) - #518
Merged
earakely-scale merged 9 commits intoNov 7, 2026
Merged
Conversation
… (FD-4943) A task_steps/browser package: a BrowserStep base that finds the website browser in the deployed env and calls browser/v1 with the control token, and browser_set_cookies, browser_delete_cookies, browser_set_local_storage, browser_clear_local_storage, browser_open_tab, browser_close_tab and browser_activate_tab on it. Preflight refuses an env with no browser, a browser it doesn't have, or none named among several; each step checks its operation on the deployed card, and tab steps pick the one tab at their URL as the browser shows it. tabs/open takes background, opening the tab behind the active one, which stays active. browser_connect_cdp moves into the package on the same base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…if the new one took its place So a tab another call switched to while the new tab loaded stays in front. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h outside agents runs them Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… deploy_env pins A task's preflight, and a bundle's, give each step the env versions the deploy_env steps before it pin, the first for each env, and the browser steps, load_artifact and snapshot_computer_env read their env at that version through stored_env, else at its latest. A step reading an env its run deploys at another version no longer passes or fails preflight on the wrong one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…b URLs match a host in another script A browser built before tabs/open took background refuses an unknown parameter, so a plain open sends none and works on it. A tab step's URL and a tab's are both normalized with the host as punycode, as the browser shows it, so https://bücher.test/ matches its tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, by UTS 46 Python's idna codec maps faß.test to fass.test, a different site, where Chromium keeps them apart, so a tab step naming one could act on the other's tab. The host is now encoded with the idna package's UTS 46 mapping without transitional processing, as Chromium does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…written, and a task pinning the browser's version runs them The browser steps check opens a tab at faß.localhost, sees chromium spell it xn--fa-hia, and closes it by the URL as written, in a desktop and alone. A new browser computer test runs a whole task through task.run: its deploy_env pins a version of the browser whose latest version has none, its preflight passes on the pinned one, the same task unpinned reports every browser step, and its tab and cookie steps run on the version deployed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…TS 46 as Chromium does idna.encode applies IDNA 2008's code point rules, so a host Chromium takes, such as ☃.net, was left in Unicode and no tab matched it. Hosts are now mapped by UTS 46 without transitional processing and each label put in punycode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
earakely-scale
deleted the
edgararakelyan/fd-4943-m514-browser-task-steps-in
branch
November 7, 2026 01:47
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 and why
Task designers can now change a website browser's state partway through a task with typed steps, without loading a whole state through
load_artifact. For example, a step can sign a user in between agent turns, open a reference page in a background tab, or clear storage to simulate a logout. This is FD-4943 (M5.14). Its outcome and seven decisions are recorded there.A new
task_steps/browser/package holds aBrowserStepbase and one thin step per change. Each step calls onebrowser/v1operation with the env's control token, asbrowser_connect_cdpalready did.browser_set_cookiescookies, in the shapecookies/settakescookies/setbrowser_delete_cookiesname?,domain?,path?(decision 4)cookies/deletebrowser_set_local_storageorigin,itemsas a map (decision 3)local_storage/setbrowser_clear_local_storageorigin?local_storage/clearbrowser_open_taburl,background?(decision 2)tabs/openbrowser_close_taburltabs/list, thentabs/closebrowser_activate_taburltabs/list, thentabs/activateEvery step also takes
env_id, andbrowserto name one when the env has several.Finding the browser: among the deployed env's children, by the card that serves
browser/v1. That covers chromium inside a computer and the browser alone (chromium-driver). Browser members of a multi env come with M8.14, and thecontextargument with M8.15.Preflight (decision 1) refuses, before deploy, a step whose env has no browser, names a browser the env doesn't have, or doesn't name one when the env has several. It reads the stored env: a computer env's apps that declare
browser: true. Malformed fields are config problems:CookieToSet, reported without its value;backgroundthat isn't true or false.At run time:
bücher.testasxn--bcher-kva.test), default port dropped,/for an empty path. No match, or several, fails the step and lists the open tabs' URLs.context.metadata["browser_steps"][<step id>],browser_open_tabrecords the new tab's id, the tab steps record the tab they acted on, andbrowser_delete_cookiesrecords how many cookies it deleted.tabs/open {url?, background?}(decision 2, protocol): a background tab is created behind the active one, which stays active on screen and intabs/list. On the headless browser alone, it's still held to the window's size before it loads. If Chrome hands the new tab focus anyway, agentenv brings the previously active tab back to the front.browser_open_tabsendsbackgroundonly when it's set: a browser built on an earlier protocol refuses an unknown parameter, so plain opens keep working on it, and only a background open there fails, namingbackground.Preflight reads the env at the version the task pins (from Greptile's review).
Task.preflightand a bundle's preflight give each step the env versions pinned by thedeploy_envsteps before it, the first for each env, throughagent_env.task_step.preflight.pinned. The browser steps,load_artifactandsnapshot_computer_envread their env at that version throughstored_env, else at the latest; before, all three read the latest.TaskStep.deploys_env()says what a step deploys, anddeploy_envreturns itsenv_idandenv_version.Episodes: the seven new steps name no agent, so they're listed in
task/episode/rules.py'sUNAFFECTED, and a task with agents played from outside can run them.browser_connect_cdpmoves totask_steps/browser/connect_cdp.pyas aBrowserStepsubclass (decision 7). Its type name and behaviour are unchanged; it now shares the finder, and gains the preflight.Not in this PR: read steps (graders read
snapshot_env's sections); thecontextargument (M8.15); multi-env browser members (M8.14).apply_server_configis unchanged.How it was tested
ruff check: clean.test_website_browser.pyaddsbackgroundtabs. The tab opens behind the active one. If focus moves to it anyway, the previously active tab is brought back to the front, but a tab another call switched to meanwhile stays in front.test_browser_steps.py(42 tests, the HTTP boundary mocked):test_preflight_pinned_versions.py: a task's preflight and a bundle's read a browser step's env at the latest version before any deploy, at the version the firstdeploy_envpins after it, and still at that one after a second deploy pins another.load_artifactandsnapshot_computer_envread the pinned version too.test_browser_connect_cdp.pypasses unchanged except for its import path, and the entity-refs and episode-rules checks cover the new steps.task_step,bundle,env,serialization): 5518 passed. The 2test_disk_recipefailures fail on macOS only, and a gateway time-trigger test failed once under the parallel run and passes on its own.browser_steps.check_browser_stepsruns in a desktop and on the browser alone, each step built from a task's JSON through the registry and passing preflight on the real stored env:browser_set_cookiesandbrowser_set_local_storagesign in a tab thatbrowser_open_tabopens in the background: it loads signed in, while the start tab stays active;browser_activate_tabbrings it to the front by its URL, andbrowser_close_tabcloses it;browser_delete_cookiesrecords 1 deleted, and withbrowser_clear_local_storagethe site has no cookies or storage left;http://faß.localhost:8783/othershows asxn--fa-hia.localhost, as UTS 46 without transitional mapping spells it, andbrowser_close_tabcloses it by the URL as written.task.run(browser alone, amd64 on a VM; CI runs it on every push): the browser env is stored at a new id as version 1, and as version 2 with no browser declared. A task'sdeploy_envpins version 1, so its preflight passes, while the same task unpinned reports all five browser steps. Its cookie and tab steps then run on the version deployed, the open, activate and close steps record one tab, and the cookie delete records 1.browser_connect_cdp, now on the shared base, passes its e2e on amd64: it hands an echo agent its address with the env's tools hidden, which a reset ends until the step reruns. The tests of an agent keeping its address through restarts and of two CDP agents at once also pass, along with the Playwright, Puppeteer and gateway CDP tests. The echo-agent tests are deselected on arm64. The Browser Use CLI test isn't part of this suite.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; the previous Unicode tab-matching issue is fixed.Summary
Adds seven browser task steps for cookies, local storage, and tabs, with shared browser lookup and preflight checks.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Browser task step] --> B[Find deployed browser] B --> C[Check browser supports operation] C --> D[Call browser/v1 with control token] D --> E[Change cookies, storage, or tabs] E --> F[Record tab ID or deleted-cookie count when applicable]Reviews (10) · Last reviewed commit: "fix(browser): tab URLs keep a host IDNA ..." · Reviewed by Greptile