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

# Sandbox Backends

> Execute commands safely with configurable shell control across different backends

Sandbox backends provide isolated command execution environments with explicit shell control to prevent injection attacks while enabling shell features when needed.

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

agent = Agent(
    name="Coder",
    instructions="Run shell commands safely",
    sandbox=True,
)
agent.start("List Python files in the current directory")
```

The user runs commands through the agent; the sandbox backend isolates execution with explicit shell control.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Sandbox Command Execution"
        A[📝 Command] --> B{🔍 shell=?}
        B -->|False| C[🛡️ Safe Parse]
        B -->|True| D[⚠️ Shell Features]
        C --> E[✅ Execute]
        D --> E
    end
    
    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef safe fill:#10B981,stroke:#7C90A0,color:#fff
    classDef shell fill:#8B0000,stroke:#7C90A0,color:#fff
    
    class A input
    class B decision
    class C,E safe
    class D shell
```

## Quick Start

<Steps>
  <Step title="Simple Usage">
    Enable sandbox on the agent — subprocess backend is the default:

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

    agent = Agent(
        name="System Agent",
        instructions="Execute system commands safely",
        sandbox=True,
    )
    agent.start("List files in the current directory")
    ```
  </Step>

  <Step title="With Configuration">
    Pick a specific backend via `SandboxConfig` or the CLI `--sandbox-type` flag:

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

    agent = Agent(
        name="Data Agent",
        instructions="Process data in an isolated container",
        sandbox=SandboxConfig.docker("python:3.11-slim"),
    )
    agent.start("Run pip list and summarise installed packages")
    ```

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai sandbox run --code "print('hello')" --type docker
    ```
  </Step>
</Steps>

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Agent
    participant Sandbox
    participant Shell
    participant Process
    
    Agent->>Sandbox: run_command(cmd, shell=False)
    alt shell=False (Safe)
        Sandbox->>Shell: shlex.split(cmd)
        Shell->>Process: exec(*argv)
    else shell=True (Features)
        Sandbox->>Shell: sh -c "cmd"
        Shell->>Process: shell execution
    end
    Process-->>Sandbox: Result
    Sandbox-->>Agent: SandboxResult
```

| Backend             | Use Case                   | Security Level                          |
| ------------------- | -------------------------- | --------------------------------------- |
| `SubprocessSandbox` | Local development, scripts | Medium (OS-level isolation, POSIX only) |
| `DockerSandbox`     | Production, untrusted code | High (container isolation)              |
| `SSHSandbox`        | Remote execution           | High (network isolation)                |

***

## Which Backend Should I Use?

Pick a backend based on where the code runs and how much you trust it.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Start([Where does code run?]) --> Q1{Run locally?}
    Q1 -->|Yes, fast dev| A[subprocess<br/>default, zero setup]
    Q1 -->|Yes, hardened| B[native / sandlock<br/>OS-level isolation]
    Q1 -->|Container isolation| C[docker<br/>production, untrusted code]
    Q1 -->|Remote server| D[ssh<br/>network isolation]
    Q1 -->|Cloud sandbox| E[modal / e2b<br/>managed cloud runtime]

    classDef start fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef answer fill:#10B981,stroke:#7C90A0,color:#fff

    class Start start
    class Q1 question
    class A,B,C,D,E answer
```

***

## All Built-in Sandbox Backends

PR #2003 exposes all seven sandboxes through `SandboxRegistry` — selectable by string name from the CLI or Python.

| Name         | Class               | Typical use                                     |
| ------------ | ------------------- | ----------------------------------------------- |
| `docker`     | `DockerSandbox`     | Container isolation for production              |
| `subprocess` | `SubprocessSandbox` | Fast local development (default)                |
| `sandlock`   | `SandlockSandbox`   | Hardened local sandbox                          |
| `ssh`        | `SSHSandbox`        | Remote server execution                         |
| `modal`      | `ModalSandbox`      | Modal cloud sandboxes                           |
| `daytona`    | `DaytonaSandbox`    | **Not implemented** — use subprocess/docker/e2b |
| `e2b`        | `E2BSandbox`        | E2B cloud code interpreter                      |

**Plugin-registered backends** (installed separately, resolved via the `praisonai.sandbox` entry-point group):

| Name      | Source                           | Typical use                                                               |
| --------- | -------------------------------- | ------------------------------------------------------------------------- |
| `capsule` | Plugin (via `praisonai.sandbox`) | Plugin-provided secure sandbox — install via `praisonai-plugins[capsule]` |

### Select by Name

<Tabs>
  <Tab title="CLI">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # Run code in any registered backend
    praisonai sandbox run --code "print('hello')" --type subprocess
    praisonai sandbox run --code "print('hello')" --type e2b
    praisonai sandbox run --file script.py --type modal
    praisonai sandbox run --code "ls" --type docker --image python:3.11-slim
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonai.sandbox._registry import SandboxRegistry

    agent = Agent(name="Coder", instructions="Run code safely")

    registry = SandboxRegistry.default()
    sandbox_cls = registry.resolve("daytona")  # or docker, e2b, modal, ssh, sandlock, subprocess
    sandbox = sandbox_cls()
    ```
  </Tab>
