Skip to content
All tags

#rivumi

44 posts

Learning Agent Design from Mature Coding Agents (4): Approval Grading and the Audit Trail

Rivumi now grades effects as read/modify/modify_execute/execute and fails closed on unclassified tools. Native MCP tools default to execute unless trusted read-only metadata lowers them. Approval events still land in events.jsonl first and grants can scope to one change set or backend; general command rules and universal sandbox coupling remain unfinished.

Learning Design from Mature Coding Agents (37): Code Mode — Compiling Tool Calls into Batches of Executable Code

rivumi now ships a bounded tool-program DSL: read-only programs support list/read/search/diff, repeat, and if_contains; modify/check transactions receive whole-transaction approval and roll back touched paths on failure. This is not arbitrary JavaScript/Python code mode, and transaction execution is not parallel.

Learning Design from Mature Coding Agents (26): Context Compression and Compaction — From Gap to Auditable Baseline

Mature-agent compaction must handle triggers, complete-turn cut points, and recovery. rivumi now has an 85% high-watermark, automatic compaction, a deterministic native-loop fallback summary, persisted checkpoints, and workspace-context reinjection. Cross-runtime fallback, model-quality summaries, and live-provider long-session validation remain open.

Learning Agent Design from Mature Coding Agents (27): Cross-Session Memory — From Explicit Remembering to Semantic Recall

omp and claude-code provide cross-session memory while the other references mostly rely on instruction files. rivumi now has an explicit remember/list/inject baseline: typed JSONL memories enter prompts across sessions, but retrieval is scope-and-recency only, with no semantic ranking, deduplication, forget command, or automatic extraction.

Learning Design from Mature Coding Agents (28): Dangerous Command Interception and Shell Escalation — Between Allowlists and Always Ask

All five projects combine allow/ask/deny decisions, compound-command inspection, and fail-closed behavior. rivumi now has a deny-first classifier, critical floor, shell segmentation, timeout-deny, configured allow/deny rules, and visible policy reasons. Broader syntax coverage and live interactive validation remain open.

Learning Agent Design from Mature Coding Agents: Series Overview — Reading Five Codebases to Build My Own

I'm building my own Python coding agent called rivumi. This series dissects the source code of five mature projects — pi, oh-my-pi, opencode, codex, and claude-code — topic by topic, while also comparing them with Rivumi's current TUI, external CLI runtimes, local gateway, usage/OTel/session tooling, and Cloudflare slice. Every post follows a fixed five-part structure: design problem → how five projects do it → rivumi's choice → academic grounding → improvement roadmap, with evidence cited at file#symbol level.

Hooks, Skills, Plugins: The Three-Layer Extension System of Mature Coding Agents

Hooks govern control flow, skills inject knowledge, and plugins package both. rivumi now has opt-in deny-only project hooks, a bounded SKILL.md loader, exact enabled_skills selection, plugin manifests/install/list, and external-runtime projection. Input rewriting, full lifecycle coverage, remote registries, and a mature marketplace remain open.

Learning Design from Mature Coding Agents (36): LSP Integration — Pushing Compiler Diagnostics into Agent Context

rivumi can now inject repository diagnostics and open-file state into the next model turn, push typed IDE context over WebSocket, package a VS Code bridge, and supervise long-lived LSP subprocesses through ManagedLspServer. Language-specific initialize/didOpen/didChange adapters and live-editor validation remain open.

Learning Design from Mature Coding Agents (30): MCP Integration — the Standard Socket for Tool Ecosystems

An MCP client must handle transports, tool refresh, approvals, and credential boundaries together. rivumi now supports allowlisted stdio, Streamable HTTP/SSE, tools/resources/prompts, tools/list_changed, OAuth metadata/PKCE, and a 0600 credential store. A real authorization-server E2E and MCP-specific confirmation UX remain open.

Learning Design from Mature Coding Agents (35): Model Catalogs and Per-Role Routing — rivumi's Role Aliases and Reviewer Lane

rivumi now has static ModelRole/ModelRoute candidates, opt-in aliases such as --model @cheap, cross-provider fallback, and a no-tool reviewer lane that runs after verification. Role inheritance/override rules and automatic summarizer, parser, or scout routing remain open.

Learning Design from Mature Coding Agents (33): Session Recording and Replay — From Event Logs to Safe Forks

