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

# Agent Sandbox

> Isolated execution for Run Code nodes and plugins, and what each deployment model can offer

The Agent Sandbox is where Noxus runs code it did not write: **Run Code** nodes and **all plugin execution**. It is a separate service with its own isolation model, and it is **not deployed by default**.

<Warning>
  **Plugins require the sandbox.** The plugin system is switched on by the
  presence of `SANDBOX_MANAGER_URL`, which is only injected into the Noxus
  Backend and Workers when the sandbox is deployed. Without it, plugin nodes and
  triggers do not load — and nothing raises an error. They are simply absent from
  the platform.

  If you are upgrading from a release that ran a standalone plugin server, you
  must enable the sandbox or you will lose your plugins.
</Warning>

## When you need it

<CardGroup cols={2}>
  <Card title="You need it" icon="circle-check">
    You use plugins, or your workflows contain **Run Code** nodes that should be
    properly isolated.
  </Card>

  <Card title="You may not need it" icon="circle-minus">
    No plugins and no Run Code nodes. The rest of the platform is unaffected by
    leaving it off.
  </Card>
</CardGroup>

***

## Isolation modes

The sandbox runs jailed processes. Which jail it can use depends on what your
platform lets a container request.

| Mode      | Isolation                                        | Requires     | Use when                                                                  |
| :-------- | :----------------------------------------------- | :----------- | :------------------------------------------------------------------------ |
| `syd`     | Syscall filtering **and** network jail           | `SYS_PTRACE` | Default. Any deployment running untrusted or user-authored code.          |
| `minimal` | `chroot` plus egress restricted by NetworkPolicy | `SYS_ADMIN`  | Only when the platform refuses `SYS_PTRACE`, and only for code you trust. |

<Warning>
  `minimal` constrains the filesystem and the network but **not syscalls**. It
  is meaningfully weaker than `syd`. Treat it as a compatibility fallback, not
  an equivalent option.
</Warning>

### Platform compatibility

| Platform                          | `syd` jail        | Notes                                                                                   |
| :-------------------------------- | :---------------- | :-------------------------------------------------------------------------------------- |
| EKS                               | Supported         | Works on Auto Mode and managed node groups.                                             |
| GKE Standard                      | Supported         |                                                                                         |
| **GKE Autopilot**                 | **Not supported** | Autopilot refuses `SYS_PTRACE`. You must use `minimal`, or move to Standard node pools. |
| AKS                               | Supported         |                                                                                         |
| Restrictive PodSecurity admission | Depends           | A policy that blocks added capabilities blocks `syd`.                                   |

