Browser harness for AI agents.
ABR is not a replacement for Playwright. Mature ABR is a thin, agent-facing harness that gives agents one stable way to create browser profiles, drive pages, collect evidence, bridge into the operator's real Chrome when needed, and hand authenticated state to Raw HTTP.
Playwright/CDP is the primary execution engine for agent-owned browser work. The Personal Chrome bridge is reserved for cases Playwright should not own: existing real Chrome sessions, user-requested current-tab work, and operator-owned state. Agent Browser remains the main lane for isolated target profiles; user-supervised challenges happen inside that isolated profile through handoff tools. If that isolated profile is explicitly rejected by the challenge provider, agents can switch to a named Personal Chrome Worktab: a background tab in the operator's real Chrome that avoids the active tab but shares the real browser profile.
| Layer | Responsibility |
|---|---|
| Playwright/CDP | Primary browser automation engine: launch/profile/page/action/wait/screenshot/trace. |
| ABR harness | Stable agent API, profile ownership, structured failures, evidence paths, redaction, cleanup, acceptance gates. |
| Personal Chrome bridge | Operator-owned Chrome sessions, explicit current-tab work, real logged-in tabs, and named background Worktabs. |
| Raw HTTP | Exact API replay, authorization checks, batch variants after session capture. |
Agents should not reason about managed, slim, personal-spawn, CDP ports,
or browser selectors. Those are implementation details or legacy labels.
Agent
|
v
ABR harness API (:17337)
|-- Agent Browser lane
| |-- Playwright/CDP adapter for agent-owned profiles
| |-- profile/session ownership, cleanup, network evidence, redaction
|
|-- Personal Chrome lane
| |-- Chrome extension bridge into the operator's real Chrome
| |-- explicit current-tab work, real logged-in tabs, and named Worktabs
|
`-- Raw HTTP lane
|-- replay captured requests, authorization checks, batch variants
`-- write evidence artifacts instead of dumping secrets to chat
The legacy worker on :17335 is not the product entry point. It remains only
for old compatibility while the harness is collapsed around the :17337 API.
New agent workflows must not depend on :17335, managed, slim, or raw CDP
port routing.
# npm (global)
npm install -g agent-browser-runtime
# from source
git clone https://github.com/ttcd77/agent-browser-runtime.git
cd agent-browser-runtime
npm install && npm run buildLinux / macOS:
npm run personal:chromeWindows (PowerShell):
npm run personal:chromeThe harness listens on http://127.0.0.1:17337 by default. Agents should use
the agent-browser CLI or the :17337 HTTP API. Do not start the legacy
:17335 worker for new workflows.
Global install?
agent-browser doctorworks directly. Source install? Usenpx agent-browser doctorornode scripts/agent-browser-cli.mjs doctor.
# Health check
agent-browser doctor
# Open a page, capture evidence, print artifact paths
agent-browser open https://example.com --profile demo
agent-browser capture start --profile demo --label first
agent-browser inspect network --profile demo
agent-browser pack https://example.com --profile demoNow try your own URL: agent-browser pack https://your-site.com --profile mine.
For a local production check, run:
npm run acceptance:strictIt verifies the agent-facing tool contract, Personal Chrome safe background-tab operation, Agent Browser profile lifecycle, origin-state warm-up, and Raw HTTP smoke coverage.
| Platform | Script | Mechanism |
|---|---|---|
| Windows | scripts/install-agent-server-task.ps1 |
Scheduled Task (user-level) |
| Linux | scripts/install-systemd-units.sh |
systemd user units |
| macOS | scripts/install-launchd-plists.sh |
launchd LaunchAgents |
Windows:
pwsh -File scripts/install-agent-server-task.ps1
pwsh -File scripts/install-personal-bridge-task.ps1Linux / macOS:
bash scripts/install-systemd-units.sh # Linux
bash scripts/install-launchd-plists.sh # macOS
# follow printed instructions to enable unitsWhen you need to inspect your already-open Chrome tab:
Linux / macOS:
npm run personal:chromeWindows (PowerShell):
npm run personal:chromeLoad the unpacked extension from extension/, then:
agent-browser backend status --intent personal-current-tabRead docs/personal-chrome-quickstart.md before using this mode.
The stable product surface is the agent-browser CLI plus the :17337 harness
API. Tool names may evolve internally; agents should route by lane and task, not
by backend implementation detail.
| Lane | Example commands/tools |
|---|---|
| Agent Browser | agent-browser open, agent-browser capture start, agent-browser inspect network, profile_create, profile_list, browser_challenge_status, browser_human_handoff |
| Personal Chrome | personal_chrome_list_browsers, personal_chrome_read_page, personal_chrome_select_browser, personal_chrome_worktab_open |
| Raw HTTP | agent-browser raw ..., request replay and authorization checks after session capture |
| Health & routing | agent-browser doctor, /health, /tools for the small primary catalog, /tools?all=1&schema=1 for expert/debug catalog, structured tool_not_found for removed legacy tools |
Full tool reference: docs/agent-devtools-api.md.
F12-to-tool lookup: docs/devtools-panel-map.md.
Default professional workflow:
browser_open → browser_capture → browser_inspect → browser_security_pack
Use agent_inspect as the agent router — it picks the right evidence tools
based on a focus parameter (overview, network, storage, console,
dom, sources, performance, evidence, debug) without requiring the
agent to scan all tools.
Any tool is callable as a plain HTTP POST:
curl -X POST http://127.0.0.1:17337/tool/profile_create \
-H "content-type: application/json" \
-d '{"name":"researcher"}'
curl -X POST http://127.0.0.1:17337/tool/personal_chrome_list_browsers \
-H "content-type: application/json" \
-d '{}'
curl -X POST http://127.0.0.1:17337/tool/browser_workflow_guide \
-H "content-type: application/json" \
-d '{"task":"first-pass"}'Health check:
curl http://127.0.0.1:17337/healthThe old :17335 worker is a compatibility backend, not the product entry point.
- Tools return objective evidence — they do not classify vulnerabilities.
- Use
AGENT_BROWSER_RUNTIME_TOKENto require a bearer token on all tool calls. CDP_BROWSER_HEADLESS=1for headless/CI mode (headful is default for AppSec work).- Set
CDP_SECURITY_DATA_DIRto control where evidence is stored. - Artifact paths are validated against a whitelist; no directory traversal.
- HTTP body capture is capped to prevent runaway storage.
- Personal Chrome mode requires explicit operator authorization — never attaches silently.
For DNS rebinding protection and full boundary details: docs/safety-boundaries.md.
| Variable | Default | Purpose |
|---|---|---|
PERSONAL_CHROME_HTTP_PORT |
17337 |
Harness / Personal Chrome bridge port |
CDP_AGENT_PROFILE |
default |
Default compatibility profile when omitted |
CDP_BROWSER_HEADLESS |
unset | Headless mode (CI/test) |
CDP_SECURITY_DATA_DIR |
~/.agent-browser-runtime |
Evidence storage root |
CDP_BROWSER_PORT_MODE |
ephemeral |
ephemeral or fixed CDP port |
AGENT_BROWSER_RUNTIME_TOKEN |
unset | Bearer token for HTTP auth |
Full list: see the Environment Variables section of docs/agent-operator-runbook.md.
~/.agent-browser-runtime/
profiles/
<profile>/
events/events.jsonl
traffic/traffic.jsonl
screenshots/*.png
evidence/
Do not commit captured evidence from real targets until reviewed and sanitized.
const baseUrl = "http://127.0.0.1:17337";
async function callTool(name: string, params: unknown) {
const res = await fetch(`${baseUrl}/tool/${name}`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(params),
});
return res.json();
}
await callTool("browser_open", { profile: "researcher", url: "https://example.com" });
await callTool("browser_capture", { profile: "researcher", action: "start" });
const snapshot = await callTool("browser_snapshot", { profile: "researcher" });No CDP target ids, tab ids, or browser ports needed. Route by profile name.
See docs/architecture.md for a full breakdown of the harness lanes, security
boundaries, and cross-platform support.
- Issues / questions: GitHub Issues
- Pull requests: see CONTRIBUTING.md
- Security disclosures: see SECURITY.md
The underlying Playwright/CDP adapter tried to launch Chrome but the browser endpoint never came up. Common causes:
- Playwright browser not installed: run
npx playwright install chromiumonce. - A local browser/debug port is in use: another harness or compatibility worker may already be running. Stop it (
agent-browser doctorto confirm) or set explicit ports for that session. - No display on Linux server: headful mode needs a display. Set
CDP_BROWSER_HEADLESS=1or use a virtual framebuffer (xvfb-run). - Firewall blocking localhost: most Linux containers ship without one, but check with
ss -tlnp.
A previous harness bridge is still running. Either:
pkill -f personal-chrome-bridge(Linux/macOS)- Find the PID with
netstat -ano | findstr :17337(Windows) andtaskkill /F /PID <pid>
The Chrome extension must be installed and the personal bridge running. See docs/personal-chrome-quickstart.md.
ws is at 8.21.0+ (patched). If you see advisories for vite, they are transitive dev-only and do not enter the production bundle.
Per-profile under ~/.agent-browser-runtime/profiles/<profile>/:
traffic/— request/response journalsevidence/— evidence bundlesscreenshots/,events/— page captures
Use agent-browser doctor to print the exact path on your machine.
- Bugs: GitHub Issues using the
bug_reporttemplate. - Capability gaps (tool missing for a workflow): same Issues page,
capability_gaptemplate. - Security: see SECURITY.md.
MIT — see LICENSE.