Skip to content

Frazer Browsers

Frazer Browsers gives agents browsers and desktops. Agents test and debug through the same screens people use. A browser here is a Chromium browser that one agent session drives, through a Rust executor that gives every harness the same compact view of the page, the same actions and a receipt for every step. It runs in the agent’s own cell, next to a preview, or on a devbox or laptop, and it records everything it does. Agents use it to check a change through the UI against the real backend, to reproduce an issue a user hit, and to hand a page to a person when only a person may act.

View What it holds
interactive (the default) One line per actionable element: its role, accessible name, state and ref, with landmarks and headings as context
content The visible text in reading order, without refs
full The whole accessibility tree with refs, on request
delta What changed since the last snapshot of the same document, after every action

A snapshot covers the viewport by default, or the full page, or one landmark or ref. Frames appear inline with their own refs, including cross-origin frames, and open shadow roots are included. Page text is built from what the page renders, never from raw source, so hidden text never reaches the model, and it is wrapped in content boundaries with a random nonce and its origin. A snapshot over its size limit returns its first part and a handle to page through. Screenshots are for layout, images and canvases, with zoom for small text; they carry no refs, so they are never the way to find a control.

--- PAGE nonce=7f3a origin=https://pv-4718.preview.frazer.run ---
main "Checkout"
textbox "Email" value="buyer@acme.example" @e4
textbox "Gift card code" value="" @e11
button "Apply" @e12
region "Payment card" (cross-origin frame: the payments fake)
textbox "Card number" @f1e2
button "Pay $42.00" @e19
--- END nonce=7f3a ---

A ref names an element until the element is replaced or its document navigates; it is never reused for another element. Every action returns a receipt that the executor writes into the Fir session: the step, the action and its resolved target, the outcome (done, failed with the reason, or outcome_unknown when the executor cannot tell whether a change ran, which is never retried blindly), the effects (navigation, popups, dialogs, downloads, requests and their statuses, new console errors, the delta), the rule that allowed it, the time and the browser seconds it used.

Errors name the next call:

Error Means Next
STALE_REF The element was replaced or the page navigated snapshot
AMBIGUOUS_TARGET A locator matched several elements snapshot --scope <landmark>
NOT_ACTIONABLE Covered, disabled or outside the viewport The receipt names what covers it
ORIGIN_NOT_ALLOWED The origin is outside the run’s origin set A person’s approval to widen it
POLICY_ASK The action needs an approval Wait for the approval card
OUTCOME_UNKNOWN A change may have run Observe (snapshot, net) before any retry
NOT_SETTLED The page did not settle in time wait --settled, or snapshot it as it is
AUTH_REQUIRED The app asks for a login login --persona <p>, or a hand-off for a real sign-in
CAPTCHA_PRESENT A challenge blocks the page Hand off: Frazer never solves one
FUNDS_EXHAUSTED The budget or the balance cannot cover the run (“Not run: no funds”) The balance call, then the top-up person task
INJECTION_SUSPECTED Page content looked like instructions The run’s policy: go on with the origin read-only, or hand off
STEP_LIMIT_REACHED, BUDGET_REACHED The run stopped at a limit you set (exit 14); the result so far is kept Raise the limit or continue from haltedAt
STALE_CAPTURE A pixel action names a screenshot the screen no longer matches Take a new screenshot
METHOD_NOT_ALLOWED A protocol command the gate refuses The receipt names the rule

Waits and checks. wait takes a URL pattern, text, a ref’s state, a function or settled. A check records an assertion: a UI check (visible text, a value, a role’s state) or a state check (an API response, a row read through the preview’s data API, a page tool’s result). A test passes on state checks, never only on how the page looked, and each fact a plan item’s acceptance criteria expect is checked on its own. An agent’s “verified in the UI” counts only when its receipts show the path: the page opened, the action taken, the state read.

