website/src/content/docs/agent-os/persistence.mdx
/home/user automatically| Data | Storage | Persists? |
|---|---|---|
Files in /home/user | Persistent filesystem | Yes |
| Session records | SQLite (agent_os_sessions) | Yes |
| Session event history | SQLite (agent_os_session_events) | Yes |
| Preview URL tokens | SQLite (agent_os_preview_tokens) | Yes |
| Cron job definitions | Actor state | Yes |
| Running processes | VM kernel | No |
| Active shells | VM kernel | No |
| In-memory mounts | VM memory | No |
| VM kernel state | VM memory | No |
The actor stays awake as long as any of these are active:
When all activity stops, the sleep grace period begins.
After all activity stops, the actor waits 15 minutes before sleeping. This allows for brief pauses between interactions without restarting the VM.
Activity stops ──> 15 min grace period ──> Actor sleeps
(VM shutdown, processes killed)
New client connects ──> Actor wakes ──> VM boots ──> Filesystem restored
| Sleep | Destroy | |
|---|---|---|
| Filesystem | Preserved | Deleted |
| Session records | Preserved | Deleted |
| Event history | Preserved | Deleted |
| Preview tokens | Preserved | Deleted |
| VM state | Lost | Lost |
| Processes | Killed | Killed |
Subscribe to vmBooted and vmShutdown events to track VM lifecycle.
const client = createClient<typeof registry>("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]);
agent.on("vmBooted", () => { console.log("VM is ready"); });
agent.on("vmShutdown", (data) => { console.log("VM shutdown reason:", data.reason); // reason: "sleep" | "destroy" | "error" });
```ts @nocheck server.ts
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: { software: [common, pi] },
});
export const registry = setup({ use: { vm } });
registry.start();
When the actor wakes up:
resumeSessiongetSessionEvents to replay missed eventsconst client = createClient<typeof registry>("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]);
// List sessions from before sleep const sessions = await agent.listPersistedSessions(); console.log("Previous sessions:", sessions.length);
// Resume the most recent session if (sessions.length > 0) { const last = sessions[0]; await agent.resumeSession(last.sessionId);
// Replay events for transcript const events = await agent.getSessionEvents(last.sessionId); for (const e of events) { console.log(e.seq, e.event.method); } }
```ts @nocheck server.ts
import { agentOs } from "rivetkit/agent-os";
import { setup } from "rivetkit";
import common from "@rivet-dev/agent-os-common";
import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({
options: { software: [common, pi] },
});
export const registry = setup({ use: { vm } });
registry.start();
agent_os_fs_entriesStores the virtual filesystem.
| Column | Type | Description |
|---|---|---|
path | TEXT PRIMARY KEY | File or directory path |
is_directory | INTEGER | 1 for directory, 0 for file |
content | BLOB | File content |
mode | INTEGER | POSIX mode bits |
size | INTEGER | File size in bytes |
atime_ms | INTEGER | Access time (ms) |
mtime_ms | INTEGER | Modification time (ms) |
ctime_ms | INTEGER | Change time (ms) |
birthtime_ms | INTEGER | Birth time (ms) |
agent_os_sessionsStores session metadata.
| Column | Type | Description |
|---|---|---|
session_id | TEXT PRIMARY KEY | Unique session identifier |
agent_type | TEXT | Agent type (e.g. "pi") |
capabilities | TEXT (JSON) | Agent capabilities |
agent_info | TEXT (JSON) | Agent metadata |
created_at | INTEGER | Creation timestamp (ms) |
agent_os_session_eventsStores session event history.
| Column | Type | Description |
|---|---|---|
id | INTEGER PRIMARY KEY | Auto-incrementing ID |
session_id | TEXT | Session reference |
seq | INTEGER | Sequence number within session |
event | TEXT (JSON) | JSON-RPC notification |
created_at | INTEGER | Timestamp (ms) |