# rho v0.1.0 - API Reference

## Modules

- Loop &amp; sessions
  - [Rho](Rho.md): An agent core for Elixir apps: pi-agent-core's loop (`Rho.Loop`), omp/pi
JSONL sessions (`Rho.Session`), compaction, tools, and model sign-in
(subscription OAuth or API keys, `Rho.Auth`) on req_llm.
  - [Rho.Artifacts](Rho.Artifacts.md): The output budget: a tool result over 16 KiB goes to
the model as its head and tail with a marker in the middle; the full
text is kept as an artifact the agent reads back with the `read_artifact`
tool, a page of lines at a time.
  - [Rho.Compaction](Rho.Compaction.md): Context compaction, ported from pi's local summary method
(`pi-agent-core/src/compaction/compaction.ts`; omp writes it as
`method: "soft"`). When a request nears the model's context window, the
older part of the branch is summarized by the model into a `compaction`
entry (`Rho.Session.compaction/4`), and `Rho.Session.context/1`
sends that summary plus the recent tail from then on.
  - [Rho.Events](Rho.Events.md): What a loop tells its subscribers, as `{:rho, session_id, event}`
messages (plain `send`, no PubSub). The lifecycle is pi's
(`pi-agent-core/src/agent-loop.ts`)
  - [Rho.Loop](Rho.Loop.md): The agent loop for one session: a GenServer with pi's lifecycle
(`pi-agent-core/src/agent-loop.ts`; events in `Rho.Events`).
  - [Rho.Session](Rho.Session.md): Sessions in omp/pi's JSONL format (`pi-coding-agent/src/session/