Page tools and the app map. Tools a page registers through WebMCP are offered as typed tools, and Frazer’s own console registers its actions that way. Agents set up and check through APIs and page tools, and drive the UI for what the test is about. A repository may keep an app map (.frazer/app-map.yaml: routes, landmarks, key flows, personas, readiness signals and page tools), written by an exploring agent and reviewed like code.

  • Scripts. An agent sends a short JavaScript program in a familiar end-to-end-test style (page.goto, getByRole(...).click(), fill, check). It runs in an isolated engine inside the executor with no file, network or process access; the call has one receipt and each step a child receipt; policy and budget are checked per step, so a script can never carry an action the rules would refuse one step at a time. It stops at the first failed step and reports what ran. Limits by default: 60 seconds, 200 steps, the run’s origin set; --max-steps and --budget set your own, and a run stopped at either exits 14 with what it did so far.
  • Each model family’s own browser and computer tools. Models are trained on their own labs’ tool shapes, so the executor is the driver behind each family’s toolset, and the harness picks the face per model family by default. The harness Lab measures that choice on your own flows.
  • Frazer’s tools. MCP tools (browser_snapshot, browser_click, browser_run and the rest), the CLI and the API, with the same verbs and JSON results, for any harness. Every action takes --dry-run and --estimate.
  • The protocol endpoint. frazer browser open --cdp returns a wss:// endpoint bound to that browser and its Fir session, so existing end-to-end suites and agent frameworks connect unchanged; the same browser speaks WebDriver BiDi. A method gate refuses with METHOD_NOT_ALLOWED the commands that would step around the policy: a context with its own proxy, ignoring certificate errors, downloads outside the cell, attaching to another target, and, for agents, page scripts on third-party origins. Every input and navigation still writes a receipt, and the cell’s network still enforces egress below the browser.

Suspended between steps. Models take seconds between steps, so an idle browser is suspended while it waits and resumes on the next action; open streams stay inside step mode’s held clock.

  1. Reaching the preview. Previews on frazer.run sit behind Frazer sign-in. A browser in the preview’s network reaches it with its cell’s workload identity: the egress gateway adds a short-lived token for that preview host only. No secret in the cell, no person task.
  2. The app’s own login. The preview’s recipe declares personas (buyer, admin). frazer browser login --persona buyer asks for a login handle that expires within 10 minutes and redeems it once at the preview’s own login path. For apps on Frazer sign-in, the preview’s front door mints the app’s session from the handle; for apps with their own login, Frazer seeds the persona in the app’s user store, runs the app’s own login once per persona and preview revision with generated credentials kept in the preview’s secrets, and installs that session. Passkeys come from a virtual authenticator seeded per persona, one-time codes from seeds Frazer holds, and email links and codes from the preview’s inbox. When the test is about the login itself, the persona signs in through the real login form against the real backend.

The session ends with the run (1 hour by default), cookies stay on the preview’s own host, and every mint is an audit row. A real third-party login is Sign in here: a person task, with the recording paused while the person signs in. On an allowed third-party origin the agent asks with frazer browser handoff --reason sign-in --origin <origin>, and the person gets a sign-in card: it shows the verified origin and the form’s fields, the person types into Frazer’s own interface and never the page, the executor fills the form and the model never sees the values; it expires in 5 minutes and a retry never fills the form twice. A take-over remains for what a card cannot carry, such as a CAPTCHA. A persona’s passkey is answered from outside the browser’s VM, so its private key never enters it. An agent’s run never gets a password in a prompt, a credentials file in the cell or a person’s own browser profile.

Captured Format By default
Steps and receipts JSON, in the Fir session Always
Snapshots around each step The executor’s text views Always
Network HAR 1.2, bodies capped at 64 KiB and scanned Always
Console and page errors Source-mapped stacks Always
DOM recording The same open format as Frazer’s session replays, so one player serves both Always
Video Frames at 5 per second as WebM, with the agent’s cursor and each step as a chapter Always on Frazer’s fleet; on request locally
Screenshots At checkpoints and on failure Always
Versions Engine build, app build digests, preview, data branch, persona, flow revision Always

Password and card fields, and fields the app map marks, are never captured: they are masked in the DOM stream, the video and the HAR. Secret-bearing headers are dropped, bodies pass the gateway’s data-loss checks, persona data is synthetic, and each recording carries a redaction report. Recordings are stored by content in Frazer Storage and kept 14 days for passing runs and 90 days for failing ones by default; a recording attached as evidence keeps the evidence’s retention. Playback syncs the DOM, the video, the network and the console by step and compares two runs. A video is a view of a run, never its verdict.

A flow (tests/flows/<name>.flow.yaml) is a recording’s steps as an editable file with role and name targets, the persona and data as parameters, UI and state checks and readiness. Flows come from recordings, a person’s walkthrough or an agent, and they are reviewed like code.

Rerun Environment Speed Catches
Fast The new frontend build, with the network answered from the recording Seconds Frontend regressions, with very little flake
Deep A preview at the exact version and data branch, with the real backend Minutes Everything a user would see, the backend included

