diff --git a/containers/Dockerfile b/containers/Dockerfile index 9943266a..7bbda9fc 100644 --- a/containers/Dockerfile +++ b/containers/Dockerfile @@ -117,6 +117,17 @@ ENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium ENV AGENT_BROWSER_USER_AGENT="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" ENV AGENT_BROWSER_ARGS="--disable-blink-features=AutomationControlled,--no-first-run,--no-default-browser-check,--lang=en-US" ENV AGENT_BROWSER_SCREENSHOT_DIR=/workspace/.agent-browser-screenshots +# Reclaim abandoned browsers. Each `--session` name is a separate daemon owning its +# own Chromium process group — measured at ~340 MB and ~12 processes with one page +# open — and nothing in the engine owns a browser's lifecycle: agents drive +# `agent-browser` through exec_command, so an agent that finishes, is stopped, or +# crashes leaves its browser resident for the life of the sandbox. Upstream +# disables the idle timeout by default, which turns a wide fan-out into gigabytes +# of stranded Chromium. The daemon relaunches transparently on the next command, so +# the only cost of reclamation is losing browser state (see the skill's note on +# persisting it). Three minutes is longer than the gap between two browser commands +# in an active agent turn; override the env var to tune. +ENV AGENT_BROWSER_IDLE_TIMEOUT_MS=180000 RUN /home/pentester/.npm-global/bin/agent-browser doctor --offline --quick RUN set -eux; \ diff --git a/strix/agents/prompts/system_prompt.jinja b/strix/agents/prompts/system_prompt.jinja index 3efc07af..6763f9d8 100644 --- a/strix/agents/prompts/system_prompt.jinja +++ b/strix/agents/prompts/system_prompt.jinja @@ -263,7 +263,12 @@ Remember: A single well-validated high-impact vulnerability is worth more than d AGENT ISOLATION & SANDBOXING: - All agents run in the same shared Docker container for efficiency -- Each agent has its own: browser sessions, terminal sessions +- Each agent has its own terminal sessions +- Browsers are NOT per-agent: `agent-browser` shares one browser across every agent + using the default session, so another agent may be driving it. Pass + `--session ` only when you genuinely need an isolated browser (separate + cookies/logins, e.g. testing two users at once) — each one costs a full Chromium + (~340 MB) on the shared box, and `close` it as soon as you're done with it - All agents share the same /workspace directory and proxy history - Agents can see each other's files and proxy traffic for better collaboration diff --git a/strix/skills/tooling/agent_browser.md b/strix/skills/tooling/agent_browser.md index db074e86..bcacf37a 100644 --- a/strix/skills/tooling/agent_browser.md +++ b/strix/skills/tooling/agent_browser.md @@ -58,6 +58,14 @@ agent-browser screenshot The browser stays running across commands so these feel like a single session. Use `agent-browser close` (or `close --all`) when you're done. +The default session is **shared with every other agent in the sandbox**, and each +extra `--session ` is a whole extra Chromium (~340 MB) on a box you share — +so open one only when you need isolated cookies, and close it when you're done. +A browser left idle for 3 minutes is reclaimed automatically; the next command +relaunches it, but the page, tabs, refs and cookies are gone. If you're +authenticated and about to go do something else for a while, save the state +first (see [Persist session across runs](#persist-session-across-runs)). + ## Reading a page ```bash @@ -307,6 +315,15 @@ agent-browser --session b fill @e1 "bob@test.com" `AGENT_BROWSER_SESSION=myapp` sets the default session for the current shell. +Every session is a separate Chromium, so this is the most expensive thing you can +do to the shared sandbox — use it for genuine isolation (two users, two cookie +jars), not as a habit, and close each one when the flow is finished: + +```bash +agent-browser --session a close +agent-browser --session b close +``` + ### Mock network requests ```bash @@ -368,8 +385,11 @@ agent-browser dialog dismiss # cancel ## Readiness & recovery The first `agent-browser open` in a session launches the headless-Chrome -daemon; later commands reuse it. Distinguish the two failure modes and react -differently — do **not** blindly re-run the same failing command in a loop: +daemon; later commands reuse it. A daemon left idle for 3 minutes shuts itself +down to free memory for the other agents, so an `open` after a long gap is a +fresh browser rather than a resumed one — expect to re-navigate, and re-`state +load` if you were logged in. Distinguish the failure modes and react differently +— do **not** blindly re-run the same failing command in a loop: - **Daemon / connection failure** (`Failed to connect`, `connection refused`, socket missing, `browser not running`): the daemon isn't up or has died. Run