agentOS (Embedded)
Give an agent a computer inside your own process: boot an agentOS VM with @rivet-dev/agentos-core in Node.js or a Rivet Actor, then run processes, read and write files, execute code, and reach its network as direct method calls.
Embedded agentOS is the same computer for one agent, with a filesystem, processes, terminals, networking, and a software registry, run as a library: @rivet-dev/agentos-core boots the VM inside your own Node.js process or Rivet Actor, your application owns its identity and lifecycle, and the same action groups are methods on the VM handle. This page is an overview of that API; the full agentOS docs cover every method, option, and limit.
Quickstart
Install the library
The package includes the native sidecar for your platform, so nothing else needs to be deployed.
npm install @rivet-dev/agentos-core
Boot a VM
AgentOs.create() boots a VM inside this process and returns a handle to it. The VM runs until you call dispose() or the process exits.
import { AgentOs } from "@rivet-dev/agentos-core";
const vm = await AgentOs.create();
Run a command
process.exec runs a shell command line to completion and returns its exit status and captured output.
try {
const result = await vm.process.exec("echo hello", {
output: { capture: "all" },
});
console.log(result.stdout); // "hello\n"
} finally {
await vm.dispose();
}
The sections below reuse vm from the quickstart. Library methods take positional arguments, so vm.filesystem.writeFile(path, content) is the same action a hosted VM exposes as v1.filesystem.writeFile({ path, content }).
Processes and shells
process.exec runs a shell command line and process.execFile runs a command with an argument array; process.spawn starts a long-running process and returns its pid for stdin, signals, waiting, and output callbacks. terminal.open allocates a PTY and starts an interactive shell.
const result = await vm.process.exec("ls -la /home/agentos");
console.log(result.stdout);
const { pid } = await vm.process.spawn("node", ["/tmp/server.mjs"]);
vm.onProcessOutput(pid, (event) =>
console.log(event.stream, new TextDecoder().decode(event.data)),
);
await vm.process.signal(pid, "SIGTERM");
Full docs: Processes & Shells and Bash.
Filesystem
The filesystem methods read and write the VM’s filesystem without starting a process, and every shell and language in the VM sees the same files. Batch, directory, and mount methods follow the same shape, and the library can also mount and unmount filesystems on a running VM.
await vm.filesystem.writeFile("/home/agentos/hello.txt", "Hello, world!");
const content = await vm.filesystem.readFile("/home/agentos/hello.txt");
console.log(new TextDecoder().decode(content));
Full docs: Filesystem.
Code execution
The javascript, typescript, and python methods run code on the VM’s native V8 and CPython 3.13: evaluate returns a JSON-serializable value, execute runs source and captures its output, and spawn starts a long-lived script.
const sum = await vm.javascript.evaluate<number>("1 + 2");
console.log(sum.outcome === "succeeded" ? sum.value : sum.error); // 3
const answer = await vm.python.evaluate<number>("21 * 2");
console.log(answer.outcome === "succeeded" ? answer.value : answer.error); // 42
await vm.javascript.execute("console.log(1 + 2)");
Full docs: Node.js and Python.
Network
Servers inside the VM listen on VM-local ports and are not exposed on the host network; network.httpRequest sends a bounded HTTP request to one and returns the buffered response. The library creates no public preview URLs, so route browser traffic through your application and forward it with httpRequest or vm.fetch.
await vm.filesystem.writeFile(
"/tmp/app.mjs",
'import http from "http"; http.createServer((req, res) => res.end("hello")).listen(3000);',
);
await vm.process.spawn("node", ["/tmp/app.mjs"]);
const response = await vm.network.httpRequest({ port: 3000, path: "/" });
console.log(new TextDecoder().decode(response.body));
Full docs: Networking & Previews.
Software
Software ships as immutable .aospkg packages. Because the embedding process is trusted, software.install accepts a registry package by name, an HTTPS URL with a digest, or a local path, while the VM is running or in the software option to AgentOs.create().
const installed = await vm.software.install({ type: "registry", name: "ripgrep" });
console.log(installed.packageName, installed.version, installed.commands);
const result = await vm.process.execFile("rg", ["--version"], {
output: { capture: "all" },
});
console.log(result.stdout);
Full docs: Software.
Schedules
cron.schedule runs a command or a host callback on a cron expression, or once at an ISO 8601 timestamp. Library jobs run while the embedding process and the VM are alive, so durable scheduling across restarts belongs to the application that owns the VM.
const job = vm.cron.schedule({
id: "cleanup",
schedule: "0 * * * *",
action: { type: "exec", command: "rm", args: ["-rf", "/tmp/cache"] },
});
console.log("Scheduled:", job.id);
console.log(vm.cron.list());
Full docs: Crons & Schedules.
Lifecycle and persistence
A library VM runs until dispose() is called or the process exits, and its root filesystem is in memory by default, so files are discarded when the VM is disposed. To keep them, give the VM a SQLite database and store the root filesystem there with the chunked_sqlite plugin; a new VM created with the same options sees the same files, while running processes, terminals, and language contexts do not survive recreation.
import { resolve } from "node:path";
import { AgentOs } from "@rivet-dev/agentos-core";
const vm = await AgentOs.create({
database: { type: "sqlite_file", path: resolve("agentos.sqlite") },
rootFilesystem: { type: "native", plugin: { id: "chunked_sqlite", config: {} } },
});
await vm.filesystem.writeFile("/home/agentos/result.txt", "persistent");
await vm.dispose();
Full docs: Persistence & Sleep and Embedded VMs.
Actions
The library exposes the same groups as namespaces on the VM handle (vm.filesystem, vm.process, vm.cron, …). Where a library method name differs from the hosted action, the capability page lists both: for example process.exec and process.execFile in place of run, and process.writeStdin in place of stdin.write.
| Group | Actions |
|---|---|
config | get, set, patch |
vm | status, restart |
filesystem | readFile, writeFile, readFiles, writeFiles, stat, exists, mkdir, readdir, readdirEntries, readdirRecursive, move, remove, listMounts, export |
process | run, spawn, get, list, tree, wait, signal, stdin.write, stdin.close, pty.resize, output.read |
terminal | open, list, stdin.write, pty.resize, output.read, wait, close |
network | fetch, fetchStream.start, fetchStream.read, fetchStream.cancel, preview.create, preview.expire |
software | install, uninstall, list |
cron | schedule, list, cancel |
contexts | create, get, list, reset, delete |
javascript | execute, evaluate, executeFile, spawn, spawnFile, npm.install, npm.runScript, npm.runPackage |
typescript | execute, evaluate, executeFile, spawn, spawnFile, check, checkProject |
python | execute, evaluate, executeFile, executeModule, spawn, spawnFile, spawnModule, install |
Every action, its input and output, configuration fields, events, and error codes are in the hosted API reference; the library adds host functions, host-directory mounts, and local packages on top.
Next steps
- Secure Code Execution: run agentOS inside a Rivet Actor so the Actor supplies identity and persistence.
- Embedded VMs: trusted host capabilities, mount plugins, and sidecar placement.
- Custom Host Functions: expose your own functions to guest code without leaking credentials into the VM.