> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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.

<Info>
  Standalone `praisonai-sandbox` still guards built-in provider names against pip-plugin shadowing — the vendored `PluginRegistry` fallback carries the same check since [PR #4184](https://github.com/MervinPraison/PraisonAI/pull/4184). See [Plugin Precedence](/docs/features/plugin-precedence#every-registry-is-guarded).
</Info>

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    A[🤖 Agent] --> P[📦 praisonai-sandbox]
    P --> S1[subprocess]
    P --> S2[docker]
    P --> S3[e2b]
    P --> S4[modal]
    P --> S5[ssh]
    P --> S6[sandlock]
    P --> S7[daytona]
    P --> S8[novita]

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef pkg fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef backend fill:#10B981,stroke:#7C90A0,color:#fff

    class A agent
    class P pkg
    class S1,S2,S3,S4,S5,S6,S7,S8 backend
```

## Quick Start

<Steps>
  <Step title="Run an agent with the default backend">
    The `subprocess` backend ships in the base install — nothing else to configure:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="Coder",
        instructions="Run code safely",
        sandbox=True,
    )
    agent.start("Print the current directory tree")
    ```
  </Step>

  <Step title="Pick a specific backend">
    Choose a backend with `SandboxConfig`:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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")
    ```
  </Step>

  <Step title="Install the slim package and optional backends">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    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
    ```
  </Step>

  <Step title="List available backends">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai-sandbox backends
    ```

    ```
    daytona: unavailable
    docker: unavailable
    e2b: unavailable
    modal: unavailable
    novita: unavailable
    sandlock: unavailable
    ssh: unavailable
    subprocess: available
    ```

    Each backend reports `available` or `unavailable` based on whether its optional dependency is installed.
  </Step>
</Steps>

<Note>
  The standalone `praisonai-sandbox` console script currently exposes `--help` and `backends`. To **run** code or open an interactive **shell**, use the wrapper CLI — `praisonai sandbox run` / `praisonai sandbox shell` (see [Sandbox CLI](/docs/cli/sandbox)).
</Note>

<Info>
  The slim install is not less safe: its vendored `PluginRegistry` fallback enforces the same built-in guard, so a pip package publishing `docker` cannot replace the built-in ([PR #4184](https://github.com/MervinPraison/PraisonAI/pull/4184)). See [Plugin Precedence](/docs/features/plugin-precedence#every-registry-is-guarded).
</Info>

## Do I Need to Install It Directly?

Most users never install `praisonai-sandbox` on its own — the full wrapper already bundles it.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{Do I need praisonai-sandbox directly?}:::question
    Q -->|Using the full stack| A[No — pip install praisonai<br/>bundles every backend]:::ok
    Q -->|Want a minimal footprint| B[Yes — pip install<br/>praisonai-sandbox extras]:::pick

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef pick fill:#189AB4,stroke:#7C90A0,color:#fff
```

***

## 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]`)                         |
| `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`)    |

<Note>
  Only `subprocess` ships in the base `praisonai-sandbox` install. Every other backend — including `sandlock` — requires its matching extra. This differs from the full `praisonai` wrapper, where `subprocess` **and** `sandlock` are both built in.
</Note>

***

## 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](https://github.com/MervinPraison/PraisonAI/pull/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`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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")
```

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install "praisonai-sandbox[e2b]"   # enough to reach tools_run_on="e2b"
```

That single install is all you need — no full `praisonai` wrapper.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "praisonai-sandbox"
        subgraph "SandboxProtocol"
            SB1[DockerSandbox]
            SB2[E2BSandbox]
            SB3[SubprocessSandbox]
        end
        subgraph "ComputeProviderProtocol"
            CP1[DockerCompute]
            CP2[E2BCompute]
            CP3[LocalCompute]
        end
    end

    Agent[🤖 Agent] -->|sandbox=| SB1
    Agent -->|tools_run_on= / run_in=| CP2

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef sandbox fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef compute fill:#6366F1,stroke:#7C90A0,color:#fff

    class Agent agent
    class SB1,SB2,SB3 sandbox
    class CP1,CP2,CP3 compute
```

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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What do I need?}:::question
    Q -->|Just run code in a sandbox| S["pip install<br/>praisonai-sandbox[e2b]"]:::pick
    Q -->|tools_run_on= / run_in=| S
    Q -->|Full stack: gateway, CLI, bots| W["pip install praisonai"]:::ok

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef pick fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
```

### Import paths

Old `praisonai.integrations.compute.*` imports still work through `sys.modules` **module aliases** — the same module object is reachable from both paths.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# 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`         |

<Note>
  The shims are `sys.modules` module aliases, not `from … import X` re-exports. Both paths point at the **same module object**, so monkeypatching a module-level name through either path lands on the real module — tests that patch via the old import keep working unchanged.
