Architecture
A Go core that orchestrates and does no tensor math, five memory systems behind one retrieval layer, three modes that fence what the model can reach, and a boot sequence where every degraded tier is still usable. This page is the whole design.
The Go core
Orchestration only. No tensor math. A single static binary. The core runs the agent loop, dispatches tools, manages context and holds state. It never spawns or supervises a model server — it pings endpoints.
Core Skills
A procedural spine baked into the binary: how to tool-call, how to answer without filler, how to work and research. Not learned, not editable. It is the invariant system prefix, which matters for more than tone — keeping it stable is what lets the engine's prefix cache survive across turns.
The cycle
Observe, think, act, repeat.
exit status 1 — a model cannot self-correct from an exit code.
The five memories
All five live behind one retrieval layer, and one Typesense instance holds every type, tagged by memory_type.
1 · Working — the recall layer
System-owned, never model-invoked. It fires automatically at turn start and on context shifts: a steer, a plan-step change, an error (which pulls similar past errors and their fixes). The query is built from current context, ranked by hybrid vector plus keyword, deduped by document id, and budget-capped into memory pulls.
It merges the Typesense index with the live tail of events.jsonl, so async indexing lag can never hide a recent event.
2 · Episodic — the session log
Append-only and immutable: messages, tool calls and results, decisions, plan state, timestamped events. One JSONL per session — replayable, crash-safe, git-friendly. Read directly by the core and not searched; searching is Typesense's job.
A write-behind indexer keeps a cursor on the last indexed event. If Typesense goes down the cursor stalls while events keep appending; when it returns, indexing replays from the cursor. Self-healing, because the file is the source of truth.
3 · Semantic — curated, cross-session
Facts, decisions and preferences. Written by the remember tool and by promotion from episodic. Four properties matter:
- Single writer. The curator serialises all writes — no races.
- Never deletes. Corrections supersede, through a
superseded_bychain. - Provenance on every document — the source episodic event ids, so "why do you think this?" is always auditable.
- Degrades without losing writes. If Typesense is down, candidates park as
pending_semanticepisodic events and drain through the dedup gate on recovery.
The dedup gate embeds each candidate and runs k-NN against existing documents:
| Similarity | Action |
|---|---|
| > 0.9 | Merge into the existing document: bump confidence and last_seen, add a source reference. |
| 0.7 – 0.9 | Create, and link related_to. Surfaced in the panel for review. |
| < 0.7 | A new document. |
4 · Codebase — the structural graph
Pure-Go extraction: go/ast for Go, tuned regex for eleven other languages. No tree-sitter and no cgo, which is a core reason the project is in Go at all — it keeps the single static binary. Definitions and call edges, re-indexed incrementally on mtime.
Stored in SQLite rather than Typesense, because the repository is the source of truth and the graph rebuilds from it in seconds. Measured against read plus grep: about 10× lower token cost and 2.1× fewer calls.
5 · Procedural — skills
A folder of markdown skills the user adds. Progressively loaded only when relevant, so the window stays lean. Prose playbooks stay documentation; executable capability migrates to RFX.
Window management
Memory is the state; the window is a projection. Nothing is destroyed when the window shrinks — the stores still hold it.
The watermark policy decides when to act, counted with the real tokenizer rather than estimated:
| Zone | At | Action |
|---|---|---|
| Green | < 60% | Append freely. |
| Yellow | 80% | Batch-demote the oldest raw content to pointers — one cache invalidation, not churn. The pinned zone is untouchable. |
| Red | 95% | Forced handback or a hard tail trim. |
Per-mode budget profiles differ: Discussion runs a small tail with capped prose, Brainstorming a large pulls budget with research externalised to notes, Autopilot a fresh window of plan payload plus step-scoped pulls. Implementation detail is on Context window.
The tool registry
Single source of truth for tools, grammars and guards. Each entry carries name, argument schema, mode matrix, risk tier, ingress cap, retry class and executor.
Thirteen default tools are baked into the binary. Recall is deliberately absent from the mode matrix — it is system-owned and always on. See Tools.
Boot and degradation
Data-first: load config, open the session store, connect Typesense if reachable, panel live. No model is needed to browse. Opening a past session replays its events.jsonl into a read-only window — full history, reports and decisions, with zero components running.
| Tier | Needs | You get |
|---|---|---|
| T0 | files only | Browse and replay every past session. |
| T1 | + Typesense | Keyword recall. |
| T2 | + embedder | Vector recall. |
| T3 | + model endpoint | The full agent, all modes. |
Only T3 hard-requires a model. Missing components degrade; nothing crashes. A readiness gate runs parallel checks before anything enters the loop and blocks only what the requested tier actually needs, with a per-component status card and one-tap fix hints.
Turn-boundary hooks
Zero extra inference, zero user wait. Everything below runs after the answer has already been delivered.
Control flow
The prefix cache survives all three; aborted partials are logged but not kept in the window; and all of them resume through episodic replay.
The verification loop
Three tools exist so the model can check its own work rather than assert it:
serve runs an in-process file server in a goroutine that outlives the tool call, jailed to the workspace, binding synchronously so a port clash is a real error.--disable-gpu made every Three.js page report a false "no WebGL context".The guidebook
The core's book of mechanical self-fixes, consulted when a tool call fails: a busy port becomes the next port, an invalid regex becomes a literal search. The registry repairs the arguments and retries, bounded at eight, prefixing the result with [auto-fixed] naming what changed. Real errors — missing files, failed matches, guard denials — fall through untouched.
The rules live in code, not in the prompt. Prompt advice is a suggestion a small model may ignore; a guidebook entry always runs. New rules must be mechanical (no judgment call), loss-free (adjust the how, never the what) and always disclosed.