Skip to main content

agentOS (Hosted)

Give an agent a computer over HTTP: create a hosted agentOS VM by key through the Rivet gateway, then run processes, read and write files, execute code, and fetch the network from any language or the TypeScript client.

Every hosted agentOS VM is one agentOS Rivet Actor: a computer for one agent with a persistent filesystem, processes, terminals, networking, and a software registry, created by key and driven over HTTP through the Rivet gateway from any language, or through the @rivet-dev/agentos TypeScript client that is generated from the same contract. This page is an overview of that API; the full agentOS docs cover every action, option, and limit.

Quickstart

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 control plane instead, see self-hosting agentOS.

The TypeScript client is optional; every action is also a plain HTTP call.

npm install @rivet-dev/agentos

Create a VM

The returned actor_id is the VM ID used in every action path. A second request with the same key returns the existing VM.

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 }

Run a command

Every public action is versioned under v1 at POST /gateway/{vm_id}/action/v1.{group}.{action}. Send the action’s input as the single element of args; the result comes back as output.

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": "" } }

The TypeScript client does the same with getOrCreate and a typed method per action, so vm.v1.process.run({ … }) is the call above.

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"],
	options: { captureStdio: true },
});
console.log(result.stdout);

The sections below reuse vm from the quickstart. Each method maps to the HTTP action of the same name, so vm.v1.filesystem.writeFile is v1.filesystem.writeFile in the path.

Processes and shells

process.run runs a command to completion; process.spawn starts a long-running one and returns a { generation, pid } handle for stdin, signals, waiting, and output replay. terminal.open allocates a PTY and starts an interactive shell.

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

const server = await vm.v1.process.spawn({ command: "node", args: ["/tmp/server.mjs"] });
await vm.v1.process.signal({ process: server, signal: "SIGTERM" });

Full docs: Processes & Shells and Bash.

Filesystem

The filesystem group reads and writes the VM’s filesystem without starting a process, and every shell and language in the VM sees the same files. Batch, directory, and mount actions follow the same shape.

await vm.v1.filesystem.writeFile({
	path: "/home/agentos/hello.txt",
	content: "Hello, world!",
});
const content = await vm.v1.filesystem.readFile({ path: "/home/agentos/hello.txt" });
console.log(new TextDecoder().decode(content));

Full docs: Filesystem.

Code execution

The javascript, typescript, and python groups 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.v1.javascript.evaluate({ expression: "1 + 2" });
console.log(sum.value); // 3

const answer = await vm.v1.python.evaluate({ expression: "21 * 2" });
console.log(answer.value); // 42

await vm.v1.python.execute({ source: `print("hello from agentOS")` });

Full docs: Node.js and Python.

Network

Servers inside the VM listen on VM-local ports; network.fetch sends a bounded HTTP request to one and returns the buffered response. network.preview.create exposes a port through an expiring, signed preview URL, which is a hosted-only feature.

await vm.v1.process.spawn({ command: "node", args: ["/tmp/app.mjs"] });

const response = await vm.v1.network.fetch({
	request: { port: 3000, path: "/", method: "GET", headers: {} },
});
console.log(response.status);

const preview = await vm.v1.network.preview.create({ port: 3000, ttlMs: 60 * 60 * 1_000 });
console.log(preview.path);

Full docs: Networking & Previews.

Software

Software ships as immutable .aospkg packages. A hosted VM installs one from an HTTPS URL and sha256: digest, looked up in a release manifest, either while running with software.install or at creation in its software config.

const base = "https://releases.rivet.dev/agent-os/latest/software/";
const { artifacts } = await (await fetch(`${base}manifest.json`)).json();
const ripgrep = artifacts.find((artifact: { name: string }) => artifact.name === "ripgrep");

const installed = await vm.v1.software.install({
	source: { url: new URL(ripgrep.path, base).href, digest: ripgrep.digest },
});
if (installed.config.state === "restart_required") {
	await vm.v1.vm.restart({});
}

Full docs: Software.

Schedules

cron.schedule runs a command inside the VM on a cron expression. Hosted jobs are identified by name, are stored with the VM, and survive sleep.

const job = await vm.v1.cron.schedule({
	name: "cleanup",
	expression: "0 * * * *",
	command: "rm",
	args: ["-rf", "/tmp/cache"],
	options: { env: {} },
});

for (const scheduled of await vm.v1.cron.list({})) {
	console.log(scheduled.name, scheduled.expression);
}

Full docs: Crons & Schedules.

Lifecycle and persistence

A hosted VM sleeps when idle unless a process is running and starts lazily on the first action after it wakes; durable files, configuration, and cron jobs survive sleep and restarts, while running processes, terminals, language contexts, and open streams do not. Give the VM a durable root in its config to keep files, and use vm.status and vm.restart to inspect the active generation or start a new one from the latest config.

// Creation input is used only when the VM is first created.
const vm = client.agentOS.getOrCreate(["my-vm"], {
	createWithInput: {
		config: { filesystem: { root: { type: "durable" } } },
	},
});

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

Full docs: Persistence & Sleep and VM lifecycle.

Actions

GroupActions
configget, set, patch
vmstatus, restart
filesystemreadFile, writeFile, readFiles, writeFiles, stat, exists, mkdir, readdir, readdirEntries, readdirRecursive, move, remove, listMounts, export
processrun, spawn, get, list, tree, wait, signal, stdin.write, stdin.close, pty.resize, output.read
terminalopen, list, stdin.write, pty.resize, output.read, wait, close
networkfetch, fetchStream.start, fetchStream.read, fetchStream.cancel, preview.create, preview.expire
softwareinstall, uninstall, list
cronschedule, list, cancel
contextscreate, get, list, reset, delete
javascriptexecute, evaluate, executeFile, spawn, spawnFile, npm.install, npm.runScript, npm.runPackage
typescriptexecute, evaluate, executeFile, spawn, spawnFile, check, checkProject
pythonexecute, 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.

Next steps