# Sandboxes (/platform/self-hosting/sandboxes)





Configure a remote provider and a dedicated Function base image to run Python, Shell, JavaScript imports, or custom workspace sandboxes. Plain JavaScript can run in a local isolated-vm Node worker inside the app container.

## Choose the execution path [#choose-the-execution-path]

| Code or block setting | Runtime requirement |
| - | - |
| JavaScript without `import` or `require`, no selected sandbox or sandbox file-path reference | Local worker; no remote provider required |
| Python, Shell, JavaScript imports | Remote provider credentials and immutable Function image |
| Selected workspace sandbox | Remote provider, Function base, and sandbox access |
| File path from another block or sandbox output path | Remote sandbox filesystem |

Selecting a sandbox without a configured provider is refused with 503. File-path cases that cannot use the sandbox filesystem are refused with 422. Failing user code can also return 422; inspect the error message to distinguish the cause. A saved Python block is never silently executed as JavaScript.

## Build and verify the Function base [#build-and-verify-the-function-base]

Run these repository scripts from a checkout with dependencies installed (`bun install` at the repository root). Supply provider credentials to the build environment. Custom workspace sandboxes layer their packages on this base.

<Tabs items="['E2B', 'Daytona']">
  <Tab value="E2B">
    ```bash
    E2B_API_KEY=... \
      bun run apps/sim/scripts/build-function-e2b-template.ts \
      --name sim-function
    ```

    The builder uses E2B's maintained `code-interpreter-v1` base and assigns a release generation. It prints the immutable template/build reference and generation. `--generation` supports release automation; `--base-template` accepts an immutable base override.

    Set the exact values printed by that build, then verify and capture its package/runtime manifest:

    ```bash
    SANDBOX_PROVIDER=e2b \
    E2B_ENABLED=true \
    E2B_API_KEY=... \
    E2B_FUNCTION_TEMPLATE_ID='<template>:<build-id>' \
    E2B_FUNCTION_TEMPLATE_GENERATION='<release-epoch-ms>' \
    SANDBOX_PARITY_MANIFEST_OUT=/tmp/function-sandbox-manifest.json \
      bun run apps/sim/scripts/verify-sandbox-parity.ts
    ```

    Replace the placeholders before running. Setting `SANDBOX_PROVIDER=e2b` explicitly prevents an exported Daytona selection from changing this verification step.
  </Tab>

  <Tab value="Daytona">
    The API key needs `write:snapshots` to build and `write:sandboxes` to execute. The builder reconstructs packages from an accepted E2B manifest: complete the E2B build and verification first, even when Daytona is your runtime provider.

    ```bash
    DAYTONA_API_KEY=... \
      bun run apps/sim/scripts/build-function-daytona-snapshot.ts \
      --name "sim-function-<release>" \
      --parity-manifest /tmp/function-sandbox-manifest.json
    ```

    Use the snapshot ID printed by the builder and verify it against the accepted E2B baseline:

    ```bash
    SANDBOX_PROVIDER=daytona \
    DAYTONA_API_KEY=... \
    DAYTONA_FUNCTION_SNAPSHOT_ID='<snapshot-uuid>' \
    SANDBOX_PARITY_MANIFEST_BASELINE=/tmp/function-sandbox-manifest.json \
      bun run apps/sim/scripts/verify-sandbox-parity.ts
    ```

    Replace the placeholders before running.
  </Tab>
</Tabs>

<Callout type="warn">
  Function images must be immutable. `E2B_FUNCTION_TEMPLATE_ID` requires an exact `<template>:<build-id>` reference with a UUID build ID, plus the positive `E2B_FUNCTION_TEMPLATE_GENERATION` printed by that build. `DAYTONA_FUNCTION_SNAPSHOT_ID` requires a snapshot UUID, not a mutable name. Missing or invalid values do not fall back to a shell image.
</Callout>

## Configure the deployment [#configure-the-deployment]

Apply the verified runtime values through the deployment's environment or secret mechanism:

<Tabs items="['E2B', 'Daytona']">
  <Tab value="E2B">
    ```dotenv
    SANDBOX_PROVIDER=e2b
    E2B_ENABLED=true
    E2B_API_KEY=...
    E2B_FUNCTION_TEMPLATE_ID=<template>:<build-id>
    E2B_FUNCTION_TEMPLATE_GENERATION=<release-epoch-ms>
    ```
  </Tab>

  <Tab value="Daytona">
    ```dotenv
    SANDBOX_PROVIDER=daytona
    DAYTONA_API_KEY=...
    DAYTONA_FUNCTION_SNAPSHOT_ID=<snapshot-uuid>
    ```
  </Tab>
</Tabs>

### Enable sandbox access and controls [#enable-sandbox-access-and-controls]

| Variable | Effect |
| - | - |
| `SANDBOXES_ENABLED=true` | Grants the server-side sandbox entitlement on a billing-disabled self-hosted deployment |
| `NEXT_PUBLIC_SANDBOXES_ENABLED=true` | Reveals the Function block's **Sandbox** selector; asserts readiness rather than checking it |

On a billing-disabled deployment, `ENTERPRISE_ENABLED=true` also grants the entitlement when `SANDBOXES_ENABLED` is unset. The server must verify provider credentials and the immutable Function base before offering Shell and the sandbox list. **Settings → Sandboxes** remains in the sidebar but shows an upgrade notice until access/readiness resolves. Python remains selectable; execution still requires the remote configuration.

Set the browser flag only after provider verification succeeds. On Compose or a source checkout, `bunx sim-setup doctor` compares the public flag with selected-provider readiness.

## Promote or roll back a build [#promote-or-roll-back-a-build]

Use the accepted E2B manifest as the release baseline. Verify the exact E2B build and any Daytona reconstruction before updating the deployment variables above.

<Callout type="warn">
  Every promoted E2B Function base needs a generation greater than every prior deployment. A rollback is a new promotion: assign a higher generation to the older build instead of reusing its old generation.
</Callout>

## Configure other code images [#configure-other-code-images]

Chat's public `run_function` and `run_code` tools use a separate shell image, including plain JavaScript. The workflow-internal `function_execute` path uses the Function image.

```dotenv
# E2B shell image
MOTHERSHIP_E2B_TEMPLATE_ID=<shell-template-ref>

# Daytona shell image
DAYTONA_SHELL_SNAPSHOT_ID=<shell-snapshot-ref>
```

These values do not replace `E2B_FUNCTION_TEMPLATE_ID` or `DAYTONA_FUNCTION_SNAPSHOT_ID`. Shell, Function, document, and Pi images have separate package contracts and release cadences. Pi also needs `E2B_PI_TEMPLATE_ID` or `DAYTONA_PI_SNAPSHOT_ID`; revealing a Pi mode with `NEXT_PUBLIC_E2B_ENABLED` does not supply that image.

## Related docs [#related-docs]

* [Environment variables](/platform/self-hosting/environment-variables)
* [Security and hardening](/platform/self-hosting/security)
