Sandbox Providers
The provider decides where the agent’s commands run. Everything else — the policy, the workspace bridge, the record of each command, your credentials — stays in your process and works the same with every provider. By the end of this page you will have picked one, set it up, and know what it enforces.sandbox_manifest, the same for every provider; the
Sandboxes and execution page has a first run
and the manifest in full.
Every output on this page is what the code printed when it was run: Docker on
Linux, and free E2B and Daytona accounts. Modal and Vercel were not run for
this page; what is said about them comes from their adapters’ code.
Choose a provider
- Start with
docker. It is free, local, and the strictest by default. - Hosted (
e2b,daytona,modal,vercel) when the agent runs where there is no Docker, or you want the sandbox off your machine. httpfor anything without an adapter: your own sandbox service.localonly where the machine itself is the boundary: a CI job, a throwaway VM, an evaluation container.
Network: what each provider enforces
A manifest’snetwork_policy is {"default": "deny"} unless you say
otherwise. What each provider can keep:
denied_hosts is passed on to an http service, which must keep it or refuse
the session. No other built-in provider can block named hosts, so there it is
refused when the agent is built. To reach only some hosts, use
"default": "deny" with allowed_hosts on a provider that keeps them.
Docker
/tmp kept in memory. The Docker socket, system
directories and credential folders (~/.ssh, ~/.aws, …) are never mounted.
The first run pulls the image; later runs start in seconds.
The default image has Python and its standard library and nothing else, and
with no network a command cannot pip install. Build an image with what your
tasks need and name it in the options or the manifest.
A run on Docker, end to end, is on Sandboxes and execution.
A container left behind by a process that was killed is removed when its run
is resumed, run again with the same run ID, or abandoned (
abandon_run): each
container carries its run’s ID in the label omnicoreagent.run. To remove one
run’s leftovers yourself, await DockerSandboxRuntime().cleanup_orphans(run_id=...)
(from omnicoreagent.sandbox.docker). Without run_id it removes every
container labelled omnicoreagent.sandbox, including those of agents still
running on the same Docker host.
E2B
Daytona
python:3.12-slim) gave Debian 13 and Python 3.12.14,
commands ran as root, and a sandbox took 48 to 84 seconds to start. Daytona
returns a command’s output as one stream: stdout holds everything and
stderr is empty.
allowed_hosts is refused when the agent is built: Daytona’s allow list takes
IP ranges, not host names. Use "deny" or "allow" on Daytona. (In 0.4.1 it
was accepted and the session then failed to start.)
Modal
outbound_domain_allowlist. Each allowed host is its own
sandbox.network.configure question, so a policy can allow some hosts and ask
about the rest. Sandboxes run in a Modal app named omnicoreagent-sandbox
(created if missing). There is no from-inside network check for Modal.
Vercel
deny-all or allow-all; a host allowlist is refused. There is
no from-inside network check for Vercel.
HTTP: your own sandbox service
For anything without an adapter — Cloudflare’s Sandbox SDK behind a Worker, a sandbox service inside your own network — run a small service and point the agent at it:Authorization: Bearer <token>
when a token is set:
network carries default, allowed_hosts and denied_hosts. The service is
responsible for the isolation it promises: one that cannot keep the network
policy must refuse the session. Only the plain environment is sent.
Local: this machine, not a sandbox
local runs each command as a process on the machine the agent runs on, with
nothing in between: a command can reach the network, read and change any file
your user can, and what it changes stays changed. Use it only where the machine
is already the boundary.
The built-in profiles never allow host commands on their own
(permissive-dev and strict-production deny them; interactive-dev asks a
person for each one). To let an agent run them without asking, start from a
profile, drop the asks that stand in the way, and allow host commands with a
rule of your own. The manifest’s working_dir must already exist, so create
it first (here app/, next to the script: mkdir app, or the os.makedirs
line below); otherwise the first command fails, saying the working directory
does not exist:
pwd; echo "LLM_API_KEY=${LLM_API_KEY:-unset}" in that agent came
back as:
ask_high_risk stops the profile asking about every other high-risk
action on the host too; keep it if the agent has other tools that should still
ask. A deny rule always wins over an allow, so this cannot be done from
permissive-dev.
What it refuses. A manifest must ask for what local really gives: network
allow and filesystem allow, with no host or path lists. A manifest
that leaves the network at its default (none), or no manifest at all, is refused when the agent is built,
as are an image, a workspace mount, CPU, memory or GPU limits, a sandbox lifetime, and secret references.
What it enforces. Each command’s time limit (the command and everything it
started are killed); the output cap; the host environment is not passed, only
PATH, HOME, USER, LOGNAME, LANG, LC_ALL, TERM, TMPDIR and TZ
plus the manifest’s plain environment. Files are another matter: a command can
read whatever your user can, including credential files. Workspace files are
not copied in or out — point working_dir at the workspace to have commands
work in it directly. The model is told the truth too: its execute tool says
it runs on this machine and is not isolated, and every command is recorded with
execution_surface: host.
none and local_test
"provider": "none" gives the agent a policy but no sandbox: there is no
execute tool, and a policy rule that requires a sandbox (sandbox_required)
is never satisfied.
local_test runs Python handlers you register instead of commands, for tests
of your own agent. Pass the runtime itself, and say that a test runtime may
stand in for a sandbox:
execute with pytest -q, the tool
returned:
allow_test_sandbox_runtime, the agent gets no execute tool.
Bring your own provider
register_sandbox_provider("name", factory) adds a provider; it then works
anywhere a provider name does. The factory is called with the options dict
and a telemetry recorder, and returns a SandboxRuntime:
create, execute, read_file, write_file,
set_network_policy, snapshot and terminate, and sets
supports_execution = True and supports_required_sandbox = True when it
isolates commands.
When things go wrong
SandboxUnsupportedError: … still reached the internet
SandboxUnsupportedError: … still reached the internet
The hosted sandbox was asked for no network and has one (see the warning
above). Allow the network in the manifest, use a plan or provider that
enforces isolation, or set
"verify_network_isolation": False.ValueError: governance_config.sandbox_config.provider must be a registered sandbox provider
ValueError: governance_config.sandbox_config.provider must be a registered sandbox provider
A misspelled provider, or one of yours not registered before the agent is
built:
ValueError: Unknown docker sandbox option(s): network
ValueError: Unknown docker sandbox option(s): network
Options are checked per provider; the network belongs in the manifest:Use
"sandbox_manifest": {"network_policy": {"default": "allow"}}.ValueError: The docker sandbox does not enforce a network host allowlist
ValueError: The docker sandbox does not enforce a network host allowlist
allowed_hosts on docker, e2b, daytona, vercel or local:denied_hosts on any built-in provider but http
(“does not enforce blocking named hosts”), and environment.secret_refs on every
built-in provider (“does not enforce delivering secrets”).The local sandbox cannot restrict the network
The local sandbox cannot restrict the network
local with no sandbox_manifest, or one that leaves the network at its default (deny). Building the
agent fails with:ImportError: … requires optional dependency
ImportError: … requires optional dependency
The provider’s extra is not installed, e.g.
pip install "omnicoreagent[e2b]".SandboxUnsupportedError: The Docker sandbox needs the Docker SDK
SandboxUnsupportedError: The Docker sandbox needs the Docker SDK
Without the
docker extra, nothing fails when the agent is built: the
run’s first execute call fails with The Docker sandbox needs the Docker SDK: pip install omnicoreagent[docker]. Install it:
pip install "omnicoreagent[docker]".Next
Sandboxes and execution
The execute tool, files in and out, the network, the record of a command.
Policies
Allow, ask or deny commands, images and network access.
Approvals
The person who says yes to the network.
Budgets
Cap sandbox seconds, and everything else a run spends.
Security model
What each boundary does and does not protect.
Guardrails
Prompt injection in what the agent reads.