Each rerun pins the clock, randomness, time zone, locale, fonts, animations, network, viewport and device as asked. Verdicts are pass, fail (with the failing step and the failure signature), reproduced k of n, flaky, blocked (the environment failed) and Not run: no funds. Flows map to the code they exercise, so only the flows a change reaches rerun. When a flow fails for a reason that is not the product (a renamed label), an agent proposes the healed flow as a pull request with before and after recordings; a flow that proves an acceptance criterion is read-only to the implementing agent, and its change goes to the plan’s approver. An agent’s successful run can be proposed as a flow, so the next run needs no model.

Step What happens
1. Evidence The issue’s evidence: a user’s session replay, a HAR, the error group, the release and the steps, redacted
2. Environment A preview of the issue’s moment: the services that ran then, data branched at that second from the masked replica, the failing requests’ trace IDs, and services isolated so the past never mixes with today’s
3. Steps A flow from the user’s replay, from the HAR, or written by an agent from the issue’s text; a masked field becomes a persona-filled parameter, never the original value
4. Rerun Three reruns by default with the clock, randomness and network pinned; the failure signature (a status and error code, an assertion, a console error) must match the issue’s
5. Evidence back The recording is attached to the issue as an attested reproduction: run by Frazer CI in a preview with these digests
6. The test The exported test goes into the fix pull request, and Frazer CI reruns it on its own: it fails at the issue’s version and passes at the fix

On acme/storefront#4711 “Checkout fails with 500 on gift-card orders since v2.14.2”, filed by the monitor agent, the fixer agent’s session s-4a71 opens browser br-7a2c next to the reproduction preview pv-4718 as buyer and reruns the user’s steps: reproduced 3 of 3, signature POST /api/checkout → 500 GIFT_CARD_STATE. Recording rec-4711a goes on the issue; the exported test tests/e2e/repro/4711-gift-card-checkout.spec.ts fails at v2.14.2 and passes on the fix, pull request #4718 (demo data). A reproduction that fails every rerun ends not_reproduced with what was tried.

For every version of a pull request that touches UI or a user flow, the test plan runs:

  1. Flow reruns with no model: the fast tier for every such pull request (two smoke flows by default), and the deep tier with the full flow set at the top of each stack.
  2. An agent verifies what flows do not cover: the plan item’s acceptance criteria, through the UI against the real backend, with state checks; new paths become proposed flows.
  3. Evidence on the pull request: the test run, its recordings and checks. Because a tester’s session produced them, not the author’s, they are an independent source of evidence for the second opinion and auto-merge.
  4. Outcomes link back: a UI bug that escapes links to the flows that ran on its pull request, and the gap becomes a flow.
Default How
Network The cell’s egress allows the preview’s origins and its declared fakes only; private and link-local ranges are blocked and checked again after redirects. A project admin widens it per origin, as a plan
Your own apps by default A run’s origins are your previews on frazer.run, the domains your organization verified and the fakes your recipes declare; anything else is ORIGIN_NOT_ALLOWED. A preview’s own third-party resources (map tiles, fonts, a payment frame) are declared in its recipe: the page loads them, and the agent never navigates to or acts on them
Outside sites, by opt-in A project admin adds an outside origin to the project’s browser policy as a reviewed change, with its purpose (vendor_portal, docs or research), its mode (read-only or read-write) and its rate limit (by default 1 request a second and 2,000 a day). The policy file is a sealed path: an agent may propose an origin (frazer browser policy propose), and a project admin who did not write the change approves it
Origin sets Per run: the origins an agent may read and the origins it may act on; frames from other origins are not shown
Schemes http and https only, always
Actions Seven action classes for every model: payments and legal terms Hand off; creating accounts, sending messages and changing sensitive data Ask; other data changes Ask outside the preview; consent Auto on your previews with test personas, Hand off elsewhere
The action reviewer A model of another family checks an action against the task from the action’s metadata, never from page content
Injection probes The gateway’s classifiers scan page text and screenshots before the model reads them
Page scripts Off for agents by default, on for flows and CI
Downloads, uploads Downloads stay in the cell and are scanned; uploads come only from the workspace
Profiles A fresh profile per run
Identity No stealth, no fingerprint spoofing, no challenge solving. On outside sites agents sign their requests with Web Bot Auth by purpose: as your organization on vendor portals and docs, as Frazer for research reading, with your own rate limit. Agents slow down on 429 and follow robots.txt on research sites
Kill switch Your organization’s kill switch stops every browser and desktop