</Note>

***

## Use the Backends Directly

Import a backend class straight from the package when you want the isolated runtime without an `Agent`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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`, `modal`, `daytona`, `novita` | ✅ Cloud isolation                                              | ✅ Cloud isolation                                                                                                          |
| `ssh`                               | ✅ Isolation is provided by the remote host                     | ✅ Isolation is provided by the remote host                                                                                 |
| `sandlock`                          | ✅ Landlock / seatbelt                                          | ❌ Not available                                                                                                            |

<Warning>
  On Windows, the built-in `subprocess` backend enforces fewer platform limits than on POSIX. Use `docker` or a cloud backend when running untrusted code. See the [main sandbox page](/docs/docs/features/sandbox#resource-limits-in-practice) for the full capability matrix and [PR #3224](https://github.com/MervinPraison/PraisonAI/pull/3224) for background.
</Warning>

***

Every backend is lazy-loaded — importing one never imports the others.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# New (recommended)
from praisonai_sandbox import SubprocessSandbox

# Backward-compatible shim (still works)
from praisonai.sandbox import SubprocessSandbox
```

Use `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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Agent[🤖 Agent] --> Manager[⚙️ SandboxManager]
    Manager --> Registry[🔍 registry]
    Registry --> Backend[📦 praisonai_sandbox.Backend]
    Backend --> Result[✅ SandboxResult]

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef manager fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef registry fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef backend fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff

    class Agent agent
    class Manager manager
    class Registry registry
    class Backend backend
    class Result ok
```

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.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
$ praisonai-sandbox backends
daytona: unavailable
docker: unavailable
e2b: unavailable
modal: unavailable
novita: unavailable
sandlock: unavailable
ssh: unavailable
subprocess: available
```

The 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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "E2E Runner"
        R[▶️ run_e2e.py] --> C1[✅ subprocess]
        R --> C2[✅ SandboxManager]
        R --> C3[✅ shim]
        R --> C4{🐳 Docker?}
        R --> C5[✅ CLI]
        C4 -->|available| C4a[✅ execute]
        C4 -->|unavailable| C4b[⏭️ SKIP]
    end

    classDef runner fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef check fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef pass fill:#10B981,stroke:#7C90A0,color:#fff
    classDef skip fill:#8B0000,stroke:#7C90A0,color:#fff

    class R runner
    class C1,C2,C3,C5,C4a pass
    class C4 decision
    class C4b skip
```

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
cd src/praisonai-sandbox
python e2e-validation/run_e2e.py
```

The 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.

<Note>
  The `e2e-validation/` bundle ships with the source repository, **not** the published wheel. Run these commands from a checkout of [`MervinPraison/PraisonAI`](https://github.com/MervinPraison/PraisonAI) under `src/praisonai-sandbox/`, not from a `pip install`ed environment.
</Note>

| 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:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
PRAISONAI_SANDBOX_E2E_DOCKER_TIMEOUT=300 python e2e-validation/run_e2e.py
```

See [`MANUAL-E2E-GUIDE.md`](https://github.com/MervinPraison/PraisonAI/blob/main/src/praisonai-sandbox/e2e-validation/MANUAL-E2E-GUIDE.md) for step-by-step manual validation of each backend path.

***

## Best Practices

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="Prefer the canonical import">
    Import from `praisonai_sandbox` in new code. The `praisonai.sandbox` shim stays for existing scripts.
  </Accordion>

  <Accordion title="Let the wrapper install it for you">
    `pip install praisonai` bundles `praisonai-sandbox` — install the standalone package only for minimal, sandbox-only environments.
  </Accordion>

  <Accordion title="Interact through SandboxManager">
    Keep using `SandboxManager` and `sandbox=True` on agents. Backends resolve through the registry, so where they live is an internal detail.
  </Accordion>

  <Accordion title="Check availability in CI">
    Run `praisonai-sandbox backends` in CI to confirm the expected backend is installed before a pipeline depends on it.
  </Accordion>

  <Accordion title="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](#validating-your-install) section above.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Sandbox Backends" icon="shield" href="/docs/features/sandbox-backends">
    All eight backends, the registry, and backend selection guide
  </Card>

  <Card title="Sandbox CLI" icon="terminal" href="/docs/cli/sandbox">
    `praisonai sandbox run`, `shell`, and `backends` commands
  </Card>

  <Card title="Sandboxed Agent" icon="shield-check" href="/docs/docs/features/sandboxed-agent">
    Local agent loop with tool sandboxing
  </Card>

  <Card title="praisonai-sandbox SDK" icon="box" href="/docs/docs/sdk/praisonai-sandbox/index">
    Package overview and public API surface
  </Card>
</CardGroup>
