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

# Lifecycle

> Sandbox states, creation, suspend/resume, and cleanup

## Overview

Sandboxes come in two flavors:

* **Ephemeral** — no name. Runs until you terminate it or it times out. Cannot be suspended.
* **Named** — a name given at creation (or assigned later). Supports suspend and resume, so you can pause between tasks and pick up exactly where you left off.

|                      | Ephemeral                            | Named                                    |
| -------------------- | ------------------------------------ | ---------------------------------------- |
| **Created with**     | `tl sbx create`                      | `tl sbx create <name>`                   |
| **Suspend / Resume** | Not supported                        | Supported                                |
| **Reference by**     | ID only                              | ID **or** name                           |
| **Use when**         | Short-lived tasks, one-off execution | Multi-step work, persistent environments |

## Lifecycle states

Every sandbox moves through the states below. Create starts the sandbox in `Pending`; from `Running`, you can suspend (named only), snapshot, or terminate. Ephemeral sandboxes follow the same flow but skip `Suspending`/`Suspended`.

```mermaid theme={null}
stateDiagram-v2
    [*] --> Pending: • create<br/>• restore from snapshot
    Pending --> Running
    
    Running --> Snapshotting: snapshot
    Snapshotting --> Running: snapshot complete
    
    Running --> Suspending: named sandbox <br/>• suspend<br/>• timeout
    Suspending --> Suspended
    Suspended --> Running: resume
    
    Running --> Terminated: • terminate<br/>• timeout (ephemeral)
    Suspended --> Terminated: terminate
    
    Terminated --> [*]

    style Suspending fill:#E8F4FF,stroke:#1D70B8,color:#0B3C6F,stroke-width:2px
    style Suspended fill:#E8F4FF,stroke:#1D70B8,color:#0B3C6F,stroke-width:2px
```

| State            | What it means                                                                                                           | How you exit it                                                 |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| **Pending**      | Sandbox is being scheduled and booted. Not yet ready to accept commands.                                                | Transitions to `Running` automatically once boot completes.     |
| **Running**      | Sandbox is live and accepting commands, file operations, and process execution. Snapshots can be taken from this state. | Call `suspend` (named only) or `terminate`.                     |
| **Snapshotting** | A reusable snapshot artifact is being captured from the sandbox's filesystem, memory, and running processes.            | Returns to `Running` when capture completes.                    |
| **Suspending**   | Named sandbox is being paused in place. Triggered by manual suspend or by `timeout_secs` elapsing.                      | Transitions to `Suspended` automatically.                       |
| **Suspended**    | Named sandbox is paused. Consumes no compute; state is preserved for resume under the same sandbox ID.                  | Call `resume` to return to `Running`, or `terminate` to end it. |
| **Terminated**   | Sandbox has stopped — manually, or via timeout for ephemeral sandboxes. Final state; cannot be reversed.                | —                                                               |

## Suspend vs. snapshot

Suspend and snapshot both preserve sandbox state, but they serve different purposes:

* **Suspend** pauses *this* sandbox so you can resume it later under the same ID.
* **Snapshot** captures a reusable artifact you can restore into a *new* sandbox.

Suspend/resume is covered on this page; see [Snapshots](/sandboxes/snapshots) for save-and-restore.

### When should I use what?

| Scenario                        | Use Suspend | Use Snapshot |
| ------------------------------- | ----------- | ------------ |
| Pause and resume later          | ✅           | ❌            |
| Save cost when idle             | ✅           | ❌            |
| Keep agent memory alive         | ✅           | ❌            |
| Retry from a checkpoint         | ❌           | ✅            |
| Run experiments from same state | ❌           | ✅            |
| Clone environment               | ❌           | ✅            |

## Create a sandbox

Create an ephemeral sandbox by calling create with no name. Add a name to make the sandbox persistent and eligible for suspend/resume.