session-entries.ts`, `CURRENT_SESSION_VERSION = 3`), so a session can move
between omp on a computer and a rho host (Operator on a phone, say).

- Tools
  - [Rho.Tool](Rho.Tool.md): A tool the agent can call. Implementations are plain modules, so a host
can register one at runtime by module, or serve changing sets of them
from a source (see `Rho.ToolRegistry`).
  - [Rho.ToolRegistry](Rho.ToolRegistry.md): The tools the agent can call, by name, from three places
  - [Rho.ToolRegistry.Source](Rho.ToolRegistry.Source.md): A source of tools the registry asks on every call, for tool sets that
change while the app runs (the Dyn layer's generations, `Rho.Dyn.Source`:
tools the agent writes, compiles and activates on the device). Configure with
`{Rho.Supervisor, tool_sources: [MySource]}` or
`config :rho, :tool_sources, [MySource]`.
  - [Rho.ToolRunner](Rho.ToolRunner.md): Runs one tool call in its own task (under a `Task.Supervisor`, not linked
to the loop). The `before_tool_call` gate runs first, inside the task, so
a gate that waits (a biometric approval) never blocks the loop;
once the gate allows, the task tells the loop (`{:tool_running, pid}`),
which starts the tool's timeout clock from then.
  - [Rho.Tools.ReadArtifact](Rho.Tools.ReadArtifact.md): Core tool: read a page of a tool output that was too big to give whole
(`Rho.Artifacts`). A page stays under the output budget, so
reading never spills again.

  - [Rho.Tools.Todo](Rho.Tools.Todo.md): Core tool: the session's todo list (omp's `todo`), kept in
`todos/<session_id>.json` in the app's data dir. Writing the steps of a
multi-step job down and ticking them off keeps the agent from stopping
halfway, or forgetting a step after a compaction; and the list survives a
restart of the app. One item at a time is in progress: the first open one,
moved on whenever an item is done or removed.

- Models &amp; usage
  - [Rho.Budget](Rho.Budget.md): The per-day cost cap: what the model calls cost today, priced by
req_llm from each reply's usage (notional on a Claude or ChatGPT
subscription), against the host's `Rho.Settings.daily_cap/1`.
  - [Rho.LLM](Rho.LLM.md): The model client the loop talks to. `Rho.LLM.ReqLLM` is the real
one (Anthropic, OpenAI, OpenAI Codex and Google through req_llm, with
the credential from `Rho.Auth`); tests inject a scripted fake.
  - [Rho.LLM.ReqLLM](Rho.LLM.ReqLLM.md): The model calls through req_llm's providers, streamed, with the
provider's credential from `Rho.Auth` (fetched, and for a subscription
refreshed when due, per call)
  - [Rho.LLMCatalog](Rho.LLMCatalog.md): Gives llm_db (the model catalog req_llm resolves models through) a
snapshot that works on a phone.
  - [Rho.Models](Rho.Models.md): The models rho can call right now (like omp's `/models`): the static
catalog filtered to the providers that have a credential (`Rho.Auth`).
  - [Rho.Usage](Rho.Usage.md): How much of each provider subscription is left, and what the model calls
used, for the host's usage page and status line.
  - [Rho.Usage.Fetch](Rho.Usage.Fetch.md): Asks a provider's OAuth usage endpoint what its subscription has left,
with the sign-in's access token (`Rho.Auth.credential/1`), as omp
does (subscriptions only: an API key has no such endpoint)

- Sign-in &amp; credentials
  - [Rho.Auth](Rho.Auth.md): The model-provider credentials, one per provider, each pi's `auth.json`
entry as JSON in the credential store (`Rho.CredentialStore`) under
`"auth:<provider>"`
  - [Rho.Auth.Login](Rho.Auth.Login.md): Signing in to a subscription (`:anthropic`, `:openai_codex`): the OAuth
flow (`Rho.Auth.OAuthFlow`) with the provider's own localhost redirect,
answered by this BEAM.
  - [Rho.Auth.OAuthFlow](Rho.Auth.OAuthFlow.md): The OAuth authorization-code flows omp signs in with (`/login anthropic`,
`/login openai-codex`), built as omp's declarative engine builds them from
`pi-catalog`'s `rules/auth/anthropic.kdl` and `openai-codex.kdl`
  - [Rho.CredentialStore](Rho.CredentialStore.md): Where rho keeps secrets: the provider sign-ins and API keys
(`Rho.Auth`), a binary value per string key. A host seam:
`config :rho, :credential_store, Module` picks the backend.
  - [Rho.CredentialStore.File](Rho.CredentialStore.File.md): The default backend: one 0600 file per key under `<data dir>/secure/`,
the key made filename-safe. Written through a temp file created 0600
before the secret goes in, then renamed over the old one.

- Host seams
  - [Rho.Config](Rho.Config.md): The host's settings for rho, `config :rho, ...`, each with a default that
works on a computer. `:data_dir`, `:default_model` and `:system_prompt`
may be given as `{module, function, args}` (or a 0-arity function),
called each time the value is read, so a host can keep them in its own
settings and change them at run time.
  - [Rho.Settings](Rho.Settings.md): The user settings the loop reads, a host seam
(`config :rho, :settings, Module`)
  - [Rho.Settings.File](Rho.Settings.File.md): The default `Rho.Settings`: `settings.json` in the data dir (a missing
or unreadable file means the defaults; other keys in it are kept, so a
host may share the file). Each call reads the file.
  - [Rho.Supervisor](Rho.Supervisor.md): rho's processes, for the host to start in its own tree (rho has no OTP
application callback: a mob app starts its code by hand)

- Dyn
  - [Rho.Dyn](Rho.Dyn.md): The Dyn layer: code the agent writes, compiles and runs on the device
itself (tools and screens), next to the fixed Core (the loop, sessions,
sign-in, the core tools, the approval gate and the repair path, which
ship in the app and which the agent can't change). The Core changes Dyn
only through this module, one generation at a time
  - [Rho.Dyn.Approval](Rho.Dyn.Approval.md): The approval gate on changing what runs (the pipeline's step 3, see
`Rho.Dyn`):
activating a proposed generation, or reverting to a chosen one by hand.
  - [Rho.Dyn.Approval.Biometric](Rho.Dyn.Approval.Biometric.md): The production approval: the system screen-lock prompt (fingerprint,
face, or the phone's PIN, pattern, password or passcode) behind an
approve control the host shows with the change (Operator's approve chip).
This small process (`Rho.Supervisor` starts it with Dyn) holds what the
human confirmed; only the host's UI, after the prompt passed, calls
`confirm/1`.
  - [Rho.Dyn.AutoApprove](Rho.Dyn.AutoApprove.md): The "approve all" setting: while on, the host's UI activates each
candidate generation as it arrives instead of asking for approval (the
same activation, so probation and revert-on-crash still apply). Only
Dyn activations: reverting still asks.
  - [Rho.Dyn.Check](Rho.Dyn.Check.md): The static check every staged file passes before it is compiled (the
pipeline's step 2, see `Rho.Dyn`), and `beam/2`, a second pass over the
compiled binaries.
  - [Rho.Dyn.Config](Rho.Dyn.Config.md): The host's settings for the Dyn layer, `config :rho, :dyn, [...]` (see
`Rho.Dyn`). Every key has a default; a host that doesn't use Dyn sets
none of them.
  - [Rho.Dyn.Generation](Rho.Dyn.Generation.md): One generation of the Dyn layer: what `gens/<n>/manifest.json` holds
(see `Rho.Dyn.Store`).
  - [Rho.Dyn.Keeper](Rho.Dyn.Keeper.md): The Core process that decides which Dyn generation runs (activation,
probation, revert and safe mode, steps 3–4 in `Rho.Dyn`). It owns the
registry table (`Rho.Dyn.Registry`) and is the only writer of the
`current` pointer.
  - [Rho.Dyn.Screens](Rho.Dyn.Screens.md): How Dyn screens plug into the host's UI: a host seam (`config :rho, :dyn,
