Skip to content

Usage ledger

Rho's usage ledger is a durable, provider-neutral SQLite interface for accounting tools. It is separate from session persistence and is not rebuildable from transcripts. Rho writes one row for each provider request across interactive, automation, delegated-agent, compaction, title-generation, and goal-evaluation paths.

Location and access

The database is ~/.rho/usage.sqlite3 by default. Setting RHO_HOME changes Rho's data root, including the ledger, to $RHO_HOME/usage.sqlite3. Rho creates the data directory and database with mode 0700 and 0600, respectively, on Unix.

The database uses WAL mode and a five-second busy timeout. Multiple Rho processes can write concurrently, and reporting tools can use SQLite's read-only mode while Rho is active. Readers should tolerate normal SQLite -wal and -shm sidecar files.

Compatibility and schema

PRAGMA user_version versions database migrations. Version 1 contains usage_events; each immutable row also has a schema_version for row-semantics evolution. Future schema changes should be additive, and existing columns will be preserved. Readers should ignore columns they do not recognize and reject a user_version newer than they support.

Each row represents one actual provider request. event_id is the primary key, and writes use INSERT OR IGNORE, so retrying persistence with the same event is safe. A separately billed provider retry has a different event ID and its own row.

ColumnSemantics
event_idStable opaque request-event identity.
schema_versionSemantics version for this row, initially 1.
occurred_at_msUTC Unix timestamp in milliseconds.
session_id, parent_session_id, run_idOptional Rho execution identities.
step_index, attempt_indexOptional one-based orchestration step and provider-attempt indexes.
workspace_pathOptional workspace identity as recorded by the caller.
provider, modelExact provider and model identities used for the request, without pricing aliases.
purposeOpen string describing why the model was called. Documented values are agent, subagent, compaction, title, and goal.
request_outcomecompleted, failed, or cancelled. Usage observed before failure or cancellation is still recorded.
input_tokensUncached input tokens.
output_tokensOutput tokens.
cache_read_tokensProvider-reported cache-read tokens.
cache_write_tokensProvider-reported cache-write tokens.
total_tokensProvider-reported total. It is not recomputed or redistributed.
cost_usd_microsProvider-reported USD micros, stored without floating-point conversion. Local estimates are not stored.
rho_versionOptional Rho version that wrote the row.

All token and cost fields are independently nullable. NULL means the provider did not report that value and is distinct from zero. Cache categories are preserved as reported and are not added to input_tokens. ModelUsage::context_window is not request consumption and is not stored. Rust u64 values larger than SQLite's signed 64-bit integer maximum are rejected, and no partial row is inserted.

Privacy

The ledger stores accounting and execution identity metadata only. It must never contain prompts, responses, reasoning, tool arguments, credentials, provider payloads, or transcript content. Workspace paths and caller-provided identifiers may still be sensitive metadata, so access is restricted by filesystem permissions.