--- title: "Run browser QA" description: "Drive a signup or checkout flow end to end on staging, screenshot every step, file an issue when a step breaks — and use shadow mode before you point it anywhere real." --- Sweeping pages is read only. Walking a *flow* is not: signup creates an account, checkout submits a payment form, and both leave something behind. `signup-checkout-test` is the template for that, and everything about how it is configured follows from the fact that it writes. ## What it does Drives the flow you name from a start URL, screenshots every step, and files a GitHub issue when a step fails. Its defaults are Safe writes, `safe` execution mode, a 15-minute timeout, and an allowlist covering the target site and `api.github.com`. ```bash curl -fsS -X POST "$WS/workers" \ -H "Authorization: Bearer $OBOL_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "slug": "checkout-flow", "display_name": "Checkout flow", "agent_passport_id": "agt_release", "template_id": "signup-checkout-test", "environment_classes": ["browser"], "permission_preset": "safe_writes", "execution_mode": "safe" }' ``` ## Point it at staging, and prove it This template's own sample input is deliberately marked not demo-safe. It walks a checkout with a synthetic test card, and Obol will not pretend that a card-shaped flow against an arbitrary target is a sandbox. Use a staging environment, and narrow the allowlist to it so the Worker cannot reach production even if the model is confused about which site it is on. ```ts const started = await obol.workers.run("checkout-flow", { inputs: { start_url: "https://staging.example.test/catalog", flow: "checkout", test_email: "qa+staging@example.test", issue_repository: "acme/storefront-qa", }, test_mode: true, }); ``` ## Shadow mode Browser and desktop test mode is **shadow mode**: the Worker reports the action it would take rather than committing it. That is the mode to run a new flow Worker in first — it produces the same output structure as production, so the deliverables tell you whether the walkthrough is right before any of it lands. ## Two kinds of thing a browser Worker does The distinction matters enough that the interface shows it, and no execution mode erases it. | | Verified capability | Computer-use action | |---|---|---| | Example | `github.issue.create` | click, type, screenshot | | Arguments | typed, and authorized by policy on those arguments | a coordinate and a string | | What it means | the action's effect is expressible to the policy engine | the application-level meaning of the click is not something Obol can guarantee | | Evidence | decided by the route the call took, and the receipt names the class | an observation of a screen | Filing the issue is the first. Clicking through checkout is the second. A screenshot of an order confirmation is evidence that a page rendered that way; it is not proof that an order exists in the vendor's system. Where an action's effect cannot be established from observations, the run stops with `ambiguous_effect_requires_review` rather than guessing — and a Worker's default of zero ambiguous-write retries means nobody retries a write whose outcome is unknown. `autonomous` mode asks for fewer approvals and still enforces every limit. It does not lift the restriction on high-impact arbitrary UI actions; that restriction is a semantic boundary, not a preference. ## When a step needs a login Use a saved session profile rather than putting credentials in the Worker's instructions. See [Authenticated browser sessions](/workers/authenticated-sessions). ## When it breaks mid-run Take the browser yourself. See [Take over a browser](/workers/take-over-a-browser). As of 2026-09-10 a run does not complete end to end. The orchestration service has an image and Compose services now, but the joins that would let it accept a run are still being built, so a start is refused at the hand-off. See [Overview](/workers/overview).