screens: Module`, `Rho.Dyn.Config`). rho builds, checks, selftests and
watches Dyn screens the same way whatever the UI; this says what a
screen is and how the UI tells the Keeper a launch got going
  - [Rho.Dyn.Screens.Mob](Rho.Dyn.Screens.Mob.md): Mob screens as Dyn screens (`config :rho, :dyn, screens:
Rho.Dyn.Screens.Mob`, see `Rho.Dyn.Screens`)
  - [Rho.Dyn.Screens.None](Rho.Dyn.Screens.None.md): No screens (the default `Rho.Dyn.Screens`): Dyn code is tools and
modules. Without a UI there is no first frame to wait for, so
`c:Rho.Dyn.Screens.after_first_render/1` applies the MFA at once: a launch's clock to
"stable" starts at `Rho.Dyn.boot/1`.

  - [Rho.Dyn.Seed](Rho.Dyn.Seed.md): The seed: the Dyn sources an install starts from, which the host ships
(Operator's default front: a welcome screen, a component library, the
front's settings). The host embeds them at build time
(`Application.app_dir/2` can't resolve priv/ on the device) and hands them
to `start/2`.
  - [Rho.Dyn.Source](Rho.Dyn.Source.md): The Dyn layer as a `Rho.ToolRegistry.Source`: the current generation's
tools, read from the Keeper's registry table on every call, so an
activation or a revert (by hand, or automatic) changes the tools the
loop offers from its next model call. Every tool call's task is handed
to the Keeper first (`c:Rho.ToolRegistry.Source.watch/2`), so a Dyn tool's crash, or the kill at
its timeout, counts against its generation.
  - [Rho.Untrusted](Rho.Untrusted.md): Text and data from code rho doesn't trust, the Dyn layer's (`Rho.Dyn`),
for the processes it does: the loop, the Keeper, the caller of a compile
or a selftest.

- Dyn internals
  - [Rho.Dyn.Compiler](Rho.Dyn.Compiler.md): Compiles a source set into generation `n` (part of the pipeline's step 2, see
`Rho.Dyn`) and loads, unloads and purges generations' modules.
  - [Rho.Dyn.Diff](Rho.Dyn.Diff.md): Unified diff (as `diff -u` and git print it, three lines of context) between
two source sets `%{relative_path => source}`: what the approval card and
the rescue screen show for a generation.

  - [Rho.Dyn.LogGuard](Rho.Dyn.LogGuard.md): A primary `:logger` filter that keeps Dyn terms away from the logger's
formatting, in whatever process logs them.
  - [Rho.Dyn.Registry](Rho.Dyn.Registry.md): Reads the Dyn registry: one ETS table owned (and only written) by
`Rho.Dyn.Keeper`, named like the Keeper. It maps logical names
to the current generation's modules
  - [Rho.Dyn.Reuse](Rho.Dyn.Reuse.md): Incremental compiles: a proposal recompiles only the files that changed
(or depend on a change at compile time) and reuses the rest from its
parent generation, renamed. On a Moto G 2021 compiling the default
front from source takes about 33 s, and recompiling a module from its
stored Erlang code still about 350 ms (the Erlang compiler's passes):
24 s of a one-file change to the 68-module front. So a module is reused
by renaming its compiled binary instead; on a Mac that takes 56 ms for
the whole front, against 1.9 s through the Erlang compiler.
  - [Rho.Dyn.Selftest](Rho.Dyn.Selftest.md): Selftests a compiled generation (the end of the pipeline's step 2, see `Rho.Dyn`),
one module at a time, each in a fresh process with a `max_heap_size`
(killed when exceeded, off-heap binaries included), a timeout and
`trap_exit` (a linked helper that crashes doesn't take the test down
unreported).
  - [Rho.Dyn.Store](Rho.Dyn.Store.md): The Dyn layer on disk, under one root dir (`<data dir>/dyn` by default,
`Rho.Config.data_dir/0`)
  - [Rho.Dyn.Trace](Rho.Dyn.Trace.md): An Elixir compiler tracer for Dyn compiles (`Code.put_compiler_option(:tracers, ...)`):
which modules of the generation a file needs **at compile time**, so
`Rho.Dyn.Compiler` knows when a file compiled for an earlier
generation can be reused as it is (`Rho.Dyn.Reuse`).

- Dyn tools
  - [Rho.Tools.DynCopy](Rho.Tools.DynCopy.md): Core tool: copy a staged Dyn source file to a new path under a new module
name (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynDelete](Rho.Tools.DynDelete.md): Core tool: delete a staged Dyn source file (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynEdit](Rho.Tools.DynEdit.md): Core tool: replace one exact, unique piece of a staged Dyn source file (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynFiles](Rho.Tools.DynFiles.md): Core tool: list the Dyn layer's staged source files (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynPropose](Rho.Tools.DynPropose.md): Core tool: turn the Dyn staging copy into a candidate generation
(`Rho.Dyn.propose/2`: static check, compile, selftests). It
never activates anything itself: the human approves on the phone, or has
turned approve all on (`Rho.Dyn.AutoApprove`), when the host's UI
activates it as it arrives. Description and result say which.

  - [Rho.Tools.DynRead](Rho.Tools.DynRead.md): Core tool: read a staged Dyn source file with line numbers (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynReset](Rho.Tools.DynReset.md): Core tool: put the Dyn staging copy back to the current generation's sources (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynStatus](Rho.Tools.DynStatus.md): Core tool: what the Dyn layer runs, what's pending, and its recent crash reports (see `Rho.Tools.DynTool`).
  - [Rho.Tools.DynTool](Rho.Tools.DynTool.md): What the `dyn_*` Core tools share: the agent edits its Dyn layer's
staging copy and proposes it (`Rho.Dyn`). There is deliberately
no tool to activate or revert: those need the human's approval (the screen lock).
  - [Rho.Tools.DynWrite](Rho.Tools.DynWrite.md): Core tool: create or overwrite a staged Dyn source file (see `Rho.Tools.DynTool`).

