Sessions & Persistence
How AgentOS stores exact ACP history and restores adapters through VM SQLite.
SQLite is the AgentOS source of truth for public session metadata, prompts, pending requests, and durable ACP events. Adapter-owned session files or databases remain private adapter state; AgentOS does not mirror them into the VFS or import adapter replay into public history.
One SQLite descriptor per VM
VM creation supplies exactly one trusted database descriptor:
actor_udstalks directly to Rivet actor SQLite through its authenticated Unix socket.sqlite_fileopens one local SQLite file for the logical VM on the sidecar’s bounded blocking executor.
The sidecar resolves the descriptor once and injects the same database handle into VFS metadata, VFS block storage, and the AgentOS core session store. Filesystem plugins receive only filesystem policy, not another SQLite path or UDS credential. One Rivet actor is one logical VM, so tables do not repeat a VM ID.
Each actor-UDS transaction generates a fresh UUID transaction key and attaches it to BEGIN, every statement, and COMMIT or ROLLBACK. Rivet owns transaction affinity and isolation. AgentOS adds no second UDS mux, pool, writer scheduler, or retry layer.
Independent schema owners
Three owners share the physical per-VM database without sharing a migration sequence:
| Owner | Version table | Data tables |
|---|---|---|
| Native filesystem | agentos_fs_schema_version | agentos_fs_* |
| Sidecar/core durable state | agentos_core_schema_version | agentos_core_* |
| TypeScript actor hosting metadata | agentos_actor_schema_version | agentos_actor_* |
Each version table is a STRICT singleton table. Its owner alone validates and advances its append-only migration ladder, updating the schema and version in the same transaction. A future version fails closed. There is no shared schema-version table, global AgentOS migration sequence, or AgentOS use of PRAGMA user_version; Rivet-owned schema metadata remains independent. Owners do not create cross-owner foreign keys.
Session event log
agentos_core_events keeps the durable envelope in scalar columns: public session ID, sequence, timestamp, negotiated ACP version, internal storage kind, correlation ID, payload byte length, and permission outcome fields. payload_json contains only the exact native ACP payload:
session_updatestores an ACPSessionUpdate, including itssessionUpdatediscriminator, optional fields, and_meta.permission_requeststores the ACPRequestPermissionRequestselected for public delivery.permission_responsestores the ACPRequestPermissionResponse.
The internal session_update storage kind is not a public event discriminator. On read, AgentOS exposes SessionUpdate.sessionUpdate as the event’s top-level type and places that ACP variant’s native fields directly beside it. Permission request and response fields are flattened the same way. The public AgentOS durability envelope is reconstructed from the scalar columns; it is not duplicated inside payload_json, and the row is not a raw JSON-RPC frame. This keeps event data ACP-native while giving AgentOS a stable sequence, timestamp, and public request correlation.
Complete user content is committed before prompt dispatch. Agent message and thought deltas are live and ephemeral; they receive no durable sequence and are coalesced into native ACP chunk updates only at a completed-message boundary. Other ACP updates are stored unchanged. Events are published only after their SQLite transaction commits. If an adapter emitted an event that never committed, SQLite wins, and AgentOS never automatically resends a prompt whose delivery is uncertain.
Trusted plaintext storage
The per-VM SQLite database is trusted runtime storage. Session environment values, MCP headers or credentials, prompts, message content, tool arguments and results, permission payloads, and cached adapter metadata may be stored as plaintext JSON or SQLite values so a session can restore after sleep. AgentOS does not currently encrypt, redact, or replace these values with secret references. Operators must protect database and backup access according to the sensitivity of the workload.
Retention and default bounds
Defaults are generous, VM-configurable limits.acp safeguards. AgentOS warns at 80% and returns a typed error naming the setting to raise when a hard-admission limit is reached.
| Durable collection | Default | Contract |
|---|---|---|
| Sessions | 10,000 per VM | Hard admission limit; sessions are never evicted implicitly. |
| History | 1,000,000 events and 1 GiB per session | Oldest committed events are pruned in bounded batches; an older reconnect cursor returns history_cursor_expired. |
| Prompt/idempotency records | 100,000 per session; 1,000,000 per VM | Oldest unreferenced terminal records are pruned to admit new prompts. An idempotency key is authoritative only while its prompt record is retained. |
Pending ask permissions | 1,000 per session; 10,000 per VM | Hard admission limit with no time-based expiry; lifecycle resolution is required. |
| Terminal permission outcomes | 10,000 per session; 100,000 per VM | Oldest outcomes are pruned. A late response gets its specific terminal reason while retained and request_not_found after pruning. |
History counters and payload-byte totals are updated transactionally with insertion and pruning. Bootstrap reconciliation repairs counter drift from event rows. A single batch larger than the configured history event or byte bound fails atomically rather than partially committing.
Related request bounds default to 64 MiB and 16,384 blocks per prompt, 4 MiB of fallback continuation context, and 10,000 rows per session-list or history page.
Adapter restoration
Public session IDs do not depend on adapter IDs. When no live route exists, the sidecar starts the configured adapter and tries native ACP restoration in this order:
session/resumewhen advertised bysessionCapabilities.resume.- Stable
session/loadwhenloadSessionis advertised. session/newplus bounded continuation context derived from recent SQLite history.
Notifications replayed by resume or load are discarded. This avoids duplicate public history and accommodates adapters whose restoration behavior differs despite ACP negotiation.
Actor lifecycle
Merely having durable sessions does not keep the actor awake. The prompt action uses actor keepAwake from dispatch through the terminal SQLite commit so the VM cannot sleep halfway through a turn. Read-only session operations never start an adapter and do not hold the actor awake.
Core tables
agentos_core_sessions: scalar session state and creation options, complex creation-option JSON, cached negotiation, retained-history counters, sequence bounds, and timestamps.agentos_core_events: ordered exact ACP payloads with a scalar AgentOS envelope.agentos_core_prompts: prompt idempotency hashes and terminal result or error; accepted input is represented by durable native ACP user updates rather than duplicate prompt JSON.agentos_core_permission_records: actionable and terminal permission correlation.agentos_core_permission_outcomes: bounded terminal outcomes used to answer late responses.
The filesystem’s agentos_fs_* and actor’s agentos_actor_* tables share the database handle but remain independently owned.