Skip to content
rivet-devPublic

About

Tiny, fast, Linux-compatible sandboxes. Powered by WebAssembly.

Topics

Resources

Stars

4.8k stars

Watchers

11 watching

Forks

Latest commit

 

History

458 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


agentOS

Tiny, fast, Linux-compatible sandboxes. Powered by WebAssembly.

92× faster cold starts, 47× less memory, 254× cheaper to run.
Each agent gets files, processes, shell, and networking in one lightweight OS.

Quickstart • Documentation • Changelog • Discord • X

Why agentOS

Powered by WebAssembly and V8 isolates, the same technology powering Chrome and Cloudflare Workers. Linux with POSIX files, processes, and networking.

  • Library, not extra infrastructure. Install agentOS from npm and run it inside the backend process you already operate.
  • WebAssembly + V8, not a microVM. V8 isolates run JavaScript while WebAssembly contains compiled tools inside the same compact runtime.
  • Direct function calls, not extra APIs. Connect agents to your application with ordinary JavaScript calls instead of another network service.
  • Scoped access, not exposed credentials. Bind trusted host functions without ever giving the agent your raw secrets.
  • One process, not a VM per agent. Many isolated agent operating systems share one compact runtime instead of duplicating a full microVM stack.
  • Runs anywhere, no nested virtualization. Deploy on standard Linux infrastructure without a hypervisor or nested virtualization.

Benchmarks

Metric agentOS Sandbox baseline Difference
Cold start, p50 4.8 ms 440 ms 92× faster
Cold start, p95 5.6 ms 950 ms 170× faster
Cold start, p99 6.1 ms 3,150 ms 516× faster
Memory, shell workload ~22 MB 1,024 MB 47× less
Cost per execution-second, shell workload $0.000000073 $0.000018 254× cheaper

See the benchmark details for methodology, or Performance to run the benchmarks yourself.

Quickstart

Library: agentOS runs as a VM inside your backend. Or hosted: your backend and frontend call an agentOS VM over HTTP.

Library Hosted
Runs Inside your process Durable instance on Rivet Cloud or self-hosted
Lifecycle Runs until dispose() or process exit Sleeps when idle unless a process is running
Clients Your backend Your backend, or browsers with a scoped JWT
Preview URLs None Expiring preview URLs

Library

Step 1: Install the library

npm install @rivet-dev/agentos-core

Step 2: Create a VM and use it

import { AgentOs } from "@rivet-dev/agentos-core";

// Boots a VM inside this process. It runs until dispose() or process exit.
const vm = await AgentOs.create();

try {
	// Bash
	const result = await vm.process.exec("echo hello && ls /home/agentos", {
		output: { capture: "all" },
	});
	console.log(result.stdout);

	// Filesystem
	await vm.filesystem.writeFile("/home/agentos/hello.txt", "Hello, world!");
	const file = await vm.filesystem.readFile("/home/agentos/hello.txt");

	// JavaScript
	await vm.javascript.execute("console.log(1 + 2)");

	// Python
	const answer = await vm.python.evaluate<number>("21 * 2");
} finally {
	await vm.dispose();
}

Step 3: Configure the VM

The filesystem is in memory by default. Pass options to AgentOs.create() to persist it, attach other filesystems, and lock the VM down.

import { resolve } from "node:path";
import { AgentOs } from "@rivet-dev/agentos-core";

const vm = await AgentOs.create({
	// Store the root filesystem in SQLite so files survive VM recreation.
	database: { type: "sqlite_file", path: resolve("agentos.sqlite") },
	rootFilesystem: { type: "native", plugin: { id: "chunked_sqlite", config: {} } },

	// Attach a host directory (read-only) and an S3 bucket.
	mounts: [
		{
			path: "/mnt/code",
			plugin: { id: "host_dir", config: { hostPath: "/path/to/repo" } },
			readOnly: true,
		},
		{
			path: "/mnt/data",
			plugin: { id: "chunked_s3", config: { bucket: "my-bucket", region: "us-east-1" } },
		},
	],

	// Environment variables for guest processes.
	environment: { NODE_ENV: "production" },

	// Deny network access except to one host.
	permissions: {
		network: {
			default: "deny",
			rules: [
				{
					mode: "allow",
					operations: ["*"],
					patterns: ["dns://api.example.com", "tcp://api.example.com:*"],
				},
			],
		},
	},

	// Cap processes and filesystem size.
	limits: { resources: { maxProcesses: 64, maxFilesystemBytes: 256 * 1024 * 1024 } },
});

See Filesystem, Persistence, Permissions, Resource Limits, and Host Functions.

Hosted

Step 1: Create a project

Create a project in the Rivet dashboard and choose agentOS as the product. Set RIVET_NAMESPACE and RIVET_TOKEN from the project. To run on your own infrastructure, see Self-Hosting.

Step 2: Install the client

npm install @rivet-dev/agentos

Step 3: Create a VM and use it

import { createAgentOsClient } from "@rivet-dev/agentos";

const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" });

// Creates the VM on first use and returns the same VM for the same key.
const vm = client.agentOS.getOrCreate(["my-vm"]);

const result = await vm.v1.process.run({
	command: "sh",
	args: ["-c", "echo hello && ls /home/agentos"],
	options: { captureStdio: true },
});
console.log(result.stdout);