</Tabs>

### Installing Optional Backends

Only `subprocess` and `sandlock` ship in the base install — every other backend requires an optional extra.

| Backend      | Install command                            |
| ------------ | ------------------------------------------ |
| `subprocess` | Built in — no extra required               |
| `sandlock`   | Built in — no extra required               |
| `docker`     | `pip install "praisonai[docker]"`          |
| `ssh`        | `pip install "praisonai[ssh]"`             |
| `modal`      | `pip install "praisonai[modal]"`           |
| `daytona`    | `pip install "praisonai[daytona]"`         |
| `e2b`        | `pip install "praisonai[e2b]"`             |
| `capsule`    | `pip install "praisonai-plugins[capsule]"` |

Selecting an uninstalled backend exits with code 2 and prints a fix-it hint — no silent downgrade to subprocess:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
$ praisonai sandbox run --code "print('hi')" --type modal
Error: sandbox 'modal' is unavailable: <reason>
Available: ['subprocess', 'sandlock']
To install the optional backend:  pip install "praisonai[modal]"
Or explicitly choose another sandbox:  --sandbox-type subprocess
$ echo $?
2
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    A[--sandbox-type X] --> B{Registry}
    B -->|installed| C[✅ Run]
    B -->|missing| D[❌ Error + hint\nexit code 2]

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef registry fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef success fill:#10B981,stroke:#7C90A0,color:#fff
    classDef error fill:#8B0000,stroke:#7C90A0,color:#fff

    class A input
    class B registry
    class C success
    class D error
```

<Note>
  You'll never get an unexpected backend — if `--sandbox-type X` isn't available, the CLI tells you exactly what to install.
</Note>

For **plugin-registered** backends (like `capsule`), `SandboxManager` resolves the name through `SandboxRegistry` and raises a clearer error when the plugin is missing. When `praisonai` is installed but the plugin is not registered:

```
ValueError: Unknown sandbox type: 'capsule'. Available: ['docker', 'subprocess', 'sandlock', 'ssh', 'modal', 'daytona', 'e2b']
```

When `praisonai` itself is not installed (the registry import fails):

```
ValueError: Unknown sandbox type: 'capsule'. Supported built-ins: 'docker', 'subprocess', 'e2b', 'sandlock', 'ssh', 'modal', 'daytona'. Install a plugin package that registers 'capsule' under the 'praisonai.sandbox' entry-point group (e.g. pip install praisonai-plugins[capsule]).
```

### Third-Party Sandbox Plugins

Register custom sandboxes via the `praisonai.sandbox` entry-point group:

```toml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# pyproject.toml
[project.entry-points."praisonai.sandbox"]
my-sandbox = "my_pkg.sandbox:MySandbox"
```

After `pip install`, the new name appears alongside the built-ins when you call `registry.list_names()`.

### Example: Capsule (from praisonai-plugins)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install "praisonai-plugins[capsule]"
```

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

agent = Agent(
    name="SecureRunner",
    instructions="Execute code inside the Capsule sandbox.",
    sandbox=SandboxConfig.capsule(),   # strict security policy applied automatically
)

agent.start("Run a Python script")
```

The `capsule` backend is registered by `praisonai-plugins` under the `praisonai.sandbox` entry-point group. `SandboxManager` resolves the name via `SandboxRegistry` the first time the sandbox starts.

### Which Sandbox Should I Pick?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    A[Need sandbox execution?] --> B{Where should code run?}
    B -->|Local machine| C{Need container isolation?}
    B -->|Remote server| D[ssh]
    B -->|Cloud provider| E{Which platform?}
    C -->|No, fast dev| F[subprocess or sandlock]
    C -->|Yes| G[docker]
    E -->|Modal| H[modal]
    E -->|Daytona| I[daytona]
    E -->|E2B| J[e2b]

    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef choice fill:#10B981,stroke:#7C90A0,color:#fff

    class A,B,C,E decision
    class D,F,G,H,I,J choice
```

***

## Configuration Options

### Shell Parameter Control

<Tabs>
  <Tab title="shell=False (Default)">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # String commands are parsed safely
    result = await sandbox.run_command("python script.py --arg value")

    # List commands are executed directly
    result = await sandbox.run_command(["python", "script.py", "--arg", "value"])
    ```

    **Security**: No shell injection possible. String commands are parsed with `shlex.split()`.
  </Tab>

  <Tab title="shell=True (Opt-in)">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # Shell features available: pipes, redirects, globs
    result = await sandbox.run_command(
        "find . -name '*.py' | xargs grep 'TODO' > todos.txt",
        shell=True
    )

    # Environment variable expansion
    result = await sandbox.run_command(
        "echo $HOME && ls $PWD/*.log", 
        shell=True
    )
    ```

    **Security**: Shell evaluation enabled. Only use with trusted input.
  </Tab>
</Tabs>

<Warning>
  Set `shell=True` only when you need shell features (pipes, `&&`, globbing). With untrusted input always keep `shell=False`.
</Warning>

