Skip to main content
Placement decides where work happens: a whole flow, one agent’s tools, and its explicit code calls each answer a different question with a different parameter.

Quick Start

1

Share one sandbox across a flow or team

Thinking stays on this machine; every step’s shell, file and code tools run in one shared Docker sandbox.
2

Move one agent's tools

Give a single LocalAgent its own remote compute provider — thinking stays local, tools run on the provider.
3

Isolate explicit code calls

Agent(sandbox=…) configures the explicit agent.execute_code() API. It does not add tools the model can call.

How It Works

Each parameter moves a different scope, so the choices never overlap.

Which parameter do I want?

The scope you want to move picks the parameter. On a single Agent, run_on= hands the whole loop to a managed runtime — hosted (anthropic) or self-hosted (docker).
docker legitimately appears under both run_on= and tools_run_on= — same place, two scopes, carried by the parameter. run_on="docker" runs the whole loop in the container; tools_run_on="docker" keeps the loop local and moves only the tools. See Self-Hosted Agent (Docker).

Where run_on= and compute= can point

run_on= and compute= accept the same seven compute providers. A typo is rejected at load / call time with the full list of valid names. The explicit Agent(sandbox=…) API accepts additional local sandbox backends — subprocess, sandlock, docker — through SandboxConfig. See Sandbox Backends.
local / subprocess is not a security boundary. Its blocked-command list is bypassable by ordinary shell syntax (cat $(echo /etc/passwd) reads the file). For untrusted code, use docker, a cloud provider, or sandlock (via Agent(sandbox=…)).

Inspect placement

where_does_it_run() prints the answer in plain English. It is available on Agent, AgentFlow and AgentTeam, and reports two fields — thinks_on (the model calls) and tools_run_on (the tools).
A bare local agent reports that nothing is isolated:
thinks_on and tools_run_on are output fields from where_does_it_run() — they describe where work lands. They are not constructor parameters. Set placement with run_on=, compute=, or sandbox=.

Migration

YAML run_on: maps directly to the Python AgentFlow(run_on=…) kwarg — same name, same providers, validated at load time.
ExecutionConfig(code_sandbox_mode="sandbox") still exists with a "sandbox" default and survives to_dict() / from_dict(), but no execution path reads it today. It does not isolate anything on its own. To isolate code the model runs, use AgentFlow(run_on="docker") or Agent(sandbox=…). See Execution Systems.

Best Practices

subprocess separates a process but does not contain it. sandlock enforces Landlock + seccomp-bpf, the only kernel-level boundary that runs on this machine. Configure it through Agent(sandbox=SandboxConfig.native()).
run_on= on a flow or team provisions one sandbox for the whole run, so a file written by one step is visible to the next. Leave it unset for zero-overhead local execution.
Agent(sandbox=…) does not add a model-visible tool and does not protect the host execute_command path. For model-driven isolation, run the whole workflow in a real container with AgentFlow(run_on="docker").

Self-Hosted Agent (Docker)

run_on="docker" runs the whole agent in a container you own.

Shared Sandbox

Run every step’s tools in one shared sandbox.

Sandbox

Run tools and code in an isolated environment.

Sandbox Guarantees

What each boundary does and does not protect.