Skip to main content
Reference

Hosted HTTP API

Reference for the hosted agentOS VM API: creating VMs, authentication, actions, configuration, lifecycle, events, and errors.

Each hosted VM is one instance of the prebuilt agentOS Rivet Actor. You create it by key, then call its actions over the Rivet gateway. The @rivet-dev/agentos TypeScript client is generated from the same contract and calls the same actions. See the hosted quickstart for a walkthrough.

Overview

FieldValue
Base URLhttps://api.rivet.dev, or your control plane when self-hosting
Actor nameagentOS
Create a VMPUT /actors?namespace={namespace}
Call an actionPOST /gateway/{vm_id}/action/v1.{group}.{action}
Request body{ "args": [input] }
Response body{ "output": result }
AuthenticationAuthorization: Bearer to create VMs and tokens; x-rivet-token for actions

Create a 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 }

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

The TypeScript client does the same with getOrCreate, and can pass creation input on first creation:

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

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

const vm = client.agentOS.getOrCreate(["my-vm"], {
	createWithInput: { config: { environment: { CI: "true" } } },
});
const vmId = await vm.resolve();

Authentication

Keep your admin token on the backend. To let a browser or other untrusted client call one VM directly, issue a JWT scoped to that VM. See JWTs.

curl -X POST "https://api.rivet.dev/auth/tokens" \
  -H "Authorization: Bearer $RIVET_TOKEN" \
  --json @- <<EOF
{
  "namespace": "$RIVET_NAMESPACE",
  "subject": "user-123",
  "duration": 3600,
  "grants": [{
    "resource": "actor_gateway",
    "target": { "id": "$VM_ID" },
    "operations": ["read"]
  }]
}
EOF
# → { "token": "…", "expires_ts": … }

A client created with that token reaches the VM with client.getForId("agentOS", vmId).

Call an action

Every public action is versioned under v1. Send the action’s input as the single element of args. See Call Action for the gateway’s routing options.

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

In TypeScript, the same call is vm.v1.process.run({ ... }).

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

Process, terminal, context, and network stream handles carry the VM generation, for example { "generation": 1, "pid": 42 } for a process. The hosted contract has no agent sessions and no shell-string process.exec.

Each capability page shows its hosted actions in the Hosted tab of its examples: Filesystem, Processes & Shells, Networking & Previews, Software, Crons & Schedules, and Resource Limits.

Configuration

Configuration is stored with the VM and versioned.

ActionBehavior
v1.config.getReturns the durable desired config and its revision.
v1.config.setReplaces the complete config. An omitted field selects its default.
v1.config.patchApplies an RFC 7386 JSON Merge Patch to the desired config.

Merge Patch recursively merges objects and replaces arrays as complete values. Setting a property to null removes the override, which selects its default. Both mutations accept expectedRevision for compare-and-set updates; a stale revision fails without changing durable state.

curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.config.patch" \
  -H "x-rivet-token: $VM_TOKEN" \
  --json '{"args": [{
    "expectedRevision": 3,
    "patch": { "environment": { "DEBUG": "1" } }
  }]}'

The config contains, among others:

FieldPurpose
environmentEnvironment variables for guest processes.
filesystemRoot and mounts from the hosted registry, such as { "root": { "type": "durable" } }.
softwarePackage sources, such as [{ "url": "https://…/tool.aospkg" }].
previewPreview defaults, such as { "defaultTtlMs": 30000 }.
limitsResource limits.

Creation input is used only when the actor is first created. Calling getOrCreate with different input for an existing key does not reconfigure it.

When a VM is running, the actor compares the resolved creation policies for supported runtime fields and applies what it can live. Setting an explicit value equal to the active default does not by itself require a restart. Software sources, filesystem policy, and fields outside that comparison take effect after a restart.

VM lifecycle

v1.vm.status reports the active generation, applied config revision, package readiness, lifecycle state, and recent issues. A desired config can be durable while the active generation reports that a restart is required.

v1.vm.restart stops the active VM, waits for bounded shutdown, and starts a new generation from the latest desired config. Handles from an older generation fail with stale_generation.

The VM sleeps when idle unless a process is running, and starts lazily on the first action after it wakes; see actor lifecycle. Durable files and configuration survive sleep; running processes, terminals, contexts, and open streams do not.

Events and replay

Clients connected through RivetKit receive live events. Plain HTTP clients use the pull actions, which are also the recovery path after a disconnect.

ResourcePull actionEvents
Processv1.process.output.read, v1.process.waitprocess.output, process.exit
Terminalv1.terminal.output.read, v1.terminal.waitterminal.output, terminal.exit
HTTP responsev1.network.fetchStream.readNone
VMv1.vm.statusvm.booted, vm.shutdown, vm.limitWarning
Cronv1.cron.listcron.fired

Event names are not versioned. vm.shutdown carries a reason of "sleep", "destroy", or "error".

Process and terminal replay use a generation-scoped sequence cursor. Pass the last cursor as after, and bound each page with maxEvents and maxBytes. Network response streams are pull-based, so each action is bounded and the caller owns backpressure.

const conn = vm.connect();
await conn.ready;

conn.on("process.output", (data) => {
	console.log(data.process.pid, data.stream, new TextDecoder().decode(data.data));
});
conn.on("process.exit", (data) => {
	console.log(data.process.pid, "exited with code", data.status.exitCode);
});

Errors

CodeCause
stale_generationA process, terminal, context, or stream handle from before a v1.vm.restart was used.
expiredA fetch-stream handle expired.
timeoutA required package-resolution deadline passed.
not_foundA closed terminal’s replay was evicted from the bounded retention window.

Final terminal output and its confirmed exit remain readable after exit within the bounded closed-terminal retention window.

Contract compatibility

The @rivet-dev/agentos package exports AGENTOS_API_VERSION, AGENTOS_CONTRACT_MAJOR, AGENTOS_CONTRACT_HASH, and AGENTOS_CAPABILITIES. Rust DTOs and the action registry generate the TypeScript surface.

The contract is currently agentos-sdk.dev/v1alpha1, major 1. The hash covers the canonical public actions, events, DTOs, and capabilities. Private cron and maintenance actions are excluded from both the client and the hash.

Inspector

The Rivet Inspector shows a hosted VM’s filesystem, processes, terminals, software, previews, configuration, status, and limit warnings through the same public contract. It can restart the VM but cannot edit host mounts.

Published services binaries and the services container include the Inspector tabs. A source or custom deployment can point the service at another built copy:

AGENTOS_INSPECTOR_TABS_DIR=node_modules/@rivet-dev/agentos/assets/inspector-tabs-app \
  rivet-services start