Sandboxes¶
A sandbox runs shell commands inside a workspace: repo.setup, the test command,
benchmarks and the environment's run action.
LocalSandbox (default)¶
Runs commands with subprocess on the host. The environment is scrubbed to an
allowlist (PATH, HOME, LANG, PYTHONPATH, VIRTUAL_ENV, toolchain homes,
...) so API keys in your shell never reach agent-controlled commands. python is
made to resolve to the interpreter running repogym unless a setup step creates
its own environment.
from repogym import LocalSandbox
sandbox = LocalSandbox(extra_env={"MY_FLAG": "1"})
sandbox = LocalSandbox(inherit_env=True) # pass everything through (not recommended)
Warning
LocalSandbox is not a security boundary. A task's setup or test command runs
with your privileges. Use Docker for tasks you did not author.
DockerSandbox¶
Each command runs in a fresh container with the workspace bind-mounted at
/workspace, the network disabled and resource limits applied.
repogym validate tasks --sandbox docker:python:3.12-slim
repogym run tasks -k 'bugfix-node-*' --agent golden --sandbox docker:node:22-slim
from repogym import DockerSandbox
sandbox = DockerSandbox(image="python:3.12-slim", network="none", memory="2g", cpus="2")
env = RepoEnv(task, sandbox=sandbox)
Because the network is off, dependencies must be installed in the image or by a
setup step run with network="bridge". A common pattern is a per-task image
built from the repository's own Dockerfile and referenced in metadata.
Writing a sandbox¶
class MySandbox:
name = "remote"
def available(self) -> bool: ...
def run(self, command, cwd, timeout=300, env=None, max_output=200_000) -> CommandResult: ...
Anything with that shape (Modal, E2B, Firecracker, SSH) can be passed wherever a sandbox is accepted; the workspace directory must be reachable from it.