Repository navigation
bench: give agents pi's read tool, in a bubblewrap sandbox - #124
Merged
Merged
Conversation
…nscripts Mount only Node's binary and pi's package instead of their install prefixes, so a prefix such as ~/.local does not expose its other files. Pass the key variables of providers not named after them, such as GEMINI_API_KEY for google/. Create sandbox directories under /tmp, delete browsers before removing sandbox directories on shutdown, and redact the agent's keys from transcripts.
…dbox, pass proxy variables Drop pi's message_update events when redacting, since a key can be split across streamed deltas. Run pi --version in a sandbox in the smoke gate, so a standalone binary or a version manager's shim fails there with its error. Pass the proxy variables and NODE_EXTRA_CA_CERTS to the agent, and redact proxy URLs.
yummybomb
marked this pull request as ready for review
October 9, 2026 22:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pi cuts any MCP result over 20KB to its start and end, saves the full text to a file, and tells the model to read that file. The bench runs pi with
--no-builtin-tools, so agents could not open the file. A WebMCP tool list is often over the limit: four Amazon tools come to about 43KB. That left the tool names and refs in the cut-out middle. Some models recover by listing the tools through Playwright, and others fall back to the page.This PR adds pi's
readtool toallowlist.txt, for both arms. Withread, an agent could also open the bench's own files: intents and their rules,run.json, other trials' transcripts, and.env. So agents on Kernel browsers now run in a bubblewrap sandbox. It needs no sudo and no setup step.What the sandbox contains:
/usr, read-only./etcfiles DNS and TLS need, and no others:/etccan hold credentials, such as/etc/hypeman/envon Hypeship VMs./tmp. It holds the agent'smcp.json, pi config andTMPDIR, which is where pi saves full outputs./tmpare not visible.How it runs:
KERNEL_API_KEY, the variables of its model's provider (ANTHROPIC_*foranthropic/...; providers whose keys are named otherwise are mapped, such asGEMINI_*forgoogle/...), the proxy variables pi's HTTP client reads, andNODE_EXTRA_CA_CERTS. They are passed through the environment, never on the command line. The values of keys and proxy URLs are redacted from transcripts, and sandboxed transcripts leave out pi's streamedmessage_updateevents, since a key can be split across their deltas;message_endholds each whole message./usr, such as under~/.nvmor~/.local, only Node's binary and pi's package directory are mounted, read-only, and pi runs asnode <pi's cli.js>. The rest of the install prefix stays hidden./tmp, whatever the host'sTMPDIR.bwrapwith SIGTERM or SIGKILL also kills pi, so the runner's caps and shutdown work as before. pi itself is killed rather than sent SIGTERM, so its print-mode SIGTERM cleanup (closing MCP sessions) does not run; the runner deletes the browsers either way. Each agent's directory is removed afterward, and on shutdown after the browsers are deleted.bwrapcannot create a sandbox, which happens when it isn't installed or unprivileged user namespaces are disallowed. It also stops if a sandbox can see the bench directory or any entry in your home that isn't on a mount path, or ifnode <pi's cli.js> --versionfails in a sandbox or differs frompi --version, as whenpiis a standalone binary or a version manager's shim.allowlist.local.txt) still run pi unsandboxed and withoutread.Limits
bwrap(apt install bubblewrap) with unprivileged user namespaces. Some distributions restrict those with AppArmor./usrand the bound/etcfiles, and its own/proc/self/environ, which holds its own keys. Their values are redacted from the transcript if it does.Testing
node --test "bench/**/*.test.mjs": 108 pass.test/sandbox.test.mjscovers:GH_TOKENdoes not), including a provider whose key is not named after it (google/getsGEMINI_API_KEY);~/.local-style prefix mounts only its package and Node's binary;bwraptest, skipped where bwrap cannot run. In it, the agent can write itsTMPDIRand read itsmcp.json, but cannot see a file elsewhere in/tmpor/etc/hostname, and sees at most three processes. It runs a stand-in pi installed under a prefix and cannot see the prefix's other files. A second real-bwraptest gets the stand-in's version from a sandbox and fails on a shell shim in front of it.test/agent.test.mjs: the runner redacts the given strings from the transcript, including a key split across streamed deltas, which it leaves out with theirmessage_updateevents.test/run.test.mjs: the run stops before any browser if bwrap fails, if a sandbox can see the bench, or ifpiis a shim the sandbox cannot run with Node. A stubbwrapruns the existing tests end to end through the sandbox path.~/.local, ran--versionin the sandbox with only its package mounted, and the gate passed with~/.local/sharehidden./home,/etc/hypeman/env,/etc/chromium.d/apikeysand other/tmpfiles were invisible. SIGTERM and SIGKILL tobwrapboth ended the command.anthropic/claude-haiku-5-5 --thinking mediumon two Amazon intents (product details and first search result, PR Add Amazon shopping and guarded retail cart tools #56's tools, 2 trials with tools only plus 3 pairs each, 2 slots, stealth):readdeclared, and all 14 trials were correct.TMPDIR, with no read errors, and 7 of 8 invoked a tool. In earlier runs withoutread, the same intents had 40% and 60% of treatment trials invoking a tool./tmp.