Sandboxes
Run an agent's file and shell tools in agentOS, E2B, Daytona, or a sandbox provider you write.
An agent’s file and shell tools run in a sandbox, not on your worker. The Quickstart agent uses agentOS. @rivet-dev/sandbox-adapter connects an agent to one. Each Actor gets its own sandbox, created on first start and reconnected every time the Actor wakes.
Quickstart
Install the adapter
npm add @rivet-dev/sandbox-adapter
Pass a provider
import { pi } from "@rivet-dev/pi";
import { agentOSProvider } from "@rivet-dev/sandbox-adapter/agentos";
import { setup } from "rivetkit";
const agent = pi({
model: "anthropic/claude-opus-5-5",
sandbox: agentOSProvider(),
});
export const registry = setup({ use: { agent } });
registry.start();
Without a sandbox, Pi’s built-in file and shell tools are turned off and the agent only has the customTools you pass.
Providers
| Provider | SDK | While the Actor sleeps | When the Actor is destroyed |
|---|---|---|---|
| agentOS | None | Sleeps on its own | Left in place |
| E2B | e2b | Paused | Deleted |
| Daytona | @daytonaio/sdk | Stopped | Deleted |
Install the provider’s SDK next to the adapter. Its credentials stay on your worker and never enter the sandbox.
agentOS
agentOS is hosted by Rivet, so there is no SDK to install and nothing else to add to the registry. The working directory is /workspace.
import { pi } from "@rivet-dev/pi";
import { agentOSProvider } from "@rivet-dev/sandbox-adapter/agentos";
import { setup } from "rivetkit";
const agent = pi({
model: "anthropic/claude-opus-5-5",
sandbox: agentOSProvider(),
});
export const registry = setup({ use: { agent } });
registry.start();
| Option | Description |
|---|---|
software | Extra packages to install, as { url, digest }. digest is optional. The VM already includes coreutils, which provides sh and the basic commands. |
cwd | Working directory inside the VM. Defaults to /workspace. |
E2B
npm add e2b
import { pi } from "@rivet-dev/pi";
import { e2bProvider } from "@rivet-dev/sandbox-adapter/e2b";
import { setup } from "rivetkit";
const agent = pi({
model: "anthropic/claude-opus-5-5",
sandbox: e2bProvider({ template: "base" }),
});
export const registry = setup({ use: { agent } });
registry.start();
| Option | Description |
|---|---|
template | Template name or id. Defaults to base. |
create | Options for E2B’s Sandbox.create. The API key defaults to E2B_API_KEY. |
cwd | Working directory inside the sandbox. Defaults to /home/user. |
E2B ends a sandbox when its timeout runs out, so the provider creates sandboxes that pause on timeout and resume on the next call.
Daytona
npm add @daytonaio/sdk
import { pi } from "@rivet-dev/pi";
import { daytonaProvider } from "@rivet-dev/sandbox-adapter/daytona";
import { setup } from "rivetkit";
const agent = pi({
model: "anthropic/claude-opus-5-5",
sandbox: daytonaProvider(),
});
export const registry = setup({ use: { agent } });
registry.start();
| Option | Description |
|---|---|
client | A Daytona client. Defaults to new Daytona(), which reads DAYTONA_API_KEY. |
create | Options for Daytona’s create. |
The working directory is the sandbox’s own working directory. A stopped sandbox is started again when the Actor wakes.
How the sandbox is managed
- The sandbox is created the first time the agent needs it.
- On wake, the Actor reconnects to the same sandbox. If it no longer exists, a new one is created and the old files are lost.
- An existing Actor cannot switch to a different provider.
- Commands run with the sandbox’s environment, not your worker’s. File tools reject paths outside the working directory, but shell commands can reach anything inside the sandbox.
Write your own provider
Any sandbox can back an agent. Implement SandboxProvider and pass it as sandbox. One provider object is shared by every Actor of a definition, so keep no per-Actor state in it; the Actor stores the sandbox id.
| Member | Description |
|---|---|
name | Stored next to the sandbox id, so a changed provider is detected on wake. |
create(c) | Provisions a new sandbox and returns its id. |
connect(c, id) | Connects to an existing sandbox and returns a Sandbox. Returns undefined when the sandbox no longer exists. |
suspend(c, id) | Optional. Releases resources while the Actor sleeps. When omitted, the sandbox stops itself when idle or keeps running, depending on the provider. |
destroy(c, id) | Optional. Deletes the sandbox when the Actor is destroyed. When omitted, the sandbox is left in place. |
The Sandbox that connect returns has a cwd and the operations the tools run: exec, readFile, writeFile, mkdir, stat, readdir, and exists. All paths are absolute paths inside the sandbox. See the E2B provider for a complete example.
Next: API Keys, how the agent gets model access.