await vm.v1.filesystem.writeFile({
	path: "/home/agentos/hello.txt",
	content: "Hello, world!",
});

// Start a server and expose it through an expiring preview URL.
await vm.v1.filesystem.writeFile({
	path: "/home/agentos/server.js",
	content: `require("node:http").createServer((req, res) => res.end("hello")).listen(3000);`,
});
await vm.v1.process.spawn({ command: "node", args: ["/home/agentos/server.js"] });
const preview = await vm.v1.network.preview.create({ port: 3000, ttlMs: 60 * 60 * 1_000 });

The client is optional. Every action is a plain HTTP call. Create the VM by key with your RIVET_TOKEN, then call POST /gateway/{vm_id}/action/v1.{group}.{action} with a token that can reach the VM.

Raw HTTP with curl
curl -X PUT "https://api.rivet.dev/actors?namespace=$RIVET_NAMESPACE" \
  -H "Authorization: Bearer $RIVET_TOKEN" \
  --json '{
    "name": "agentOS",
    "key": "my-vm",
    "runner_name_selector": "services",
    "crash_policy": "sleep"
  }'
# → { "actor": { "actor_id": "…" }, "created": true }

curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.process.run" \
  -H "x-rivet-token: $VM_TOKEN" \
  --json '{"args": [{
    "command": "sh",
    "args": ["-c", "echo hello"],
    "options": { "captureStdio": true }
  }]}'
# → { "output": { "status": { "exitCode": 0, … }, "stdout": "hello\n", "stderr": "" } }

Keep RIVET_TOKEN on your backend. To let a browser call one VM directly, issue it a JWT scoped to that VM.

Step 4: Configure the VM

Configuration is stored with the VM and versioned. Replace it with v1.config.set, then restart the VM so filesystem and software changes take effect.

const vm = client.agentOS.getOrCreate(["my-vm"]);

await vm.v1.config.set({
	config: {
		// Keep files across sleep and restarts, and mount durable storage at /data.
		filesystem: {
			root: { type: "durable" },
			mounts: [{ path: "/data", backend: { type: "durable" } }],
		},

		// Environment variables for guest processes.
		environment: { NODE_ENV: "production" },

		// Deny network access except to one host.
		permissions: {
			network: {
				default: "deny",
				rules: [
					{
						mode: "allow",
						operations: ["*"],
						patterns: ["dns://api.example.com", "tcp://api.example.com:*"],
					},
				],
			},
		},
	},
});

// Filesystem and software changes apply after a restart.
await vm.v1.vm.restart({});

See Persistence, Permissions, and the Hosted HTTP API for every config field.

Architecture

The library or the HTTP API connects to the agentOS sidecar process over stdio and a Unix socket. Its trusted kernel owns processes, the filesystem, networking, and permissions. Untrusted guest code runs in V8 isolates and WebAssembly and reaches the kernel only through syscalls.

The agentOS sidecar is a Rust process that runs separately from your application's process. The kernel and all guest code live in the sidecar, so untrusted code and its memory never enter your process. The library, @rivet-dev/agentos-core, starts and owns the sidecar from your backend and talks to it over stdio and a Unix socket. When hosted, you control the same sidecar over the HTTP API.

The sidecar's trusted kernel owns the process table, the virtual filesystem and its mounts, the socket table, and permissions and resource limits.

Untrusted guest code also runs inside the sidecar. JavaScript and TypeScript run in V8 isolates, and the shell, coreutils, and Python run as WebAssembly.

The entire kernel is virtualized. Every file, process, and network operation is a syscall into the kernel, so by default guest code can't reach host files, processes, environment variables, or the network. You opt in to host access with mounts, host functions, and network permissions. See Architecture for details.

API Overview

Library methods live under vm.<group>. Hosted actions live under vm.v1.<group>, or POST /gateway/{vm_id}/action/v1.<group>.<action> over HTTP. The table lists every method across both.

Group What it does Methods
vm Create, inspect, and stop VMs create, status, restart, dispose
config Stored, versioned VM configuration get, set, patch
process Run commands and manage child processes exec, execFile, run, spawn, get, list, tree, wait, signal, kill, writeStdin, closeStdin, resizePty, readOutput
terminal Interactive PTY sessions open, list, write, resize, readOutput, wait, close
filesystem Read, write, and list files; manage mounts readFile, writeFile, readFiles, writeFiles, stat, exists, mkdir, readdir, readdirEntries, readdirRecursive, move, remove, mount, unmount, listMounts, export
javascript Run Node.js code and npm execute, evaluate, executeFile, spawn, spawnFile, npm.install, npm.runScript, npm.runPackage
typescript Run and type-check TypeScript execute, evaluate, executeFile, spawn, spawnFile, check, checkProject
python Run Python code and pip execute, evaluate, executeFile, executeModule, spawn, spawnFile, spawnModule, install
contexts Persistent language execution contexts create, get, list, reset, delete
network Reach servers running in the VM httpRequest, fetch, fetchStream, preview.create, preview.expire
software Install .aospkg command packages install, uninstall, list, installed, link
cron Scheduled commands schedule, list, cancel

License

See LICENSE.

About

Tiny, fast, Linux-compatible sandboxes. Powered by WebAssembly.

Topics

Resources

Stars

4.8k stars

Watchers

11 watching

Forks

Releases

Used by

Contributors

Languages