The renderer’s own sandbox stays on inside a microVM per browser, and engine security fixes ship within 72 hours, or 24 when a flaw is exploited.

A desktop (dsk-…) is a Linux VM with a graphical session (Linux first; macOS on Macs dedicated to one customer and Windows on the customer’s own licenses come after) that one agent session drives, for desktop apps, flows that leave the browser (a file dialog, an OS prompt) and apps with no API. It has the same Fir session, receipts, policy, recording and live view as a browser. The agent uses the app’s own protocol first (Chromium-based desktop apps expose the same snapshots and refs), the operating system’s accessibility tree second, and pixels last. An allowlist names the apps a run may use; system settings, keychains and credential stores are off limits.

Terminal window
frazer desktop open --image ubuntu-26.04 --size 4x8

Browsers bill $0.02 per active browser-hour, by the second, where a browser-hour is the wall time of an active browser session: UI flows, exploratory testing and reproductions through the UI. Warm pools and idle browsers are not billed. Recordings bill as Frazer Storage; the agent that drives the browser bills its own runtime and tokens; every response reports the browser time it used. A run whose estimate does not fit the budget or the balance does not start and says so (“Not run: no funds”); it never falls back to a cheaper run. The price is an estimate, calibrated against measured use. The price drops to $0.01 per browser-hour at the first quarterly re-read whose measured cost is at or below $0.006 a wall-hour.

Terminal window
frazer browser open https://pv-4718.preview.frazer.run/checkout --persona buyer
frazer browser snapshot --view interactive
frazer browser fill @e11 GC-2Q7F
frazer browser click @e12
frazer browser run --script checkout.js --max-steps 200 --budget 0.05
frazer browser policy get --identity
frazer browser check --api 'GET /api/orders?last=1' --expect '{"state":"paid"}'
frazer browser rerun rec-4711a --preview pv-4718 --times 3 --pin clock,random,network
frazer browser repro --issue 4711 --preview pv-4718

frazer browser … runs the browser’s own binary, which also runs alone on a devbox or laptop and follows the CLI contract: help as data, the error envelope with next, the exit codes, no prompts. frazer browser list, get and close act on hosted browsers (br-…), each bound to a Fir session.

CLI

CommandWhat it does
frazer browser openOpen a browser for your session at a URL, next to a preview and as one of its personas; returns the first snapshot.
frazer browser snapshotThe page as an agent reads it, interactive (the default), content, full or the delta since the last snapshot, with refs such as @e12.
frazer browser runRun a short script of many steps in one call, with one receipt per step; it stops at the first failed step.
frazer browser checkRecord a check on the page or on state behind it (an API response, a row); a test passes on state checks.
frazer browser loginSign in as one of the preview's personas with a one-time login handle; no real credential reaches the agent.
frazer browser handoffHand the page to a person for a real sign-in, a challenge or a payment, as a person task.
frazer browser policy getThe project's browser policy, the outside origins it allows with their purpose, mode and rate limit.
frazer browser policy proposePropose an outside origin as a reviewed change; a project admin who did not write it approves.
frazer browser rerunRerun a recording or a flow k times against a preview, with the clock, randomness and network pinned.
frazer browser reproReproduce an issue from its evidence in a preview at the issue's moment, and export the failing test.
frazer browser exportExport a recording as an editable flow or an end-to-end test file.
frazer browser listList hosted browsers (br-…) with their sessions, states and causes; get and close complete the set.
frazer desktop openOpen a Linux desktop VM for your session, to drive apps outside the browser.

All of them: CLI reference.

MCP tools

ToolWhat it does
browser_openOpen a browser and return its first snapshot.
browser_snapshotRead the page as compact text with refs.
browser_runRun a script of many steps, with a receipt per step.
browser_checkCheck the UI or the state behind it.
browser_reproReproduce an issue and return the recording and the exported test.
browser_handoffAsk a person for a sign-in, a challenge or a payment; a sign-in card on an allowed outside origin.
browser_policy_getThe project's browser policy.
desktop_screenshotA screenshot of a desktop, for what the accessibility tree misses.

All of them: MCP tools reference.

  • Frazer QA: the environments and test plans the browser runs against
  • Issues: evidence and reproductions
  • Harnesses: which face each model family gets
  • Sessions: where every receipt and recording is linked