Skip to main content
Each isolation surface in PraisonAI guarantees something different — this page states exactly what, so you never mistake a restriction flag for a real boundary.

Quick Start

1

Isolate an explicit execute_code() call

Agent(sandbox=…) gives you the caller-invoked execute_code() API. It adds no tools and does not isolate tools= callables.
2

Isolate everything the model runs

AgentFlow(run_on="docker") puts every step’s shell and file tools inside one shared container boundary, so model-driven tools route through the shared sandbox.

Guarantee Matrix

Each surface below isolates a different thing — read the row before you rely on it.
With the docker backend, cross-command filesystem state is provided: write_file(), run_command(), and execute() share a /sandbox bind mount, so a file written by one is visible to the next. That mount does not expose the host filesystem (ls /Users fails), and code inside the container cannot swap a symlink into the mount to redirect the host’s write_file / read_file — both open descriptor-relative with O_NOFOLLOW at every path component. list_files() never returns host paths — even on platforms where TMPDIR sits behind a symlink (macOS /var → /private/var).

Why sandbox= is not a capability grant

Agent(sandbox=…) is a restriction flag, not a way to hand the model an execution tool.
Agent(sandbox=…) does not add execute_python_code / execute_shell_command to agent.tools — that auto-injection was reverted in PR #3976. Giving the model a sandboxed execution tool must be a deliberate act by the caller, the way MCP() is. No peer framework grants execution capability from a config flag.
The default subprocess backend enforces none of its own SecurityPolicy on its execute() path (this warning is scoped to that backend and that path):
  • allow_network=False does not block outbound HTTPS.
  • blocked_paths=['~/.ssh', ...] does not stop reading an SSH private key.
  • blocked_imports=['subprocess', ...] does not stop import subprocess.
  • A separate process is not a security boundary.
For real containment, use a real container backend (docker / e2b), sandlock for a kernel-enforced local boundary (Landlock + seccomp-bpf), or AgentFlow(run_on=…).
DockerSandbox is different — as of PR #4303 it does enforce the command-level parts of SecurityPolicy on the host before Docker is invoked.
  • Enforced on docker: blocked_commands, allowed_commands, blocked_paths, allowed_paths on every run_command(); max_output_size on both run_command() and execute().
  • Not enforced on docker: allow_subprocess — the container itself is the boundary that clause approximates on the host, so blocking sh inside the container would refuse every command rather than harden it.
  • Not a substitute for the container: the container still bounds where code runs; policy enforcement is additional, not a replacement for the isolation boundary.
See Docker SecurityPolicy enforcement.
praisonai-sandbox must be installed to run any sandbox backend — pip install praisonaiagents alone is not enough. Install a backend, e.g. pip install "praisonai-sandbox[docker]".

Reliability: no leaked containers

Two guarantees close the container-leak story end to end — a timed-out execution and an exited run_on= script both leave zero running containers. Verified before/after: See Reclaim Stray Sandboxes for the full mechanism and Placement for how the leaks fit the placement story.

Common Patterns


Best Practices

Agent(sandbox=…) configures the explicit execute_code() API. It never hands the model a tool — add one yourself only when you intend the model to run code.
The default subprocess backend is for trusted development only. For untrusted or model-driven execution, use AgentFlow(run_on="docker"), LocalAgent(compute="docker"), or sandlock for a kernel-enforced local boundary.
With autonomy=True, the agent still carries the host execute_command tool. sandbox= does not protect that path — isolate the whole workflow with AgentFlow(run_on=…) instead.
pip install praisonaiagents cannot execute any sandbox. Install praisonai-sandbox with the backend you need before relying on isolation.

Sandbox

Configure the explicit execute_code() API and choose a backend

Shared Sandbox

Share one container across every agent with run_on=