Skip to content

ADR 0003 — Playwright + Chromium for the agent

  • Status: Accepted
  • Date: 2026-04-26
  • Deciders: André Luiz Gallon

Context

The brief required real user navigation: the agent has to load not just HTML but also CSS, JavaScript, images, fonts and any third-party resources, while exercising real cookies, redirects and TLS handshakes.

A pure HTTP client (e.g. undici) cannot run third-party JavaScript or fire load / DOMContentLoaded the way a browser does, and we need those signals for the per-cycle metrics.

Decision

  • The agent uses Playwright with the bundled Chromium.
  • The runtime image is the official mcr.microsoft.com/playwright:v1.49.1-noble, which already ships the required system libraries (libnss3, libasound2, etc.) and a matching Chromium build.
  • One Chromium per agent, reused across cycles, but a fresh BrowserContext per cycle so cookies / cache / IndexedDB / service workers / DNS are wiped between runs.
  • A small browser pool keyed by (httpVersion, host) lets HTTP/3 forcing (--enable-quic --origin-to-force-quic-on=…) coexist with default-protocol navigation.

Consequences

  • ✅ Real Web Vitals, real TLS handshakes, real subresource fetches.
  • ✅ Native HTTP/3 support via Chromium command-line flags.
  • ⚠️ Each agent reserves ~300–500 MB of RAM; the practical ceiling is ~10–15 agents on a 16 GB laptop. Kubernetes HorizontalPodAutoscaler scales to 300 on sized clusters.
  • ⚠️ Chromium occasionally hangs; mitigated by the per-target circuit breaker, the consecutive-failures Chromium sentinel, and graceful shutdown on SIGTERM.

Alternatives considered

  • Puppeteer — works but has weaker multi-browser story and less active community.
  • Headless Chrome via CDP directly — avoids Playwright but loses the ergonomics for BrowserContext lifecycle, Web Vitals helpers and device emulation (Pixel 7 mobile profile).
  • Headless Firefox / Webkit — inferior HTTP/3 support today.