rivumi now connects events.jsonl to a deterministic reducer, CLI timeline, canonical JSON, SDK replay, and safe event-point forks. Forking never replays prior tools or model calls; provider/live-runtime validation, redaction, and richer replay hooks remain open.

Learning Design from Mature Coding Agents (32): Subagents and Worktree Isolation — Teaching the Main Loop to Delegate

Mature subagents need roles, bounded fan-out, narrowed permissions, and a result contract. rivumi now has native named-role schedules, parallel fan-out, child allowed_paths constrained by the parent, unsafe execution disabled by default, and parent-approved transaction proposals. Persistent background lifecycles, recursion trees, and automatic worktree merging remain open.

Learning from Mature Coding Agents (34): Telemetry and Cost Tracking — You Count Tokens, Then What?

rivumi now has CostBreakdown, an explicitly estimated static GPT-5-family price table, per-lane usage/cost, and OTel cost fields. Unknown models still show tokens without invented dollars; broader pricing coverage, authoritative external-CLI bills, and live billing reconciliation remain open.

Learning Design from Mature Coding Agents (18): Toolset Design Philosophy — Drawing the Tool Surface Boundary

Rivumi's core surface has grown from seven tools to nine with a read-only `tool_program` and rollback-capable `tool_transaction`; search prefers ripgrep and arbitrary shell remains absent. Native MCP tools join only from allowlisted servers and default to execute approval without trusted read-only metadata.

Learning Design from Mature Coding Agents (38): Agent as a Service — Wrapping Your Loop in Something Other Programs Can Call

rivumi now has a Cloudflare Durable Object run resource with async creation, status/cancel/artifacts, live NDJSON, and Last-Event-ID SSE; remote approvals use a separate short-lived capability. Python also provides an attach client and a stateful conversation WebSocket. Production deployment, cross-runtime parity, and full multi-tenant hardening remain unverified.

Rivumi remote execution on Cloudflare: Worker, Sandbox, Capability DO, and durable RunSession

Rivumi's old synchronous M6 path completed one real deployed coding run. It has since grown into an asynchronous control plane with RunSession, SSE, approvals, cancellation, and artifacts, but that newer path has not been live-revalidated. Audience-separated HMAC capabilities enter the Sandbox while provider credentials stay in the Worker; this is not production-traffic or SLO proof.

Rivumi's disposable workspace and run bundle: why the source repository stays untouched

Rivumi clones an exact Git commit into a detached-HEAD workspace inside the run directory before a runtime edits or verifies code. The source repository, execution workspace, and run artifacts therefore have distinct boundaries. This provides source isolation and an audit bundle, but it is not an OS sandbox.

Rivumi's ExternalCodingRunner: why Codex and Claude Code CLI are external runtimes, not ModelProviders

`ExternalCodingRunner` is Rivumi's second runtime lane. The external coding CLI owns its model loop and credentials; Rivumi hands off a task and disposable clone, then treats the returned patch as untrusted input and reruns path audit, verification, and the source invariant. This is a capability-bounded handoff, not another `ModelProvider`.

Rivumi's ModelProvider multi-gateway: multiple protocols, one canonical contract

Rivumi collapses OpenAI-compatible, Responses, Anthropic, Gemini, Workers AI, scripted, and experimental Codex OAuth adapters into one `ModelProvider` contract. The Codex OAuth transport reads SSE but still reduces it inside the adapter into one canonical `ModelTurn`; AgentRunner does not consume token deltas.

Rivumi's provider-neutral native loop: from one model turn to a verified terminal state

Rivumi's native lane is controlled by AgentRunner: prepare a workspace, request a model turn, execute tool calls, append observations, and enter verification only when the model stops calling tools. Step, wall-time, repetition, token, and cancellation guards can terminate the run independently of the model. Protocol translation belongs to the next article.

Rivumi's state-first event journaling: recovering between manifest commits and JSONL appends

Rivumi maintains append-only `events.jsonl` and atomically replaced `session.json`, reconciling sequences before crash recovery. The same event contract now supports deterministic replay, canonical JSON replay, fork seeds at a selected sequence, and new workspaces without replaying old side effects; ambiguous `tool.started` or `verification.started` states still hard-fail.

Rivumi's tool isolation: path allowlists, strict argv, process groups, and credential-free subprocesses

