Sandbox Mounting
For heavy workloads like browsers, desktop automation, and compilation, pair agentOS with a full sandbox on demand. Its filesystem mounts into the VM as a native directory, and its process management is exposed as bindings, all provider-agnostic through Sandbox Agent.
Why use agentOS with a sandbox?
Section titled “Why use agentOS with a sandbox?”agentOS is an alternative to sandboxes that covers most use cases, but some workloads need a full sandbox for special kinds of software (browsers, desktop automation, heavy compilation). Sandbox mounting lets you lazily start a sandbox on demand, only when it is needed, and project it into the VM. The hybrid model means one agent session can handle both lightweight coding tasks and heavy system operations, using the right tool for each.
See agentOS vs Sandbox for a detailed comparison.
When to use a sandbox
Section titled “When to use a sandbox”- Native binaries not yet supported in the agentOS runtime.
- Browsers and desktop automation: Playwright, Puppeteer, Selenium, or anything that needs a display server.
- Heavy compilation: Large builds or native toolchains that require a full Linux environment.
- GUI applications: Desktop apps, VNC sessions, or any workload that needs a graphical environment.
- Node.js packages with native extensions (e.g.
sharp,bcrypt,better-sqlite3) that require a full build toolchain.
Start with the default agentOS VM for all workloads, and only spin up a sandbox when a task genuinely requires one. Sandboxes are billed per second of uptime, so start them on demand and tear them down when the task is done.
Getting started
Section titled “Getting started”The sandbox integration ships as the @rivet-dev/agentos-sandbox package. It works through two mechanisms:
- Filesystem mount: Projects the sandbox into the VM as a native directory, like mounting a hard drive on your own machine. Read and write files through the mount directly.
- Bindings: Exposes sandbox process management as bindings. Execute commands on the sandbox from within the VM.
Both are powered by Sandbox Agent, and you can swap providers without changing agent code. Install both packages:
npm install @rivet-dev/agentos-sandbox sandbox-agentcreateSandboxFs and createSandboxBindings come from @rivet-dev/agentos-sandbox. SandboxAgent and the provider helpers (such as docker) come from the sandbox-agent package.
import { agentOS, setup } from "@rivet-dev/agentos";import { createSandboxFs, createSandboxBindings } from "@rivet-dev/agentos-sandbox";import { SandboxAgent } from "sandbox-agent";import { docker } from "sandbox-agent/docker";
// Start a sandbox through Sandbox Agent. Any provider works; Docker is used here.const sandbox = await SandboxAgent.start({ sandbox: docker() });
// `createSandboxFs` returns a mount plugin descriptor that projects the sandbox// filesystem into the VM, and `createSandboxBindings` exposes the sandbox's// process management as bindings.const vm = agentOS({ // Bindings let the agent control the sandbox bindings: [createSandboxBindings({ client: sandbox })], // Mounts let the agent read the sandbox filesystem (optional) mounts: [ { path: "/home/user/sandbox", plugin: createSandboxFs({ client: sandbox }) }, ],});
export const registry = setup({ use: { vm } });
registry.start();Calling the mounted bindings
Section titled “Calling the mounted bindings”Once the sandbox is mounted, write code through the filesystem and run it inside the sandbox. The sandbox bindings are exposed inside the VM as a CLI command, so you call it through the same exec/spawn surface as any other command.
import { createClient } from "@rivet-dev/agentos/client";import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });const vm = client.vm.getOrCreate("my-agent");
// Write code via the filesystem. The /home/user/sandbox mount maps to the sandbox root.await vm.writeFile("/home/user/sandbox/app/index.ts", 'console.log("hello")');
// Run it inside the sandbox. Commands execute through the VM's process table,// reading the file from the mounted directory.const result = await vm.exec("node /home/user/sandbox/app/index.ts");console.log(result.stdout); // "hello\n"
// Call a mounted binding from the client. The sandbox bindings are exposed inside the// VM as a CLI command, so you invoke it through the same exec/spawn surface.const install = await vm.exec("agentos-sandbox run-command --command \"npm install\" --cwd /home/user/sandbox/app");console.log(install.exitCode, install.stdout);
// Spawn a long-running process via the bindings and stream its output.const { pid } = await vm.spawn("agentos-sandbox", [ "create-process", "--command", "npm", "--args", "run", "--args", "dev",]);const conn = vm.connect();conn.on("processOutput", (payload) => { if (payload.pid === pid) { console.log(payload.stream, new TextDecoder().decode(payload.data)); }});Bindings reference
Section titled “Bindings reference”The bindings expose these commands inside the VM:
# Run a command synchronouslyagentos-sandbox run-command --command "npm install" --cwd "/app"
# Start a background processagentos-sandbox create-process --command "npm" --args "run" --args "dev"
# List running processesagentos-sandbox list-processes
# Get process outputagentos-sandbox get-process-logs --id "proc_abc123"
# Stop or kill a processagentos-sandbox stop-process --id "proc_abc123"agentos-sandbox kill-process --id "proc_abc123"
# Send input to an interactive processagentos-sandbox send-input --id "proc_abc123" --data "yes"Sandbox providers
Section titled “Sandbox providers”The extension works with any Sandbox Agent provider. See the Sandbox Agent documentation for available providers and setup instructions.