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

# Sandbox

> An isolated container you drive from Python: run code, manage files, expose ports, snapshot memory

A `Sandbox` is a box with a control API. You create one, then run code or processes in it, read and write its
files, open ports to the outside, and throw it away. A CPU sandbox runs in gVisor with CPU, memory and network
limits, which is what makes it safe for code an LLM wrote or a customer uploaded. A sandbox that asks for a GPU
runs on a GPU pool, and those run runc. The hardening under [Network](#network) and [Isolation](#isolation) is
there for them, but not all of it is switched on yet, so keep code you don't trust off GPU sandboxes.

```python theme={null}
from levers9 import Blueprint, Sandbox

sandbox = Sandbox(
    cpu=1, memory="1Gi",
    image=Blueprint(python_version="python3.11", python_packages=["numpy"]),
    keep_warm_seconds=600,           # -1 keeps it until you terminate it
    block_network=True,              # or allow_list=["140.82.112.0/20"]
    workspace_token=False,           # code in here can't act on your workspace
    authorized=True,                 # exposed ports need the workspace token
)
box = sandbox.create()

r = box.process.run_code("import numpy as np; print(np.arange(3).sum())")
print(r.result, r.exit_code)         # "3", 0

p = box.process.exec("python", "-m", "http.server", "8000")
url = box.expose_port(8000)          # callers send Authorization: Bearer <workspace token>
print(url)

box.fs.write_text("/workspace/notes.md", "# hello")
print(box.fs.list_files("/workspace"))
box.fs.upload_file("./data.csv", "/workspace/data.csv")
box.fs.download_file("/workspace/out.json", "./out.json")

box.terminate()
```

## What you can do with an instance

| area | calls |
| - | - |
| processes | `process.run_code(code)`, `process.exec(*cmd, cwd=, env=)`, `process.list_processes()`, `process.get_process(pid)`; each process has `.wait()`, `.kill()`, `.status()`, `.stdout`, `.stderr`, `.logs` |
| files | `fs.read_text` / `read_bytes` / `write_text` / `write_bytes`, `upload_file`, `download_file`, `list_files`, `stat_file`, `create_directory`, `delete_file`, `delete_directory`, `find_in_files(path, pattern)`, `replace_in_files(path, old, new)` |
| network | `expose_port(port)` returns a URL; `list_urls()`; `update_network_permissions(block_network=, allow_list=)` |
| lifetime | `update_ttl(seconds)`, `status()`, `poll()`, `wait()`, `terminate()` |
| snapshots | `snapshot_memory()` returns an id; `Sandbox.create_from_memory_snapshot(id)` restores a warm sandbox; `create_image_from_filesystem()` turns the current disk into a blueprint id you can reuse |
| reconnect | `Sandbox.connect(id)` picks up a running sandbox from another process |
| async | every object has `.aio()` for `await`-able equivalents |

## Network

By default a sandbox can reach the internet. `block_network=True` cuts all outbound traffic, and
`allow_list` cuts it except for the CIDR ranges you list, such as `["140.82.112.0/20"]`. Replies to
connections that come in through an exposed port always get through.

Some destinations are the platform's, not yours, and `allow_list` can't open them: the cloud's metadata
service (`169.254.169.254`), the ports of the machine your sandbox runs on, other containers on that machine,
and private network ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `100.64.0.0/10`). DNS and the
levers9 API stay reachable. The platform is turning this on in stages: where it's still in its observe phase,
such a connection goes through and is counted, so you may not see it blocked yet. If your code needs a
private service, ask the person who runs your levers9 deployment to add it to the allowed destinations.

## Isolation

On GPU machines, where sandboxes run under runc instead of gVisor, the platform can apply Docker's default
seccomp profile, hide the kernel files Docker hides under `/proc` and `/sys` and make the rest of them
read-only, and stop `setuid` programs from gaining privileges. What a deployment turns on is chosen per pool,
so ask the person who runs yours if a tool you use stops working. A sandbox that runs Docker keeps what Docker
needs.

## Docker inside

```python theme={null}
image = Blueprint(python_version="python3.11").with_docker()
box = Sandbox(image=image, docker_enabled=True).create()
box.docker.run("hello-world")
```

Docker inside a sandbox gives the container extra kernel capabilities, and only gVisor keeps those inside the
sandbox. So run Docker sandboxes without a GPU: a CPU sandbox lands on a gVisor pool. A GPU sandbox with
`docker_enabled=True` lands on a runc pool. Today that's allowed and logged; a platform admin can set
`worker.sandboxDockerRuntime: enforce`, and then such a sandbox is refused when it's created (unless a gVisor GPU
pool exists) and a Docker sandbox never lands on a runc pool.

## Parameters

Beyond the [common ones](https://levers9.mintlify.site/sdk/parameters.md): `keep_warm_seconds` (default 600), `sync_local_dir` (copy the
current directory in on creation), `block_network` / `allow_list` (CIDR ranges), `docker_enabled`, `ports`
(exposed at creation), and two choices worth making every time:

| parameter | what it decides | if you leave it out |
| - | - | - |
| `workspace_token` | whether code in the sandbox gets your workspace token as `LEVERS9_TOKEN`. With it, anything running inside can deploy, read your volumes and Maps, and stop your deployments. Pass `False` for code an LLM wrote or a customer uploaded; pass `True` (or your own token in `env`) when the code has to call levers9 itself | the token is passed, as before, and the SDK warns. A later release leaves it out unless you ask |
| `authorized` | whether exposed ports need the workspace token (`Authorization: Bearer <token>`) | ports are public, as before, and the SDK warns when you expose one. A browser can't send that header, so a preview a person opens in a browser needs `authorized=False` for now |

`workspace_token=False` takes effect once the controlplane you're on honours it; the hosted one does after its
next rollout. Until then the token is still passed.

Sandboxes appear under **Containers** in the dashboard while they run, with their output.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.