### Decision Guide

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    A[Need to run command?] --> B{Need pipes/globs?}
    B -->|No| C[Use shell=False]
    B -->|Yes| D{Input trusted?}
    D -->|Yes| E[Use shell=True]
    D -->|No| F[Sanitize OR use shell=False]
    
    classDef safe fill:#10B981,stroke:#7C90A0,color:#fff
    classDef caution fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef danger fill:#8B0000,stroke:#7C90A0,color:#fff
    
    class C,F safe
    class D,E caution
```

| Use Case                                   | Recommended `shell` Value |
| ------------------------------------------ | ------------------------- |
| Running a single executable with arguments | `False`                   |
| Pipelines (`grep \| sort`)                 | `True`                    |
| Globs and env-var expansion                | `True`                    |
| Untrusted / model-generated commands       | `False`                   |

***

## Common Patterns

### Backend Selection

<Tabs>
  <Tab title="Development">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai.sandbox import SubprocessSandbox

    # Local development with subprocess
    sandbox = SubprocessSandbox()
    result = await sandbox.run_command("python test.py")
    ```
  </Tab>

  <Tab title="Production">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai.sandbox import DockerSandbox

    # Isolated container execution
    sandbox = DockerSandbox(
        image="python:3.11-slim",
        timeout=30
    )
    result = await sandbox.run_command("python app.py", shell=False)
    ```
  </Tab>

  <Tab title="Remote">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai.sandbox import SSHSandbox

    # Remote server execution
    sandbox = SSHSandbox(
        host="remote.server.com",
        username="runner"
    )
    result = await sandbox.run_command(["python", "remote_task.py"])
    ```
  </Tab>
</Tabs>

### Safe Data Processing

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.sandbox import DockerSandbox

sandbox = DockerSandbox()

# Process user data safely
async def process_file(filename):
    # Safe: no shell injection possible
    result = await sandbox.run_command([
        "python", "process.py", "--input", filename
    ], shell=False)
    return result.stdout

# Process with shell features when controlled
async def count_errors(log_file):
    import shlex
    # Trusted input, need shell features  
    result = await sandbox.run_command(
        f"grep 'ERROR' {shlex.quote(log_file)} | wc -l",
        shell=True
    )
    return int(result.stdout.strip())
```

### Resource Limits

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.sandbox import ResourceLimits, SubprocessSandbox

limits = ResourceLimits(
    timeout_seconds=30,
    memory_mb=512
)

sandbox = SubprocessSandbox()
result = await sandbox.run_command(
    "python heavy_task.py",
    limits=limits,
    shell=False
)
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Always use shell=False for untrusted input">
    Model-generated commands or user input should never use `shell=True` to prevent injection attacks. The default `shell=False` provides automatic protection.

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # ✅ Safe with any user input
    user_script = request.get("script")
    result = await sandbox.run_command(f"python {user_script}", shell=False)

    # ❌ Vulnerable to injection
    result = await sandbox.run_command(f"python {user_script}", shell=True)
    ```
  </Accordion>

  <Accordion title="Quote arguments when building shell commands">
    If you must use `shell=True`, quote all dynamic arguments with `shlex.quote()`:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    import shlex

    filename = user_input  # Could contain special characters
    command = f"process.py --file {shlex.quote(filename)}"
    result = await sandbox.run_command(command, shell=True)
    ```
  </Accordion>

  <Accordion title="Prefer list form for complex commands">
    Using argument lists avoids shell parsing entirely:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # ✅ Clear and injection-safe
    result = await sandbox.run_command([
        "python", "script.py", 
        "--input", input_file,
        "--output", output_file
    ], shell=False)

    # ❌ Requires careful quoting
    import shlex
    command = f"python script.py --input {shlex.quote(input_file)} --output {shlex.quote(output_file)}"
    result = await sandbox.run_command(command, shell=True)
    ```
  </Accordion>

  <Accordion title="Use appropriate backend for your security needs">
    Choose the sandbox backend based on your isolation requirements:

    * **Development**: `SubprocessSandbox` for speed and convenience (no longer inherits host environment)
    * **Production**: `DockerSandbox` for container-level isolation
    * **Remote**: `SSHSandbox` for network-isolated execution
    * **High Security**: Always use Docker or SSH backends with `shell=False`
  </Accordion>

  <Accordion title="Handle missing backends explicitly in scripts and CI">
    Catch exit code 2 from `praisonai sandbox run --type <X>` and either install the extra or fall back to `--sandbox-type subprocess`:

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai sandbox run --code "print('hello')" --type docker
    if [ $? -eq 2 ]; then
      echo "Docker not available, falling back to subprocess"
      praisonai sandbox run --code "print('hello')" --type subprocess
    fi
    ```

    In CI pipelines, install the required extra before running:

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    pip install "praisonai[docker]"
    praisonai sandbox run --code "print('hello')" --type docker
    ```
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Sandbox" icon="shield-halved" href="/docs/features/sandbox">
    Agent-level sandbox=True and SandboxConfig
  </Card>

  <Card title="Sandbox CLI" icon="terminal" href="/docs/cli/sandbox">
    CLI reference for praisonai sandbox run and praisonai sandbox shell
  </Card>
</CardGroup>
