All notable changes to rho are listed here. The format follows Keep a Changelog, and rho uses Semantic Versioning.
Unreleased
0.1.0 - 2026-10-16
The first release: the agent core taken out of Operator so Operator and Bezalel can share it.
Added
- Loop (
Rho.Loop): a GenServer per session with pi-agent-core's lifecycle and events (Rho.Events): streamed replies, the reply's tool calls run in parallel (or one at a time when a tool is:exclusive) with results in call order, steering and follow-ups while a run is going, stop, retries with backoff, rate limits waited out within a budget then a fallback model, a per-day cost cap (Rho.Budget), a wrap-up turn at the iteration limit, and a reminder while the session's todo list has open items. - Sessions (
Rho.Session): omp/pi's JSONL session format (version 3), append-only, unknown entry types kept, so a session moves between omp on a computer and a rho app on a phone; tool results keep the host's pick of a tool's details (:keep_details) and the pictures a model makes. - Compaction (
Rho.Compaction): pi's local summary, before a call that would overflow the window and after a provider rejects one. - Tools (
Rho.Tool,Rho.ToolRunner,Rho.ToolRegistry): plain modules, each call in its own task with a timeout and abefore_tool_callgate; pictures for the model ({:images, ...}), data for the host's screens ({:details, output, details}, also on errors); oversized output spilled to an artifact the agent pages through (Rho.Artifacts, theread_artifacttool); thetodotool; tool sources for tool sets that change while the app runs (Rho.ToolRegistry.Source). - Models (
Rho.LLM,Rho.LLM.ReqLLM,Rho.Models,Rho.LLMCatalog,Rho.Usage): Anthropic, OpenAI, OpenAI Codex and Google on req_llm, with subscription usage windows and per-model counters, and a model catalog trimmed to those providers (llm_catalog: falsekeeps llm_db's own). - Sign-in (
Rho.Auth,Rho.Auth.Login,Rho.CredentialStore): Claude Pro/Max and ChatGPT (Codex) subscriptions through omp's OAuth PKCE flows, with refresh coordination and refresh-token rotation, or an API key for Anthropic, OpenAI or Gemini. - Host seams (
Rho.Config,Rho.Supervisor,Rho.Settings): no OTP application callback (the host startsRho.Supervisor); data dir, credential store, settings, system prompt, app name and hints are the host's. - Dyn (
Rho.Dyn, optional): tools and screens the agent writes, checks, compiles and selftests on the device as versioned generations, activated only with the human's approval, on probation and reverted on crashes or a failed launch, with safe mode, background rebuilds for a new Core, a shipped seed (Rho.Dyn.Seed) and mob screens (Rho.Dyn.Screens.Mob). - Untrusted terms (
Rho.Untrusted): nothing Dyn code hands over runs its code in a Core process. Crashes are formatted, with their stack, where they happened (a tool's task, a selftest's or compile's process), in a helper with a time and heap bound that ends without a crash report and dies with its caller; the loop, the Keeper and a proposal's caller only describe the exit reasons they receive (total over any term, improper lists and huge integers included), never calling an exception'smessage/1or a Dyn struct'sInspect,String.CharsorJason.Encoder. A Dyn tool's answer and details are plain data (structs as maps) before they leave its task, and its declaration is read in one bounded process outside the loop and kept; a tool whose declaration fails is left out, one that ran over is read again after 1, 5 and 30 minutes, then stays out. Hosts watch their own Dyn processes withRho.Dyn.watch/2andRho.Dyn.unwatch/1and may exit them with{:rho_crash, text}(Rho.Untrusted.crash/3) to reporttext. A primary logger filter (Rho.Dyn.LogGuard) describes any log event that holds a Dyn struct (within a 10,000-term budget; bigger events pass through), so a Dyn process's crash report runs none of its code in:logger_proxy; the check refuses:logger,:error_logger,:logger_backends,:telemetry,:gen_event,:gen_statemandLogger's translators, backends and configuration. - Threat model: the static check (
Rho.Dyn.Check) is a best-effort deny-list against the model's mistakes, not a sandbox against hostile code;Rho.UntrustedandRho.Dyn.LogGuardlower the chance that a built tool's crash takes a trusted process down. Known ways around the check (raw messages to:logger_proxy, Logger.App and logger backend modules, children started under trusted supervisors,:alarm_handler, resource floods) are listed inRho.Dyn.Checkand the README.