Architecture
The one structural claim RCLL makes: reading memory never invokes a language model. Everything else on this page is that claim, spelled out.
What happens on a recall
A memory_recall is five phases, in this order:
- Embed the query. One forward pass through a local sentence embedder,
BAAI/bge-small-en-v1.5by default. 33M parameters, runs on CPU. - Four retrievals, in parallel. Dense vector search over pgvector; BM25 lexical search over a Postgres text index; graph activation spreading out from entities matched in the query; and a temporal pass that resolves time expressions against fact validity windows. Each returns a few hundred candidates.
- Reciprocal rank fusion. The four ranked lists are merged into one. In our store this typically fuses about 1,500 candidates down to a single ordering.
- Rerank. A local cross-encoder —
ms-marco-MiniLM-L-6-v2, about 80 MB — scores the top 300 candidates against the query directly. This is a classifier, not a generator: it emits one relevance score per pair, no text. - Cut to budget. Take facts down the reranked list until the token budget is spent (4,096 by default) and return them.
No step in that list calls a completion API. The only models involved are the embedder and the cross-encoder, and both default to local execution — no network egress on a read at all.
How to check that rather than trust it
Two properties hold in the source tree and are worth verifying yourself when the repository goes public:
- The search package contains exactly one file that can reach an LLM
(
think_utils.py, an optional answer-synthesis helper). Thememory_recallMCP tool has no parameter that reaches it, so from the protocol surface it is unreachable. - The search package contains zero INSERT, UPDATE or DELETE statements. Reading does not mutate the store — not an access counter, not an audit row. The audit logger is wired to background consolidation tasks, not to recall.
The practical consequence is that a read-only deployment is a real thing and not a promise:
a separate process serving only memory_recall, against a Postgres role granted only
SELECT, on a bank you chose to expose. Set LLM_PROVIDER=none and the box holds no
API key at all — there is nothing on it to leak, because there is nothing on it to spend.
What LLM_PROVIDER=none actually gives you
Precisely, because this is easy to over-read in our favour. Keyless is a supported configuration and the service runs: retain accepts documents, recall answers, both the vector and the lexical channels work. But retain switches to chunk mode. Whole chunks are stored and embedded instead of being decomposed, which means no fact extraction, no entity resolution, no causal links, and reflection and consolidation disabled.
That is a functioning chunk store with hybrid retrieval — a real thing, and a smaller thing than the store described everywhere else on this site. If somebody reads "the read path never calls a model" and concludes "so RCLL needs no model at all", they will install it and get a different product than the one they read about. The read path costs nothing; the write path is where the system earns the structure it later retrieves.
There is a third option between those two. The engine ships an offline provider that runs a small local model (~2B parameters, GGUF, loaded in-process) for extraction, so a fully keyless deployment can still extract facts. We have not measured what that substitution costs — a smaller model has to emit a strict schema of typed, dated, entity-resolved facts, and that is exactly where small models fail. It exists; we are not yet telling you it is as good.
One part is free either way: room and hall assignment is 176 lines of regular expressions, not a model call. The scoping axes are the cheapest thing in the system.
The write path is the expensive half, and we say so
Symmetry matters here, because vendors quote "token savings" measured only on reads.
memory_retain does call a model: it extracts atomic facts from the incoming text,
types them, dates them, resolves entities and decides what supersedes what. That is a real LLM
cost per document, and on that side of the ledger RCLL is not cheap.
So any token accounting you see from us has two columns, read and write. Ours reads for free and pays on write. A system that does lightweight extraction and heavy retrieval has the opposite shape. Comparing only one column decides the answer before the measurement starts.
Storage
One PostgreSQL database with pgvector. Facts (memory_units), the
documents they were extracted from, the links between them, resolved entities, and consolidation
state all live in ordinary tables you can query with psql. There is no proprietary
index format and no second datastore to operate. If you want to know what your agents believe,
SELECT is a supported interface.
Where the time goes
Measured, not estimated: the cross-encoder is 85% of recall latency on CPU, and everything else together is under 0.3 s on a store of 8,300 facts. It is also the single largest quality gain we can measure — on LoCoMo it moves nDCG@5 from 0.55 to 0.77 and changes which document ranks first on more than half of all questions. The most expensive stage is the one doing the most work, which is a defensible place to be and still a real cost. The full per-phase table and the retrieval results are on the numbers page.