Sandbox
Coming soonThe sandbox is where your agent interacts with a computer: shell commands, file edits, and running agent-authored Python code. You choose one when you build the harness.
Built-in sandboxes
from mistralai.agents import agents
harness = agents.Harness() # NoSandbox (default): no code execution
harness = agents.Harness(sandbox=agents.BashkitSandbox()) # a Bashkit sandboxOther sandboxes:
MistralSandbox(): a Mistral-managed container. Use this when you need Python in the sandbox.LocalDockerSandbox(): a local Docker container for dev and CI.- Only
BashkitSandboxis documented in depth here so far.
MistralSandbox() needs the koyeb extra in your project's dependencies:
uv add 'mistralai-agents[koyeb]'Without it, agents info and agents serve stop and tell you to install it.
NoSandbox is the default: the agent can call your tools and connectors, but it cannot
run code or commands on a computer nor manipulate a filesystem.
Every executable sandbox also takes hooks=[...], for code that runs when the sandbox is
provisioned and when the session closes. See
Sandbox lifecycle hooks.
Background processes
Agents with DangerousLocalSandbox, or with MistralSandbox and LocalDockerSandbox using their
built-in images, can keep commands running while they do other work. If you set a custom image,
also set supports_background_processes=True after ensuring that image meets the requirements
below. An executable CustomSandbox can opt in by setting
supports_background_processes = True only when its command environment provides unrestricted
operating-system shell commands, python3 -I, and Python's standard socket and subprocess
modules. The model uses
tools.process.start, tools.process.output, tools.process.write, tools.process.list, and
tools.process.stop through run_typescript. Process identifiers, output cursors, and terminal
state remain available across turns in the same Session. Deployed Sessions also preserve this
state across Workflow continuation.
Background processes are unavailable with NoSandbox and BashkitSandbox. You can remove them
from another executable sandbox with Agent(disabled_tools=["process.*"]).
For an in-process Bash and filesystem sandbox without Python, install the optional extra and use
BashkitSandbox():
uv add 'mistralai-agents[bashkit]'agents.Harness(sandbox=agents.BashkitSandbox())BashkitSandbox() is executable for shell and built-in file tools, but it does not provide Python.
It cannot run background processes or be combined with SandboxTools or ProgrammaticToolCalling;
use MistralSandbox() for those.
TruncateToolOutput remains supported and falls back to in-place truncation when it cannot teleport
overflow into a Python-written sandbox file.
:::warning Weaker isolation
BashkitSandbox executes model-generated shell commands in-process. Its interpreter, virtual
filesystem, resource limits, and network policy provide weaker isolation than the Mistral-managed
container used by MistralSandbox. For stronger isolation, use MistralSandbox.
:::
Bashkit or Mistral-managed sandbox
Work in progress
Bashkit network policy
Work in progress
When you need an executable sandbox
You need one whenever
- the agent should actually interact with a computer - shell, file edits, or Python.
- Sandbox tools (coming soon): the handler's source runs in the sandbox.
- Truncate tool output (docs coming soon): overflow is teleported to a sandbox file.
Local Docker sandbox (dev / CI only)
Work in progress
Local host sandbox (dev / CI only)
DangerousLocalSandbox() runs the agent's commands directly on the host machine — no container,
no isolation. It unlocks local testing: run and test an agent end-to-end on your laptop with no
Mistral sandbox token, no Docker daemon, and no container infrastructure — the agent's shell and
file tools run for real in a per-session workspace under ~/.cache/mistral-vibe-harness-local-host/.
agents.Harness(sandbox=agents.DangerousLocalSandbox(shell="bash"))Options: shell ("bash" or "sh", defaults to bash) and default_exec_timeout_seconds
(defaults to 600). Like every executable sandbox, it also takes hooks=[...] — see
Sandbox lifecycle hooks.
:::danger No isolation
DangerousLocalSandbox executes model-generated shell commands on your machine, as the worker
user, with the worker's permissions and environment. A malicious or mistaken model output can
read, write, or delete your files — including any credentials visible to the worker.
- It is opt-in: set
ALLOW_DANGEROUS_LOCAL_HOST=1or the worker refuses to build the sandbox. - Constructing it warns loudly.
- Never enable it in production or anywhere shared.
For container isolation without a Mistral sandbox token, prefer LocalDockerSandbox(). For real
isolated execution, use MistralSandbox().
:::
A complete runnable example lives in
examples/dangerous_local_agent
in the repository.
Sandbox Proxy
Sandbox Proxy gives a managed sandbox short-lived access to external services without placing the
underlying credentials in the sandbox configuration. Add the integrations that the agent needs to
MistralSandbox:
from mistralai.agents import agents
sandbox = agents.MistralSandbox(
sandbox_proxy=agents.SandboxProxy(
integrations=(
agents.GitHubProxyConfig(
repo_whitelist=("your-org/your-private-repo",),
),
agents.SecretInjectionProxyConfig(),
),
),
)
agent = agents.Agent(
model="mistral-medium-3-5",
name="repository-agent",
harness=agents.Harness(sandbox=sandbox),
)The sandbox can then use ordinary HTTPS commands:
git clone https://github.com/your-org/your-private-repo
gh repo view your-org/your-private-repoThe SDK calls the Sandbox Proxy bootstrap API when it creates the sandbox. The API returns short-lived setup information, which the SDK installs in the sandbox. The GitHub credential itself does not enter the sandbox. Before a later sandbox command, the SDK renews the setup when it is close to expiring.
GitHubProxyConfig accepts these fields:
repo_whitelist: repositories written asowner/repository. An empty tuple grants no repository access.all_accessible_repos: grants access to every repository available to the authenticated identity and takes precedence overrepo_whitelist.ttl_seconds: requested lifetime of the short-lived credential. The default is one hour.host: GitHub host routed through the proxy. Onlygithub.comis currently supported.
SecretInjectionProxyConfig routes sandbox HTTP requests through the workspace's secret-injection
policy. The configuration has no policy or lifetime options. The bootstrap service selects the
current workspace policy and issues a short-lived credential for it. The SDK stores the returned
proxy environment in a protected file, sources it before each sandbox command, and renews the
credential before it expires.
For an in-process agent, the bootstrap request uses the identity associated with MISTRAL_API_KEY.
For an agents serve worker or a hardened managed deployment, it uses the authenticated session
caller. The selected identity must have a GitHub connector with access to every requested repository.
MistralSandbox currently uses Koyeb, so the process that creates the sandbox needs a Koyeb sandbox
API token. Set KOYEB_API_KEY or NUAGE_KOYEB_SANDBOX_API_TOKEN for agents run and agents serve.
agents serve and agents run-worker check for the token at startup and exit if it is missing.
For a managed deployment, create that token in the workspace Secrets Manager, then bind it to the worker with the environment variable expected by the SDK:
agents deploy . \
--secret-binding AGENTS_SDK_KOYEB_SANDBOX_API_TOKEN=secret:workspace:<secret-name>The deployment is hardened automatically: a sandbox-proxied agent acts on behalf of the user who
started the session, and Sandbox Proxy authenticates the bootstrap request with that user's identity
instead of the identity that deployed the agent. Pass --no-hardened only if you really mean it.
The secret binding supplies only the Koyeb runtime credential; it does not place a GitHub credential
in the worker or sandbox.
Bring your own
Work in progress