This article follows one Rivumi tool call through its mechanical execution boundary: `SafePathPolicy` for paths and symlink escape, fixed argv with `shell=False`, a sanitized subprocess environment, read-version hashes plus atomic replace for writes, and process-group cleanup at timeout. Permission policy, OS containment, and tool programs are reserved for later articles.

Rivumi's TUI and CLI: how a run becomes visible in the terminal

Rivumi's TUI and plain CLI are two interfaces over the same runtime paths. The CLI selects a presentation mode from TTY state and flags, runners emit events, and the TUI projects those events into thinking, tool, approval, verification, and terminal states. The screen distinguishes native and external runtimes without treating UI entry points as proof of backend maturity.

A map of Rivumi: how one coding-agent task crosses workspaces, runtimes, tools, and events

Rivumi turns a coding-agent task into inspectable boundaries: native side effects cross Rivumi tools, permissions, and sandboxing, while external runtimes retain their own loops and tools before returning a patch for Rivumi audit. This article maps the planned 20-part series.

Rivumi context pressure, compaction, and workspace reinjection

Near 85% context pressure, Rivumi has two distinct paths: the native loop can apply one bounded deterministic history fallback, while a conversation runtime with native compaction can compact after a completed turn. Both paths re-anchor the next request with workspace context.

Rivumi IDE/LSP Context: Diagnostics, Open Files, and the VS Code Bridge

Rivumi normalizes up to 200 diagnostics and 32 visible files into bounded, repository-local, untrusted context. Its VS Code and managed-LSP paths supply signals rather than completion, rename, code actions, or full IDE RPC.

Rivumi local OS sandboxes: fail-closed execution on macOS, bubblewrap, and Landlock

Rivumi can wrap configured local commands and verification in macOS sandbox-exec, Linux bubblewrap, or Landlock/seccomp. A required unavailable backend stops with exit 126 instead of running bare, but external CLIs, MCP/LSP processes, and the entire Rivumi process are outside this boundary.

Rivumi model roles, fallback, cache hints, and estimated cost

Rivumi uses a static model-role catalog and retries or falls back only after retryable provider errors. Cache data is a provider hint plus trace, while cost is a static-table estimate; neither is live routing intelligence or a bill.

Rivumi Native MCP: transport, authorization, and approval boundaries

Rivumi loads project MCP servers only through an explicit allowlist, projects stdio or Streamable HTTP capabilities into the existing ToolExecutor, and preserves hooks, approvals, timeouts, and cleanup.

Rivumi permission layering: how dangerous commands become allow, ask, or deny

Rivumi applies a non-bypassable critical floor, evaluates user, organization, and project denies before any allows, and keeps execute operations policy-gated even in dangerous mode. This decides authority; it is not an OS sandbox.

Rivumi prompts, instruction precedence, and explicit memory: what the model actually sees

Rivumi resolves user and root-to-leaf project instructions before rendering named prompt sections for runtime, skills, workspace state, and the latest 20 explicit memories. The pipeline is traceable and reloadable, but it is not semantic memory and repository text does not become system authority.

Embedding Rivumi: SDK, ConversationController, and the WebSocket Boundary

Rivumi exposes bounded-run and conversation contracts through a typed 0.x SDK facade. WebSocket attach wraps one prebuilt, controller-owned runtime session rather than providing conversation-ID resume or multi-client routing.

Rivumi Skills, Blocking Hooks, and Plugin Packages

Rivumi treats skills as bounded repository-local guidance, hooks as opt-in host commands that can only deny, and local plugin manifests as packages for skills and hooks; their authority is deliberately different.

Rivumi Subagent Scheduling and Parent-owned Transactions

Rivumi normalizes each subagent dispatch into dependency waves of at most four nodes, runs read-only children concurrently in isolated workspaces, then makes the parent repeat hooks, approval, and transaction execution for any modification.

Rivumi tool programs, transactions, and safe concurrency

Rivumi parallelizes calls only when they are read-only, concurrency-safe, and classified as READ. Tool programs provide bounded read-only repeat and branching, while transactions snapshot and restore possible workspace-file changes; external side effects are not rolled back.

Learning Agent Design from Mature Coding Agents (2): The Shape of the Agent Loop — Event Streams, Checkpoints, Resume

pi's loop is a double while-loop wrapped in an EventStream; claude-code's source openly says stop_reason is unreliable and uses tool_use blocks observed during streaming as the sole continue signal; codex models a turn as a cancellable SessionTask and records sessions with a dedicated rollout crate. rivumi chose an ordering — manifest first, JSONL second — that turns Ctrl-C into verified resumption instead of a rerun. All evidence cited at file#symbol level.

