How It Works
Autowright is three layers with one contract between them: evidence flows forward, and the failing script is never blocked.
Layer 1: The browser proxy
@autowright/browser wraps Playwright’s chromium in a transparent JS Proxy.
When you call browser.newPage(), the returned object is a Playwright
Page — the proxy intercepts method calls without changing behavior:
- Action methods (
goto,click,fill,evaluate, …) are logged with timing and wrapped in try/catch for error capture. - Locator methods (
locator,getByRole, …) return proxied children, so capture follows chained calls. - Everything else passes straight through with correct
thisbinding.
Alongside the proxy, a PageObserver listens to page events and keeps a rolling record of network requests, console messages, screenshots (last 3), and crash signals.
On failure
When any intercepted call throws:
- The error is recorded in the action log with its duration.
- A final DOM snapshot and screenshot are captured.
- The error is classified — observer state first (was the network down? did the browser crash?), then message heuristics. See Error Classification.
- Artifacts are saved to local disk (a safety net that always happens), then
bundled into a
.tar.gzand uploaded to S3-compatible storage. - A lightweight
ErrorContext— classification, error hash, action log, and the bundle URL, not the bytes — is POSTed to the service. - The original error is re-thrown. Your script sees exactly what plain Playwright would have shown it.
Layer 2: The service
@autowright/service is a small Express coordinator (port 4400, SQLite
state). It registers scripts, receives error metadata, deduplicates by error
hash so a scraper failing every five minutes produces one fix job instead of
a hundred, and exposes read APIs for the dashboard. It never touches artifact
bytes — only URLs pass through it.
Layer 3: The fixer
@autowright/fixer polls the service for pending jobs and processes each one
in a sandbox:
- Download the evidence bundle.
- Clone the target repo (shallow, blob-filtered, 10-minute timeout).
- Run the agent — the Claude Agent SDK with
Read,Edit,Glob, andGreptools (noBash, deliberately), confined to the job’s working directory. The agent reads the captured DOM, the action log, and your source, then edits the code. - Confidence gate — the agent must conclude with an explicit verdict:
FIX_OUTCOME: FIXEDorFIX_OUTCOME: CANNOT_FIX. No confident verdict, no PR. - Deliver — commit, push, open a GitHub pull request, and notify Slack with the outcome and the real cost (dollars, tokens, turns, duration).
The dashboard
A Next.js dashboard (port 4300) sits on top of the service’s read APIs:
totals for runs, fixes, and needs-attention outcomes; per-fix detail pages
with cost and effort breakdowns, files changed, agent summary, PR link, and
the artifact bundle. See Self-Hosting.
Design principles
- No framework. Autowright deliberately has no step DSL and no test runner. Your code is Playwright; Autowright is invisible until failure.
- Never block, never swallow. Errors always propagate to your script. Fixing is out-of-band, and every failure ends visibly — as a fix PR or a needs-attention notification.
- Evidence over guessing. The agent reasons over what actually happened — the real DOM at failure time, the real network log — not a re-run.