praisonai-sandbox Package
Standalone sandbox backends for PraisonAI — install only what you need
Use praisonai-sandbox when you only need sandboxed execution — no gateway, no CLI wrapper — or when you want the sandbox backends on a slim install. It’s a standalone Tier‑2 package extracted from the praisonai wrapper, so agents keep the same sandbox=True behaviour with a much smaller dependency tree.
from praisonaiagents import Agent
agent = Agent(
name="Coder",
instructions="Run code safely",
sandbox=True, # subprocess backend, no extras needed
)
agent.start("Print the current directory tree")The user asks the agent to run code; the sandbox package executes it in an isolated backend and returns the result.
Quick Start
- Run an agent with the default backend
The
subprocessbackend ships in the base install — nothing else to configure:python from praisonaiagents import Agent agent = Agent( name="Coder", instructions="Run code safely", sandbox=True, ) agent.start("Print the current directory tree") - Pick a specific backend
Choose a backend with
SandboxConfig:python from praisonaiagents import Agent, SandboxConfig agent = Agent( name="DataAnalyst", instructions="Analyze data with Python.", sandbox=SandboxConfig.docker("python:3.12-slim"), ) agent.start("Read CSV data and create a summary") - Install the slim package and optional backends
bash pip install praisonai-sandbox # slim install, subprocess backend pip install "praisonai-sandbox[docker]" pip install "praisonai-sandbox[e2b]" pip install "praisonai-sandbox[modal]" pip install "praisonai-sandbox[ssh]" pip install "praisonai-sandbox[sandlock]" pip install "praisonai-sandbox[daytona]" # pulls daytona-sdk; set DAYTONA_API_KEY pip install "praisonai-sandbox[novita]" # pulls novita-sandbox; set NOVITA_API_KEY pip install "praisonai-sandbox[all]" # every backend at once - List available backends
bash praisonai-sandbox backendsdaytona: unavailable docker: unavailable e2b: unavailable modal: unavailable novita: unavailable sandlock: unavailable ssh: unavailable subprocess: availableEach backend reports
availableorunavailablebased on whether its optional dependency is installed.
Do I Need to Install It Directly?
Most users never install praisonai-sandbox on its own — the full wrapper already bundles it.
Backends Included
Every backend is selectable by name through praisonaiagents.sandbox.SandboxManager — the same registry the wrapper uses.
| Name | Class | Typical use |
|---|---|---|
subprocess | SubprocessSandbox | Fast local development (base install) |
sandlock | SandlockSandbox | Hardened local sandbox ([sandlock]) |
docker | DockerSandbox | Container isolation for production ([docker]) |
ssh | SSHSandbox | Remote server execution ([ssh]) |
modal | ModalSandbox | Modal cloud sandboxes ([modal]) — stateless: no file persistence via write_file/read_file; use execute() with inline source |
e2b | E2BSandbox | E2B cloud code interpreter ([e2b]) |
daytona | DaytonaSandbox | Daytona cloud sandboxes ([daytona] + DAYTONA_API_KEY) |
novita | NovitaSandbox | Novita cloud sandboxes ([novita] + NOVITA_API_KEY) |
Install Matrix
Base install pulls the core dependencies; each backend is an optional extra.
| Extra | Command | Pulls |
|---|---|---|
| _(base)_ | pip install praisonai-sandbox | praisonaiagents, rich, typer, click |
docker | pip install "praisonai-sandbox[docker]" | docker>=7.0.0 |
e2b | pip install "praisonai-sandbox[e2b]" | e2b-code-interpreter>=1.0.0 |
sandlock | pip install "praisonai-sandbox[sandlock]" | sandlock>=0.1.0 |
ssh | pip install "praisonai-sandbox[ssh]" | asyncssh>=2.14.0 |
modal | pip install "praisonai-sandbox[modal]" | modal>=0.64.0 |
daytona | pip install "praisonai-sandbox[daytona]" | daytona-sdk (set DAYTONA_API_KEY) |
novita | pip install "praisonai-sandbox[novita]" | novita-sandbox>=2.0.0 (set NOVITA_API_KEY) |
all | pip install "praisonai-sandbox[all]" | all of the above |
Compute providers live here too
As of PR #4092, the seven vendor compute providers that tools_run_on= / run_in= / run_on= reach also live in this package — next to the sandbox backends they share a vendor with.
You never import them by hand. Name the vendor on the agent and the provider resolves from praisonai_sandbox.compute:
from praisonaiagents import Agent
agent = Agent(
name="Runner",
instructions="Run code in an E2B cloud sandbox.",
tools_run_on="e2b",
)
agent.start("Print the Python version")pip install "praisonai-sandbox[e2b]" # enough to reach tools_run_on="e2b"That single install is all you need — no full praisonai wrapper.
The two protocol stacks stay separate — a sandbox backend and a compute provider for the same vendor (docker, e2b, modal, daytona) are still two different classes. PR #4092 only co-locates them; it does not merge them.
Which install do I actually need?
Reaching a vendor used to pull vastly different dependency trees. run_in="e2b" resolved 58 packages via praisonai-sandbox[e2b]; tools_run_on="e2b" resolved 143 through the praisonai wrapper. After PR #4092 both spellings reach the same provider through the same slim package.
Import paths
Old praisonai.integrations.compute.* imports still work through sys.modules module aliases — the same module object is reachable from both paths.
# New (canonical)
from praisonai_sandbox.compute import DockerCompute
# Backward-compatible alias (still works)
from praisonai.integrations.compute import DockerCompute| Provider | Canonical location | Backward-compatible alias |
|---|---|---|
LocalCompute | praisonai_sandbox.compute.local | praisonai.integrations.compute.local |
DockerCompute | praisonai_sandbox.compute.docker | praisonai.integrations.compute.docker |
E2BCompute | praisonai_sandbox.compute.e2b | praisonai.integrations.compute.e2b |
ModalCompute | praisonai_sandbox.compute.modal_compute | praisonai.integrations.compute.modal_compute |
DaytonaCompute | praisonai_sandbox.compute.daytona | praisonai.integrations.compute.daytona |
FlyioCompute | praisonai_sandbox.compute.flyio | praisonai.integrations.compute.flyio |
TenkiCompute | praisonai_sandbox.compute.tenki | praisonai.integrations.compute.tenki |
Use the Backends Directly
Import a backend class straight from the package when you want the isolated runtime without an Agent:
import asyncio
from praisonaiagents.sandbox import SandboxConfig, SandboxManager
async def main():
manager = SandboxManager(SandboxConfig.subprocess())
result = await manager.run_code("print('hello from the sandbox')")
print(result.stdout)
asyncio.run(main())Platform support
praisonai-sandbox runs on Linux, macOS, and Windows — the subprocess backend enforces different isolation on each, and the cloud backends (Docker, E2B, Modal, Daytona, Novita, SSH) behave identically everywhere.
| Backend | Linux / macOS | Windows |
|---|---|---|
subprocess | Full setrlimit, process-group kill, symlink escape rejection | No setrlimit, leader-only kill; symlink protection only when Developer Mode / SeCreateSymbolicLinkPrivilege is present |
docker | ✅ Full container isolation | ✅ Full container isolation (Docker Desktop) |
e2b, daytona, novita | ✅ Cloud isolation | ✅ Cloud isolation |
modal | ✅ Cloud isolation — stateless, no file storage | ✅ Cloud isolation — stateless, no file storage |
ssh | ✅ Isolation is provided by the remote host | ✅ Isolation is provided by the remote host |
sandlock | ✅ Landlock / seatbelt | ❌ Not available |
Every backend is lazy-loaded — importing one never imports the others.
from praisonai_sandbox import (
DockerSandbox,
SubprocessSandbox,
SandlockSandbox,
SSHSandbox,
ModalSandbox,
DaytonaSandbox,
NovitaSandbox,
E2BSandbox,
NovitaSandbox,
)Backward Compatibility
The old praisonai.sandbox import path still works through shims.
# New (recommended)
from praisonai_sandbox import SubprocessSandbox
# Backward-compatible shim (still works)
from praisonai.sandbox import SubprocessSandboxUse praisonai_sandbox in new code; the shim keeps existing scripts running unchanged.
How It Fits with SandboxManager
SandboxManager stays the entry point — agents reach backends through the registry, never by importing them directly.
The agents layer uses praisonaiagents._sandbox_bridge for registry-only dispatch, so it never imports sandbox backends at module load.
Console Script
The package ships a praisonai-sandbox console script for listing available backends.
$ praisonai-sandbox backends
daytona: unavailable
docker: unavailable
e2b: unavailable
modal: unavailable
novita: unavailable
sandlock: unavailable
ssh: unavailable
subprocess: availableThe user-facing CLI remains praisonai sandbox … — this console script lists backends and points you at the Python API and the wrapper command.
Validating your install
Run the single-command smoke suite from a repo checkout to confirm every backend you have installed is wired up correctly.
cd src/praisonai-sandbox
python e2e-validation/run_e2e.pyThe runner prints a PASS / FAIL / SKIP table and exits 0 when every required check passes. No API keys are needed for the subprocess path; Docker is optional and is skipped gracefully when the daemon or base image is unavailable.
| Check | Required | Notes |
|---|---|---|
| Subprocess execute | ✅ | No dependencies |
| SandboxManager subprocess | ✅ | Via praisonaiagents.sandbox |
| Backward-compat shim | ✅ | praisonai.sandbox → praisonai_sandbox (skipped if the praisonai wrapper isn’t installed) |
| Docker execute | ⬜ optional | Skipped when Docker daemon/image is unavailable |
| CLI backends smoke | ✅ | praisonai-sandbox backends |
Set PRAISONAI_SANDBOX_E2E_DOCKER_TIMEOUT (seconds, default 180) to raise the bound on the optional Docker check for slow networks:
PRAISONAI_SANDBOX_E2E_DOCKER_TIMEOUT=300 python e2e-validation/run_e2e.pySee MANUAL-E2E-GUIDE.md for step-by-step manual validation of each backend path.
Best Practices
Install only the backends you use
The base package is intentionally slim. Add [docker], [e2b], [modal], [ssh], [sandlock], [daytona], or [novita] extras individually instead of [all] to keep the dependency tree small.
Set cloud credentials before selecting cloud backends
daytona needs DAYTONA_API_KEY (and optional DAYTONA_API_URL); novita needs NOVITA_API_KEY; e2b and modal need their own provider credentials. Selecting a backend without its credentials fails fast.
Prefer the canonical import
Import from praisonai_sandbox in new code. The praisonai.sandbox shim stays for existing scripts.
Let the wrapper install it for you
pip install praisonai bundles praisonai-sandbox — install the standalone package only for minimal, sandbox-only environments.
Interact through SandboxManager
Keep using SandboxManager and sandbox=True on agents. Backends resolve through the registry, so where they live is an internal detail.
Check availability in CI
Run praisonai-sandbox backends in CI to confirm the expected backend is installed before a pipeline depends on it.
Smoke every backend before shipping
Run python e2e-validation/run_e2e.py from src/praisonai-sandbox/ to smoke every backend you’ve installed. It’s the fastest way to catch a broken Docker daemon or a missing extra before an agent hits it in production. See the Validating your install section above.
Prefer the wrapper CLI for run / shell
The standalone script lists backends; the praisonai sandbox run / shell commands execute code and open REPLs with full flag support.