Learning from Mature Coding Agents (13): CLI Ergonomics — Make New Tools Feel Already Familiar

Mature coding-agent CLIs have converged on the same conventions: positional prompt, -p means print, exec is headless, resume is a first-class command, -C changes directory; rivumi inherits this vocabulary directly, driving learning cost close to zero.

Learning Agent Design from Mature Coding Agents (9): External CLIs as a Backend — Where Does the Security Boundary Go?

Every mature coding agent ships a machine interface: codex has `exec --json` plus a full app-server JSON-RPC protocol, claude-code has `-p` with stream-json, and pi/opencode/omp each expose a JSON event stream. Wrapping these CLIs as your backend is the fastest path to subscription-backed coding — but they own their agent loop, their login, and their permission model. rivumi's answer: let the external CLI fully own its loop while rivumi holds only three things — an isolated working copy, patch audit, and final verification. One runtime never impersonates another.

Learning Design from Mature Coding Agents (21): Headless Mode and CI Usage — When Nobody Can Click Approve

The biggest problem when an agent enters CI is approval: no TTY, nobody to click approve. The five reference projects converge on two strategies — delegate permission decisions to the calling program (claude-code's control protocol), or replace approval semantics entirely (codex defaults to Never plus sandboxing, opencode auto-rejects). rivumi keeps one AgentRunner loop and injects a different ApprovalPolicy: headless uses HeadlessApprovalPolicy, which never reads stdin so it cannot hang the pipeline, and denies EXECUTE by default — fail closed.

Learning Design from Mature Coding Agents (20): The Run Artifacts Contract—What Makes a Run Auditable After It Ends?

After an agent run finishes, 'the model said it's done' is not evidence. Codex splits traces into a manifest + JSONL + payloads bundle, omp mirrors on-disk files into SQLite, pi indexes native session files with runs.jsonl. Rivumi picked the strictest option: six fixed files per run, the run is incomplete if any is missing, and patch review reads changes.patch—not anyone's verbal claim.

Learning Agent Design from Mature Coding Agents (19): Session Persistence and Crash Recovery — Rescuing State After the Agent Dies

All five agents store sessions as append-only JSONL plus some form of single-writer protection, but crash recovery lives in the details: pi repairs torn tails, codex reopens and retries after write failures, and rivumi picked a 'manifest first' ordering that reduces the only crash window to one repairable slot. This post dissects each project's write ordering and fail-closed conditions, all cited at file#symbol level.

Learning Design from Mature Coding Agents (17): Startup Performance and Engineering Discipline — It Was Never the Language

A CLI tool pays its startup cost on every invocation, and performance optimization without a baseline means no regression protection. codex uses daemon reuse and skill snapshot caches; claude-code splits its entrypoint into dynamic imports plus a built-in startup profiler; opencode and omp each maintain lazy-loading discipline; pi does none of it and leans on Bun being fast. rivumi is Python — slow by birth — so it applies the full discipline: lazy imports, single-flight disk cache, background controller prewarming, and hyperfine paired benchmarks wired to a CI gate that fails on >10% regression.

Learning Agent Design from Mature Coding Agents (24): Testing a Moving Agent — fake-CLI Contracts, Recorded Streams, TUI Pilot

An agent's two dependencies — the LLM and external CLIs — are both non-deterministic, but mature projects separate 'the moving parts' from 'the shape of the boundary': codex fakes the Responses API with wiremock plus a scripted SSE server and pins its TUI with insta snapshots; opencode built a VCR-style http-recorder package; pi splits model-backed evals from unit tests into two vitest configs; omp wraps its edit benchmark itself in unit tests. rivumi stacks four layers against external CLIs: unit tests, fake-CLI contract tests, recorded-stream integration proofs, and Textual pilot TUI tests. The methodology in one line: record real non-deterministic output, then make deterministic assertions about it.

Learning Design from Mature Coding Agents (15): From Full-Screen TUI to Semantic Transcript

Mature coding agent TUIs never print the event stream directly — they build a typed projection layer first and update it in place. rivumi took three steps (full-screen composition, runtime-first dual modes, removing the Ask/Agent split) before two old constraints — non-streaming output and resume-without-replay — were truly lifted.