Projects

Browser testing and previews

Start your app inside the agent's sandbox, let the agent test it in a headless Chromium, and open the same app yourself from the Preview button.

With browser: and preview: set, SI Fabrik starts your app inside the sandbox before each attempt and gives the agent a headless Chromium through Playwright's MCP server. The agent checks user-facing changes in the browser and saves screenshots that are attached to the run. You can open the same app from Preview, and watch or take control of the agent's browser from Browser.

Set it up#

  1. Build the browser image

    On Sandboxes, build the browser image, harness-agent-browser:latest. It's the agent image plus Chromium with its OS libraries, the Playwright MCP server and the Playwright CLI. (The base image is built first if it's missing.) Cloudflare sandboxes use the bridge's browser image instead.

  2. Add browser and preview to WORKFLOW.md
    WORKFLOW.md
    browser:
      enabled: true               # Chromium + Playwright MCP in the sandbox
      viewport: 1280x800          # default
    preview:
      setup: npm ci               # once per workspace
      command: npm run dev -- -H 0.0.0.0
      port: 3000
      ready: /api/health          # waited for before the agent's turn
      ready_timeout_s: 300        # default

    Or use Workflow → Settings → Browser & preview. When your repository has a package.json, the form suggests settings for Next.js, Vite, Remix, Nuxt or Express. Press Use to fill them in.

  3. Listen on 0.0.0.0

    Dev servers must listen on 0.0.0.0 inside the container, not only 127.0.0.1, for the Preview button to reach them. That's why the examples pass -H 0.0.0.0 (Next.js) or --host 0.0.0.0 (Vite).

What happens on each attempt#

  1. preview.setup runs once per workspace.
  2. SI Fabrik starts preview.command inside the sandbox and waits until http://localhost:<port><ready> answers, up to ready_timeout_s. The app's output goes to .harness/preview.log.
  3. The agent's turn starts. Its system prompt says the app is running at http://localhost:<port>, how to restart it if it crashes, and to test user-facing changes in the browser.
  4. The agent drives Chromium through the browser MCP server: one browser per task, with a fresh profile every run. It saves screenshots under .harness/artifacts/.
  5. When the attempt ends, the app and the browser stop with the agent. SI Fabrik copies the screenshots (PNG, JPEG or WebP, up to 30 per attempt and 10 MB each) into the run's history, and keeps .harness/ out of commits.

The run shows Browser checks · N screenshots in its transcript.

Open the app yourself#

On a running agent, press Preview. The app is served on loopback only:

  • Docker: http://127.0.0.1:<port> (one free loopback port per running sandbox).
  • Cloudflare: http://127.0.0.1:79xx, proxied through the bridge.
  • Host (no sandbox): http://127.0.0.1:<port>.
Note

Preview, the live browser and the terminal work for projects on this Mac. For projects on a harnessd server they're not available through the server yet.

Watch or take control of the browser#

Press Browser on a running agent to open a live view of the agent's browser. You can take control for logins, 2FA and SSO pop-ups, to show the agent a flow, or to get it unstuck. See Live browser.

Sign in with test accounts#

Save test accounts under Edit Project → Test logins, and the agent signs in with the browser_sign_in tool without ever seeing the password. See Test logins.

Security#

  • The browser obeys the sandbox's network allowlist; localhost is always reachable. Chromium's background calls to Google services are off.
  • Its DevTools port is bound to 127.0.0.1 inside the sandbox. SI Fabrik reaches it through docker exec or the bridge's authenticated exec, so it's never exposed on a network and other sandboxes can't reach it.
  • Web pages are untrusted content. The prompt tells the agent never to follow instructions that appear on a page.
  • No browser profile or credentials carry over between runs.
  • Browser containers get a 1 GB /dev/shm, which Chromium needs.

See also#