| name | webwright |
| description | Use when the user needs to automate a real web task through a browser — filling forms, applying filters, extracting data, clicking through multi-step flows, or building reusable web automation scripts. Use when a task requires interacting with a live website where the agent must navigate, select, verify, and capture evidence. Do NOT use for API calls, static scraping, or tasks that don't need a real browser. |
Webwright
Overview
Webwright is a code-as-action browser automation approach. Instead of clicking one button at a time, the agent writes full Playwright scripts, runs them, inspects screenshots and output, then iterates. The browser is disposable — the code and logs are the persistent artifact.
When to Use Webwright
Use Webwright when:
- Automating a web workflow (search, filter, form-fill, multi-step flow)
- Extracting structured data from a site that requires interaction
- Building a reusable, parameterized web automation CLI tool
- The user explicitly asks to "automate a website", "fill out a form", "search and extract", "build a web scraper", etc.
- A task needs screenshot evidence that specific filters/selections were applied
Do NOT use Webwright when:
- The target has a REST API — call the API directly instead
- The task is static HTML scraping with no interaction — use
httpx + beautifulsoup
- The task only needs a web search — use Perplexity skill
- The task is browser testing (e.g., testing our own apps) — write standard Playwright tests
- The user just needs to read a webpage — use
curl/httpx to fetch it
Decision Flowchart
Need to interact with a website?
├─ Is there an API? → Use the API directly
├─ Just fetching static content? → httpx / curl
├─ Just searching the web? → Perplexity skill
├─ Testing our own app? → Standard Playwright tests
└─ Need to drive a real browser (forms, filters, clicks, multi-step)?
└─ → Webwright
Prerequisites (one-time)
pip install playwright && playwright install firefox
Firefox is preferred over Chromium — some sites (Akamai-protected, Cloudflare) reject Playwright Chromium with TLS/H2 fingerprinting but load cleanly under Firefox.
No API keys required. The agent itself provides visual verification (no external LLM calls).
Modes
- One-shot (default):
final_script.py solves the task for the literal values provided.
- CLI tool (
/webwright:craft): final_script.py is a reusable, parameterized CLI with argparse. Use when the user says "make it reusable", "parameterize", "I want to run this again with different values".
Workspace Contract
Every Webwright run follows this structure:
WORKSPACE_DIR/ # e.g., outputs/<task_id>/
├── plan.md # Critical points checklist
├── screenshots/ # Exploration screenshots
├── final_script.py # The automation script
└── final_runs/
├── run_001/
│ ├── final_script.py
│ ├── final_script_log.txt
│ └── screenshots/
│ ├── final_execution_1_open_page.png
│ ├── final_execution_2_apply_filter.png
│ └── final_execution_3_results.png
└── run_002/ # If run_001 failed verification
└── ...
Rules:
- Work only inside
WORKSPACE_DIR
- Each clean execution gets its own
final_runs/run_<id>/ (incrementing integer)
- Viewport is always
1280x1800. Never use full_page=True screenshots
- Browser is headless Firefox, launched fresh each run — no persistent session
Workflow
1. Plan
Parse the task into critical points (CPs) — every constraint, filter, sort, selection, or datum. Write to plan.md:
# Task
<task description>
# Critical Points
- [ ] CP1: <constraint>
- [ ] CP2: <constraint>
Each CP must be independently verifiable from a screenshot or log line.
2. Explore
Run scratch Playwright scripts to discover selectors and confirm controls exist. Use the browser launch skeleton from reference/playwright_patterns.md. Print ARIA snapshots, URLs, titles. Save exploration screenshots to WORKSPACE_DIR/screenshots/.
3. Author final_script.py
Place in final_runs/run_<id>/. Instrument it:
import asyncio
from pathlib import Path
from playwright.async_api import async_playwright
RUN_DIR = Path(__file__).parent
SCREENSHOTS = RUN_DIR / "screenshots"
SCREENSHOTS.mkdir(parents=True, exist_ok=True)
LOG = RUN_DIR / "final_script_log.txt"
LOG.write_text("")
def log(step: int, msg: str) -> None:
line = f"step {step} action: {msg}\n"
LOG.open("a").write(line)
print(line, end="")
async def main():
async with async_playwright() as p:
browser = await p.firefox.launch(headless=True)
ctx = await browser.new_context(viewport={"width": 1280, "height": 1800})
page = await ctx.new_page()
await page.goto("<URL>", wait_until="domcontentloaded")
await page.screenshot(path=str(SCREENSHOTS / "final_execution_1_open.png"))
log(1, "opened start page")
final_value = "<extracted result>"
LOG.open("a").write(f"\nFINAL_RESPONSE: {final_value}\n")
await browser.close()
asyncio.run(main())
4. Execute and Verify
Run the script. Then verify every CP against the screenshots and log:
- Identify screenshot/log evidence for each CP
- Read each PNG and confirm evidence is unambiguous
- Tick the CP only when evidence is concrete
- If any CP fails → diagnose, fix, re-run in
run_<id+1>/
5. Report
Report the final result to the user with evidence summary.
Hard Rules
- Use stable selectors (
get_by_role, aria-label) — never brittle CSS classes
- If a site exposes a dedicated control for a requirement, you MUST use it (not search-box queries)
- Numeric/date/quantity constraints are exact — wider buckets are failures
- Ranking language ("cheapest", "best-selling") must use the site's actual sort/filter
- If a selected state becomes hidden (closed drawer, collapsed accordion), reopen it before capturing
- Prefer interactive form filling over deep-link URLs — deep links silently drop parameters
- Do not install extra packages —
playwright, httpx, etc. are already available
Reference Files
reference/playwright_patterns.md — browser launch skeleton, ARIA snapshot recipes, screenshot naming, targeting patterns
reference/workflow.md — detailed plan → explore → final → verify walkthrough
reference/cli_tool_mode.md — contract for parameterized CLI tool mode
Slash Commands
/webwright:run <task> — one-shot mode
/webwright:craft <task> — reusable CLI tool mode