You can also boot a sandbox from an existing snapshot to restore a previously captured filesystem, memory, and running processes. See [Restoring from a snapshot](/sandboxes/snapshots#restoring-from-a-snapshot) for details.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Ephemeral — runs until terminated or timed out
    tl sbx create

    # Named — can be suspended and resumed
    tl sbx create my-env
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import Sandbox


    # Ephemeral sandbox — no name, cannot be suspended
    ephemeral = Sandbox.create()

    # Named sandbox — can be suspended and resumed
    named = Sandbox.create(name="my-env")

    print(f"Sandbox ID: {named.sandbox_id}")
    print(f"Status: {named.status}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    // Ephemeral sandbox — no name, cannot be suspended
    const ephemeral = await Sandbox.create();

    // Named sandbox — can be suspended and resumed
    const named = await Sandbox.create({ name: "my-env" });

    console.log(named.sandboxId, named.status);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Ephemeral
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{}'

    # Named
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name": "my-env"}'
    ```
  </Tab>
</Tabs>

### Resources

Configure CPU, memory, and disk size per sandbox. These are fixed when the sandbox is created and cannot be changed afterwards — create a new sandbox if you need different resources.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    tl sbx create --cpus 2.0 --memory 2048 --disk_mb 25600
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create(
        cpus=2.0,
        memory_mb=2048,
        disk_mb=25600,
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.create({
      cpus: 2.0,
      memoryMb: 2048,
      diskMb: 25600,
    });
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "resources": {
          "cpus": 2.0,
          "memory_mb": 2048,
          "disk_mb": 25600
        }
      }'
    ```
  </Tab>
</Tabs>

| Parameter   | Type    | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------- | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cpus`      | `float` | `1.0`   | Number of CPUs to allocate                                                                                                                                                                                                                                                                                                                                                                                  |
| `memory_mb` | `int`   | `1024`  | Memory in megabytes. Must be between 1024–8192 MB per CPU core.                                                                                                                                                                                                                                                                                                                                             |
| `disk_mb`   | `int`   | `10240` | Root filesystem size in MiB. Defaults to 10240 (10 GiB) when omitted. Must be between 10240 and 102400 (10–100 GiB). The CLI accepts `--disk_mb` in MiB. Accepted for fresh creates. With `image`, `disk_mb` can be used to grow the root disk at create time (growth-only). With `snapshot_id` from a filesystem snapshot, `disk_mb` can also be used to grow the root disk at restore time (growth-only). |

### Timeout

Set a timeout to automatically stop a sandbox that runs too long. The behavior depends on the sandbox type:

* **Named sandboxes** — timeout triggers a suspend, preserving state for later resume.
* **Ephemeral sandboxes** — timeout triggers termination (final state).

If `timeout_secs` is not set, it goes with the default value which is `600` sec (10 minutes).

The maximum allowed `timeout_secs` depends on your plan: **1 hour** on Free (unverified), **2 hours** on Free (verified), and **24 hours** on On-Demand (pay-as-you-go). Setting `timeout_secs=0` requests the plan maximum. See [tensorlake.ai/pricing](https://www.tensorlake.ai/pricing) for higher limits on committed plans.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    tl sbx create --timeout 300
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create(timeout_secs=300)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.create({ timeoutSecs: 300 });
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"timeout_secs": 300}'
    ```
  </Tab>
</Tabs>

### Secrets

Inject secrets into the sandbox at creation. Secrets must be pre-configured in your Tensorlake account with `tl secrets set OPENAI_API_KEY=<your-key>`.

<Tabs>
  <Tab title="CLI">
    Not supported in the CLI.
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create(
        secret_names=["OPENAI_API_KEY", "DATABASE_URL"]
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    Use the HTTP API for secret injection.
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "secret_names": ["OPENAI_API_KEY", "DATABASE_URL"]
      }'
    ```
  </Tab>
</Tabs>

### Runtime environment

Sandboxes run on Tensorlake's managed Ubuntu 24.04 environment by default. If you need reusable setup or preinstalled dependencies, create a [Sandbox Image](/sandboxes/images) and launch sandboxes with `--image`. For one-off startup setup, create the sandbox and then use [command execution](/sandboxes/commands) to run those steps explicitly.

## Name and reference a sandbox

You can assign or update a sandbox's name after it is created. This is how you convert an ephemeral sandbox into a named one so it becomes eligible for suspend and resume.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Assign a name to a running sandbox
    tl sbx name <sandbox-id> my-env

    # Change an existing name
    tl sbx name my-env new-name
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import Sandbox
    sandbox = Sandbox.create()
    named_sbx = sandbox.update(name="my-env")
    print(named_sbx.name)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Sandbox } from "tensorlake";

    const sandbox = await Sandbox.create();
    const named_sbx = await sandbox.update({ name: "my-env" });
    console.log(named_sbx.name);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X PATCH https://api.tensorlake.ai/sandboxes/<sandbox-id> \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name": "my-env"}'
    ```
  </Tab>
</Tabs>

Once a sandbox has a name, you can use either the name or the UUID anywhere a sandbox identifier is accepted. Use `connect` to get an operable handle from either identifier.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # All of these work with either the ID or the name
    tl sbx exec my-env python main.py
    tl sbx ssh my-env
    tl sbx cp ./file.py my-env:/workspace/file.py
    tl sbx suspend my-env
    tl sbx resume my-env
    tl sbx terminate my-env
    tl sbx checkpoint my-env
    tl sbx name my-env new-name
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    info = Sandbox.connect("my-env")
    print(info.status)

    sandbox = Sandbox.connect(identifier="my-env")
    print(sandbox.sandbox_id)  # server UUID, e.g. "s7jus08qec4axzgbpq76h"
    print(sandbox.name)        # "my-env"

    result = sandbox.run("python", ["main.py"])
    print(result.stdout)

    renamed = sandbox.update(name= "new-name")
    print(renamed.name)

    sandbox.terminate()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const info = await Sandbox.connect("my-env");
    console.log(info.status);

    const sandbox = Sandbox.connect("my-env");
    console.log(sandbox.sandboxId); // server UUID
    console.log(sandbox.name);      // "my-env"

    const result = await sandbox.run("python", { args: ["main.py"] });
    console.log(result.stdout);

    await sandbox.update({ name: "new-name" });
    await sandbox.terminate();
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl https://api.tensorlake.ai/sandboxes/my-env \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

<Note>
  Authenticated requests can use either the sandbox ID or sandbox name. Unauthenticated proxy requests can also use sandbox names for exposed user ports when `allow_unauthenticated_access` is enabled. The management URL on port `9501` still requires authentication.
</Note>

## Inspect and list

Use `get` to check a single sandbox's status and configuration, or `list` to see all sandboxes in your namespace.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # List active sandboxes
    tl sbx ls

    # Running sandboxes only
    tl sbx ls --running

    # Include all sandboxes regardless of state
    tl sbx ls --all
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import Sandbox

    # Connect returns a Sandbox handle (not SandboxInfo)
    sandbox = Sandbox.connect("my-env")
    print(sandbox.status)          # property — fetches fresh from server
    print(sandbox.name)
    print(sandbox.sandbox_id)

    # Get the full metadata (image, resources, timeouts, etc.)
    info = sandbox.info()
    print(info.image)
    print(f"{info.resources.cpus} CPUs, {info.resources.memory_mb} MB RAM")

    # List all sandboxes in the namespace
    for sb in Sandbox.list():
        print(f"{sb.sandbox_id}: {sb.status}") 
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Sandbox } from "tensorlake";

    // Connect returns a Sandbox handle (not SandboxInfo)
    const sandbox = await Sandbox.connect("my-env");
    console.log(await sandbox.status());   // status is an async method in TS
    console.log(sandbox.name);              // name is a getter
    console.log(sandbox.sandboxId);
                    
    // Get the full metadata (image, resources, timeouts, etc.)
    const info = await sandbox.info();
    console.log(info.image, info.resources.cpus, info.resources.memoryMb);

    // List all sandboxes in the namespace
    const sandboxes = await Sandbox.list();
    for (const sb of sandboxes) {                                                                                               
      console.log(`${sb.sandboxId}: ${sb.status}`);
    } 
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Get one sandbox (by name or ID)
    curl https://api.tensorlake.ai/sandboxes/my-env \
      -H "Authorization: Bearer $TL_API_KEY"

    # List all sandboxes
    curl https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

## Suspend and resume

Suspend a running named sandbox to pause it in place, then resume the same sandbox later exactly where it left off. Suspend and resume do not create a reusable artifact — for that, use [Snapshots](/sandboxes/snapshots). Ephemeral sandboxes cannot be suspended — suspend calls on them return an error.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Suspend a named sandbox (by name or ID)
    tl sbx suspend my-env

    # Resume it later
    tl sbx resume my-env
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox.suspend()
    sandbox.resume()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.suspend();
    await sandbox.resume();
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://api.tensorlake.ai/sandboxes/my-env/suspend \
      -H "Authorization: Bearer $TL_API_KEY"

    curl -X POST https://api.tensorlake.ai/sandboxes/my-env/resume \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

## Terminate

Terminate a sandbox when the work is done. `Terminated` is a final state and cannot be reversed. Sandboxes with `timeout_secs` set also terminate automatically once the timeout elapses.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    tl sbx terminate my-env
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox.terminate()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.terminate();
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X DELETE https://api.tensorlake.ai/sandboxes/my-env \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

## End-to-end example

If you want a single example that creates a sandbox, inspects it, lists sandboxes, and cleans up when finished, use one of the sessions below.

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Create an ephemeral sandbox (no name — cannot be suspended)
    tl sbx create --cpus 1.0 --memory 1024 --timeout 300

    # Create a named sandbox (can be suspended and resumed)
    tl sbx create my-env --cpus 1.0 --memory 1024 --timeout 300

    # Check status or list sandboxes
    tl sbx ls
    tl sbx ls --all

    # Terminate the sandbox when you are done (by name or ID)
    tl sbx terminate my-env
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import Sandbox

    # Ephemeral sandbox — no name, cannot be suspended
    ephemeral = Sandbox.create(
        cpus=1.0,
        memory_mb=1024,
        disk_mb=10240,
        timeout_secs=300,
    )

    # Named sandbox — can be suspended and resumed
    named = Sandbox.create(
        name="my-env",
        cpus=1.0,
        memory_mb=1024,
        disk_mb=10240,
        timeout_secs=300,
    )

    print(f"Sandbox ID: {named.sandbox_id}")
    print(f"Status: {named.status}")

    # Get the full metadata (image, resources, timeouts, etc.)
    info = sandbox.info()
    print(f"Image: {info.image}")
    print(f"Resources: {info.resources.cpus} CPUs, {info.resources.memory_mb} MB RAM")

    sandboxes = Sandbox.list()
    for sb in sandboxes:
        print(f"{sb.sandbox_id}: {sb.status}")

    sandbox.terminate()
    print("Sandboxes terminated")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Sandbox } from "tensorlake";
    const ephemeral = await Sandbox.create({
      cpus: 1.0,
      memoryMb: 1024,
      diskMb: 10240,
      timeoutSecs: 300,
    });

    const named = await Sandbox.create({
      name: "my-env",
      cpus: 1.0,
      memoryMb: 1024,
      diskMb: 10240,
      timeoutSecs: 300,
    });

    console.log(named.sandboxId, named.status);

    # Get the full metadata (image, resources, timeouts, etc.)
    const info = await sandbox.info();
    console.log(info.image, info.resources.cpus, info.resources.memoryMb);

    const sandboxes = await Sandbox.list();
    for (const sandbox of sandboxes) {
      console.log(`${sandbox.sandboxId}: ${sandbox.status}`);
    }

    await sandbox.terminate();
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Create an ephemeral sandbox
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "resources": {"cpus": 1.0, "memory_mb": 1024},
        "timeout_secs": 300
      }'

    # Create a named sandbox (supports suspend/resume)
    curl -X POST https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "my-env",
        "resources": {"cpus": 1.0, "memory_mb": 1024},
        "timeout_secs": 300
      }'

    # Get one sandbox
    curl https://api.tensorlake.ai/sandboxes/<sandbox-id> \
      -H "Authorization: Bearer $TL_API_KEY"

    # List all sandboxes
    curl https://api.tensorlake.ai/sandboxes \
      -H "Authorization: Bearer $TL_API_KEY"

    # Delete
    curl -X DELETE https://api.tensorlake.ai/sandboxes/<sandbox-id> \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

