# Sandboxes (/docs/run/sandboxes)



A sandbox is given per session, not on the agent definition. The same agent
runs with or without one.

```ts
const session = await client.createSession({
  agentId: "analyst",
  ownerUserId,
  sandbox: {
    network: { allow: ["pypi.org", "files.pythonhosted.org"] },
    resources: { cpus: 2, memory: "2GiB" },
  },
});
```

`sandbox` takes:

| Value                    | Meaning                                              |
| ------------------------ | ---------------------------------------------------- |
| omitted                  | The Tenant default (`GET`/`PUT /v1/tenant/sandbox`). |
| `false`                  | No sandbox.                                          |
| `{ id }`                 | Attach a sandbox resource.                           |
| `{ network, resources }` | Inline spec, checked against Tenant limits.          |

A caller acting for a person (`client.as(...)`) cannot define an inline
sandbox; it gets the Tenant default or `false`. Private networks, loopback,
the host, and cloud metadata endpoints are always blocked.

## Built-in tools [#built-in-tools]

The model gets `bash`, `read`, `write`, `edit`, `grep`, and `glob` on a
persistent `/workspace`. These tools run in the Runtime, not in your app.

## Kinds [#kinds]

| Kind      | Behaviour                                                                                                                                                                         |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `virtual` | Default. An emulated shell inside the Runtime. Not an isolation boundary. No `image`.                                                                                             |
| `pod`     | Preview. A Kubernetes pod through agent-sandbox, after `npx nylorun sandbox enable --context <ctx>`. Takes `image`, `storage`, and `lifecycle.ttl`. Egress only to allowed hosts. |

```sh
npx nylorun sandbox enable --context <ctx>
npx nylorun sandbox status
npx nylorun sandbox ls
npx nylorun sandbox rm <id>
```

`npx @nylorun/cli doctor sandbox` reports the backend in use. The Runtime
itself still runs with Docker Compose; see [Docker Compose](/docs/deploy/vm).

## Resources [#resources]

```ts
await client.sandboxes.ensure("team-a/proj-42", { labels: { project: "acme" } });
await client.createSession({
  agentId: "analyst",
  ownerUserId,
  sandbox: { id: "team-a/proj-42" },
});

const { session, release } = await client.sandboxes.forSession({
  session: { agentId: "analyst", ownerUserId },
  spec: { network: { allow: ["pypi.org"] } },
});
```

Sessions attached to one sandbox share `/workspace`. One turn runs at a time:
a second session's turn is refused with `409 sandbox_busy`.
`client.sandboxes.list({ labels })`, `get(id)`, and `delete(id)` manage them.
Creating and deleting through `client.as()` needs `sandboxes:write`.

Sandbox lifecycle and exec events are `sandbox.*` on
[Events](/docs/run/events).

## Next step [#next-step]

<Cards>
  <Card title="Files" description="Upload files and export /workspace/outputs." href="/docs/run/files" />

  <Card title="Kubernetes" description="Run pod sandboxes on a cluster." href="/docs/deploy/kubernetes" />
</Cards>
