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

# Sandboxes

> Run untrusted code behind a hardware boundary, with isolation you can dial up to airtight.

When an agent executes generated code, or you run something you pulled off the internet, you want the blast radius to end at a machine you can throw away. Every boxd machine is a KVM microVM with its own kernel, network stack, and disk. Code inside it has root over its own machine and no path to the host or to machines belonging to other tenants. The hypervisor boundary is the same one your laptop uses to run VMs.

<Frame caption="An isolated machine boots like any other, in milliseconds.">
  <video autoPlay muted loop playsInline src="https://mintcdn.com/azin/psRZbQh2QwMUVL3U/videos/isolated-machine-2.mp4?fit=max&auto=format&n=psRZbQh2QwMUVL3U&q=85&s=4796e5c21a41e5030b561ebc3a972cb7" data-path="videos/isolated-machine-2.mp4" />
</Frame>

<Frame caption="The console marks an isolated machine on its row.">
  <img src="https://mintcdn.com/azin/psRZbQh2QwMUVL3U/images/isolated-machine-row.png?fit=max&auto=format&n=psRZbQh2QwMUVL3U&q=85&s=9a9817b8b0b04ed31636ffc09a9071a7" alt="A machine row in the boxd console with an ISOLATED badge next to its running status" width="2364" height="174" data-path="images/isolated-machine-row.png" />
</Frame>

## A real machine as the sandbox

Containers share the host's kernel, which is exactly the surface untrusted code attacks. A microVM gives the workload a kernel of its own, so the sandbox can allow everything a Linux server allows. Code in the sandbox can run Docker, load kernel modules, restart `systemd`, edit `/etc`, open ports, and break the OS completely, and the damage stays inside that one machine.

The trade-off you'd expect, slow VM startup, is gone. A fresh machine boots in about 30ms and a [fork](/guides/fork) lands in about 160ms, so per-task sandboxes feel like function calls.

## One sandbox per task

Create a machine, run the untrusted work, destroy it:

<Tabs>
  <Tab title="CLI">
    ```bash theme={"theme":"github-dark"}
    boxd machine new task-1 --isolated
    boxd machine exec task-1 -- 'python3 generated_script.py'
    boxd machine remove task-1 -y
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"github-dark"}
    import { Boxd } from "@boxd-sh/sdk";

    const boxd = new Boxd();                    // reads BOXD_API_KEY
    const machine = await boxd.machines.create({ name: "task-1", isolated: true });
    await boxd.machines.waitUntilReady(machine.id);

    const result = await boxd.machines.exec(machine.id, {
      command: ["python3", "generated_script.py"],
    });
    console.log(result.stdout);

    await boxd.machines.delete(machine.id);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":"github-dark"}
    from boxd import Boxd

    boxd = Boxd()                          # reads BOXD_API_KEY
    machine = boxd.machines.create("task-1", isolated=True)
    boxd.machines.wait_until_ready(machine.id)

    result = boxd.machines.exec(machine.id, "python3 generated_script.py")
    print(result.stdout)

    boxd.machines.delete(machine.id)
    ```
  </Tab>
</Tabs>

For longer sessions, keep the sandbox and let it sleep between uses. A suspended machine resumes in sub-millisecond time with its filesystem and processes intact. See [Suspend, resume, and hibernate](/guides/suspend-resume).

## Fleets for automation

Sandboxes are highly suitable for automation: background jobs, runners, test matrices, agent fleets, and [RL rollouts](/use-cases/reproducible-rl-environments) all want many disposable environments at once. Create them concurrently, and every one is hardware isolated from the others and from the rest of your machines:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":"github-dark"}
    import { Boxd } from "@boxd-sh/sdk";

    const boxd = new Boxd();   // reads BOXD_API_KEY

    const names = Array.from({ length: 15 }, (_, i) => `sandbox-${i + 1}`);

    const machines = await Promise.all(
      names.map(async (name) => {
        const machine = await boxd.machines.create({ name, isolated: true });
        await boxd.machines.waitUntilReady(machine.id);
        return machine;
      })
    );

    console.log(`${machines.length} isolated sandboxes up`);
    await boxd.close();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"theme":"github-dark"}
    from concurrent.futures import ThreadPoolExecutor
    from boxd import Boxd

    boxd = Boxd()   # reads BOXD_API_KEY

    def sandbox(i: int):
        machine = boxd.machines.create(f"sandbox-{i}", isolated=True)
        boxd.machines.wait_until_ready(machine.id)
        return machine

    with ThreadPoolExecutor(max_workers=15) as pool:
        machines = list(pool.map(sandbox, range(1, 16)))

    print(f"{len(machines)} isolated sandboxes up")
    ```
  </Tab>
</Tabs>

These boot the default Ubuntu image. To start every sandbox with your own toolchain, dependencies, and services already in place, create them from a [snapshot](/guides/snapshots) instead, with `fromSnapshot: "my-toolchain"` / `from_snapshot="my-toolchain"` alongside the same `isolated` flag. Either way each machine lands in tens of milliseconds, so the fleet is up in seconds.

Disposable is one mode, and persistent is the other. In contrast to other sandbox providers, boxd machines are natively persistent. A sandbox lives as long as you keep it, disk and all, which is exactly what a multi-tenant product wants: one long-lived isolated machine per customer. See [Agentic SaaS](/use-cases/agentic-saas).

<Note>
  Accounts start with a cap of 50 concurrent machines, so this fleet fits with room to spare. Need more? Raises for real workloads are usually same-day via [contact@boxd.sh](mailto:contact@boxd.sh). See [Resources and limits](/guides/resources).
</Note>

## Cut off from your fleet by design

Normally, machines you own share one private network, and each carries a pre-authenticated in-VM `boxd` CLI. That is convenient for your own machines and exactly wrong for a sandbox, because code in the sandbox could reach your other VMs.

A sandbox created with `--isolated` is cut off from all of that from birth. boxd strips everything that could reach into the rest of your account: the in-VM `boxd` CLI, your connected integrations, your saved coding-agent logins, and the bridge to your laptop are all left out of it. It never joins the default network and never reaches another isolated machine. What it keeps is outbound internet, its public HTTPS domain, inbound SSH, and its persistent disk, so it is a normal machine to work in that simply cannot see or act on anything else you own.

When a sandbox does need a controlled path to something of yours, a job queue or a shared database for example, grant it one explicitly with [tag-based networks](/guides/vm-to-vm#tag-based-networks). An isolated machine reaches exactly the non-isolated machines it shares a named network with, and networking changes apply in real time, without a reboot:

```bash theme={"theme":"github-dark"}
boxd machine networks scratch jobs     # grant access to machines on `jobs`, effective immediately
boxd machine networks scratch --clear  # cut it off again
```

<Note>
  `--isolated` is set at creation and cannot be changed afterward. Forks and snapshot restores inherit it, so an isolated lineage stays isolated.
</Note>

## FAQ

<AccordionGroup>
  <Accordion title="What stops code from breaking out of the sandbox?">
    The microVM boundary. Code has root inside its own VM and no path to the host or to other machines. Internet egress is the only shared surface, and `--isolated` removes the paths into your own fleet as well.
  </Accordion>

  <Accordion title="How many sandboxes can I run at once?">
    As many as you want. Accounts start at 50 concurrent machines, and you can request an extension beyond that, usually granted same-day. See [Resources and limits](/guides/resources).
  </Accordion>

  <Accordion title="Can sandboxed code run Docker?">
    Yes. The machine has a real kernel and a real `systemd`, so Docker works without nesting tricks. See [Run Docker](/guides/run-docker).
  </Accordion>
</AccordionGroup>