## Sandbox object reference

### Sandbox

The `Sandbox` object returned by `Sandbox.create()` and `Sandbox.connect()` exposes the following properties. Both are resolved from the server on first access and cached for the lifetime of the object.

| Property (Python) | Property (TypeScript) | Type          | Description                                                                            |
| ----------------- | --------------------- | ------------- | -------------------------------------------------------------------------------------- |
| `sandbox_id`      | `sandboxId`           | `str`         | Server-assigned UUID. Always a UUID, never a name, even if you connected using a name. |
| `name`            | `name`                | `str \| None` | Human-readable name, or `None` for ephemeral sandboxes.                                |

```python theme={null}
sandbox = Sandbox.connect(identifier="my-env")
print(sandbox.sandbox_id)  # "s7jus08qec4axzgbpq76h"  ← UUID
print(sandbox.name)        # "my-env"                  ← name
```

### SandboxInfo

The `SandboxInfo` object returned by `Sandbox.info()` and `Sandbox.list()` contains:

| Field           | Type                     | Description                                            |
| --------------- | ------------------------ | ------------------------------------------------------ |
| `sandbox_id`    | `str`                    | Unique sandbox identifier                              |
| `name`          | `str \| None`            | Name of the sandbox, or `None` for ephemeral sandboxes |
| `namespace`     | `str`                    | Namespace the sandbox belongs to                       |
| `status`        | `str`                    | Current lifecycle state                                |
| `image`         | `str`                    | Container image used                                   |
| `resources`     | `ContainerResourcesInfo` | CPU and memory allocation                              |
| `secret_names`  | `list[str]`              | Injected secret names                                  |
| `timeout_secs`  | `int`                    | Timeout in seconds                                     |
| `entrypoint`    | `list[str]`              | Custom entrypoint command                              |
| `created_at`    | `datetime \| None`       | Creation timestamp                                     |
| `terminated_at` | `datetime \| None`       | Termination timestamp                                  |

## Learn more

<CardGroup cols={3}>
  <Card title="Snapshots" icon="camera" href="/sandboxes/snapshots">
    Save and restore sandbox filesystem, memory, and running processes.
  </Card>

  <Card title="Networking" icon="globe" href="/sandboxes/networking">
    Control internet access and blocked destinations.
  </Card>
</CardGroup>
