Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion docs/content/docs/sandboxes.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Sandboxes"
description: "Run an agent without a sandbox, or give it a shell in agentOS, E2B, Daytona, Freestyle, or a sandbox provider you write."
description: "Run an agent without a sandbox, or give it a shell in agentOS, E2B, Daytona, Freestyle, Docker, or a sandbox provider you write."
---

An agent doesn't need a sandbox. Without one, its file tools work on files in the Actor's own database. Add a sandbox only when the agent needs a shell.
Expand Down Expand Up @@ -83,6 +83,7 @@ agentOS needs no provider account. To use E2B or Daytona instead, see
| <a href="https://e2b.dev" target="_blank" rel="noopener noreferrer">E2B</a> | `e2b` | Paused | Deleted |
| <a href="https://daytona.io" target="_blank" rel="noopener noreferrer">Daytona</a> | `@daytonaio/sdk` | Stopped | Deleted |
| <a href="https://freestyle.sh" target="_blank" rel="noopener noreferrer">Freestyle</a> | `freestyle` | Paused | Deleted |
| <a href="https://docs.docker.com" target="_blank" rel="noopener noreferrer">Docker</a> | None. Uses the `docker` CLI. | Stopped | Removed |

Provider credentials stay on your worker and never enter the sandbox.

Expand Down Expand Up @@ -148,6 +149,28 @@ npm add @rivet-dev/sandbox-adapter freestyle

A Freestyle VM has no network access until a `firewall` rule allows it. Commands run as `root` through Python 3, so the image must include it. Every `freestyle/ubuntu*` snapshot does.

### Docker

For local development. The provider runs the `docker` CLI on your worker, so it uses the current Docker context.

```sh
npm add @rivet-dev/sandbox-adapter
```

<CodeSnippet file="examples/docs/sandboxes/docker.ts" title="server.ts" />

| Option | Description |
| --- | --- |
| `image` | Image to run. It must include `/bin/sh`. Defaults to `ubuntu:24.04`. |
| `cwd` | Working directory inside the container. Created when the Actor connects. Defaults to `/workspace`. |
| `env` | Environment variables of the container. |
| `network` | Docker network to join. Set `"none"` for no network access. Defaults to `bridge`. The `host` network is rejected. |
| `ports` | Container ports to publish on a random `127.0.0.1` port. Read the address with `dockerPortAddress(sandboxId, port)`. |
| `keepImageEntrypoint` | Runs the image's own entrypoint, for images such as `cloudflare/sandbox` that start a server. By default the container runs an idle process. |
| `docker` | Path of the Docker CLI. Defaults to `docker`. |

Each sandbox is one container with the label `dev.rivet.sandbox-adapter.sandbox-id`. The container has no host mounts, no host environment, no privileged mode, and no host network. A kill or timeout ends the command and every process it started.

## How the sandbox is managed

- The sandbox is created the first time the agent needs it.
Expand Down
19 changes: 19 additions & 0 deletions examples/docs/sandboxes/docker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createRegistry } from "@earendil-works/pi-durable";
import { CodingTools } from "@earendil-works/pi-durable/tools";
import { pi } from "@rivet-dev/pi";
import { dockerProvider } from "@rivet-dev/sandbox-adapter/docker";
import { setup } from "rivetkit";

// read, write, edit, and bash, running in a local Docker container
const extensions = createRegistry();
extensions.install(CodingTools);

const agent = pi({
model: "anthropic/claude-opus-5-5",
registry: extensions,
sandbox: dockerProvider({ image: "ubuntu:24.04" }),
});

export const registry = setup({ use: { agent } });

registry.start();
11 changes: 9 additions & 2 deletions packages/sandbox-adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"e2b",
"daytona",
"freestyle",
"docker",
"agent",
"ai",
"rivet",
Expand Down Expand Up @@ -45,6 +46,10 @@
"types": "./dist/daytona.d.ts",
"default": "./dist/daytona.js"
},
"./docker": {
"types": "./dist/docker.d.ts",
"default": "./dist/docker.js"
},
"./freestyle": {
"types": "./dist/freestyle.d.ts",
"default": "./dist/freestyle.js"
Expand All @@ -58,7 +63,8 @@
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc -p tsconfig.build.json",
"check-types": "tsc --noEmit"
"check-types": "tsc --noEmit",
"test": "vitest run"
},
"dependencies": {
"@earendil-works/chord": "^1.0.0",
Expand All @@ -85,7 +91,8 @@
"@types/node": "^24.0.0",
"e2b": "^2.51.0",
"freestyle": "^0.2.16",
"typescript": "^5.9.2"
"typescript": "^5.9.2",
"vitest": "3.2.7"
},
"engines": {
"node": ">=22.19.0"
Expand Down
Loading
Loading