The network jail in `minimal` mode is enforced by a Kubernetes NetworkPolicy,
which requires a CNI that implements policy. The `azure-aks` stack in
[noxus-infra](https://github.com/noxus-ai/noxus-infra) sets `network_policy = "cilium"` for
this reason; the default CNIs on EKS and GKE already enforce policy. Without an
enforcing CNI the NetworkPolicy object exists and does nothing.

***

## Configuration

| Variable                 | Default | Description                                                                              |
| :----------------------- | :------ | :--------------------------------------------------------------------------------------- |
| `SANDBOX_MANAGER_URL`    | `""`    | URL of the sandbox manager. **Empty disables the sandbox and the entire plugin system.** |
| `USE_REMOTE_SANDBOX`     | `true`  | Route Run Code through the sandbox service rather than executing locally.                |
| `REMOTE_SANDBOX_BACKEND` | `""`    | Remote execution backend. `syd` in normal use.                                           |
| `SANDBOX_BACKEND`        | `syd`   | Jail implementation.                                                                     |
| `LOCAL_SANDBOX_BACKEND`  | `deno`  | Worker-local fallback — see below.                                                       |
| `PLUGIN_CALL_TIMEOUT`    | `240.0` | Seconds before a plugin call is abandoned.                                               |

### The local fallback matters

`LOCAL_SANDBOX_BACKEND` is what a Worker uses when the remote sandbox is off or
unhealthy:

* **`none`** — no local execution. The safest setting when a remote sandbox is
  present, and the default the Helm chart selects when `sandbox.enabled=true`.
* **`deno`** — a worker-local Deno/Pyodide runtime. Reasonable isolation, limited
  capability.
* **`subprocess`** — runs user code as a plain subprocess **in the Worker's own
  process tree**. Much weaker isolation. Do not use this in a multi-tenant
  deployment.

<Note>
  Setting `LOCAL_SANDBOX_BACKEND=subprocess` as a way to "make Run Code work
  without deploying the sandbox" gives untrusted code the Worker's filesystem,
  network, and environment — including its database credentials.
</Note>

***

## Deployment

<Tabs>
  <Tab title="Kubernetes">
    The sandbox is a Deployment in the Noxus Helm chart, off by default:

    ```yaml theme={null}
    sandbox:
      enabled: true
      jail: syd          # or "minimal" where SYS_PTRACE is unavailable
      localBackend: ""   # empty selects the per-mode default ("none" when enabled)
      storage: "10Gi"
      shmSize: "512Mi"
      resources:
        requests: { cpu: "1", memory: "2Gi" }
        limits: { cpu: "2", memory: "4Gi" }
    ```

    Enabling it also injects `SANDBOX_MANAGER_URL` into the Backend and Workers,
    and applies the sandbox NetworkPolicy.

    In the Terraform stacks the equivalent is `sandbox_enabled = true`, which is
    the default there.
  </Tab>

  <Tab title="Serverless containers">
    Deploy the sandbox as an additional internal container service, reachable
    only from the Backend and Workers — it should not have public ingress.

    Point `SANDBOX_MANAGER_URL` at its internal address.

    <Warning>
      Syscall-level jailing depends on capabilities that managed container
      runtimes may not grant. Verify that your platform permits the sandbox's
      required capabilities before relying on `syd` isolation here.
    </Warning>
  </Tab>

  <Tab title="Virtual Machine">
    The appliance image runs the sandbox as a Compose service (`agentsandbox`)
    and sets `SANDBOX_MANAGER_URL=http://agentsandbox:8000` automatically. No
    additional configuration is needed.
  </Tab>
</Tabs>

***

## Filesystem and state

The sandbox uses a copy-on-write filesystem whose state is periodically synced
to object storage, so the pod itself can run on ephemeral disk.

| Variable                   | Default       | Description                                 |
| :------------------------- | :------------ | :------------------------------------------ |
| `SANDBOX_FS_ENABLED`       | `"true"`      | Enable the synced copy-on-write filesystem. |
| `SANDBOX_FS_PREFIX`        | `"sandboxes"` | Key prefix within the storage bucket.       |
| `SANDBOX_FS_SYNC_INTERVAL` | `"300"`       | Seconds between syncs.                      |

It reuses the platform's existing storage configuration — `BUCKET_CLIENT`,
`SPOTFLOW_STORAGE_BUCKET`, and whatever credentials or workload identity the
Backend and Workers already use. No separate bucket is required.

***

## Sizing

The sandbox's own resource requests cover the **manager**, not the code it runs.
Jailed processes draw from the same container limits, so a deployment running
heavy Run Code workloads needs headroom above the defaults.

Start at 1 vCPU / 2 GiB requests with 2 vCPU / 4 GiB limits, and raise the limits
if you see sandbox restarts under load.

***

## Health and troubleshooting

The sandbox manager exposes `/health`, used for all three probes.

| Symptom                                              | Cause                                                                                                            |
| :--------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- |
| Plugins missing from the platform, no error anywhere | Sandbox not deployed, so `SANDBOX_MANAGER_URL` is empty                                                          |
| Sandbox pods stuck `Pending` or failing admission    | `SYS_PTRACE` refused — GKE Autopilot or a restrictive PodSecurity policy. Use `minimal`.                         |
| Run Code executes but has no network access          | Expected. The NetworkPolicy restricts egress by design; widen it deliberately rather than disabling the sandbox. |
| Sandbox restarts during heavy Run Code use           | Container limits exhausted by the jailed processes. Raise them.                                                  |

<CardGroup cols={2}>
  <Card title="Plugin Development" icon="puzzle-piece" href="/developers/plugins/overview">
    Build plugins that run inside the sandbox.
  </Card>

  <Card title="Environment Configuration" icon="sliders" href="/deployment/configuration/environment">
    The full platform variable reference.
  </Card>
</CardGroup>
