Skip to main content
TRW
LEDGER // MEMORY
LOCAL_FIRSTEXPLICIT RECALLBSL 1.1 → APACHE 2030

Project memory a later session can explicitly recall

TRW Memory stores selected project learnings outside the conversation that produced them. When the agent calls session start or recall, ranked candidates can be added to context and re-checked before substantive work; optional graph expansion is shown at right.

OPT-IN GRAPH EXPANSION
0/11 nodesdepth 0
securitysecuritysecuritysecuritydeploymentsecuritysecuritysecuritydeploymentsecuritysecurity
similarityevidence_forsame_root_causeco_anchoreddepends_on
RECALL RESULTS0/5
> "JWT auth security patterns"
LEDGER // STORAGE

Memory that survives compaction

Learnings live in a SQLite store on your machine, with no hosted service required. The trw-mcp memory daemon keeps one file, by default ~/.trw/memory/memory.db, with a separate namespace for each project. Optional sync depends on configuration. Inside your repo, .trw/ holds the project's settings, including which namespace it uses, and a YAML copy of each learning.

Durable storage survives conversation compaction, but context injection is still an explicit ceremony action. The agent or client calls trw_session_start() first, or uses trw_recall(), to retrieve candidates again before substantive work.

Example learning record
id: M-a3f2c1b9
summary: JWT refresh tokens need rotation on every use
tags: [security, auth]
importance: 0.93
created_at: 2026-04-01T09:12:43Z

4000+

repository inventory, not outcome proof

Local

primary SQLite storage

TRACE // RETRIEVAL

Not just vectors. A scoring engine.

Retrieval fuses keyword matching with dense vector similarity (with embeddings installed), then a cross-encoder re-reads the top candidates and sets the final order when its model is available. Utility, built from importance and time decay, does not reorder search results: it orders a recall with no query and, with age, decides what is archived or purged. The retrieval path does not run or observe repository checks.

A learning recorded again decays more slowly. Frequent recall adds a small, capped access boost, while a separate recall-frequency decay lowers an entry's importance the more often it is recalled, down to a floor.

UTILITY FORMULA

search  = keyword + vector fusion, then cross-encoder re-rank
          utility does not reorder search results

utility = importance × max(floor, 0.95^r) × retention
        + access_boost + source_boost
          r = times recalled
          orders recall with no query; with age, gates archive and purge

retention = exp(−(ln2 / half_life) / k^0.6 × days_unused)
          k = recurrence (starts at 1; +1 each time it is recorded again)
          half_life: per type and confidence (14-day fallback)

Utility never reorders search results. It orders a recall with no query and, with age, gates archive and purge.

HYBRID RETRIEVAL PIPELINE

1

BM25 (keyword)

BM25Okapi sparse retrieval — exact match, token overlap

2

Dense (vector)

Cosine similarity via sqlite-vec — conceptual similarity

3

RRF fusion

Reciprocal Rank Fusion — entries present in both lists score higher. The Python library also blends in each entry’s importance (30% by default); the MCP tools fuse on rank alone

4

Re-rank

When its model is available, a second model re-reads the top candidates and drops weak matches, in the Python library and the MCP recall tools alike

5

Utility order (no query)

A search keeps the order above. Only a recall with no query, which has no search ranking, is ordered by utility

Graceful degradation: if the embedding model is not cached, BM25 runs alone and recall stays keyword-only until you run trw-mcp models fetch. Without the re-ranker model, recall keeps fusion order.

BENCHMARKS

What it finds, and what it costs

Memory only helps if the right note comes back when your agent needs it. Here is how often trw-memory finds it on two public benchmarks, how it compares with Mem0 on Mem0's own test, and what it costs to run as your store grows. Methods, raw tables and the full fine print are in the trw-memory README.

PUBLIC BENCHMARK · LOCOMO

10 long conversations, 1,540 questions

85.8%

found in top 10

95% CI 83.9–87.4%

92.7%

found in top 50

95% CI 91.3–93.9%

How often the message that holds the answer came back in the results.

PUBLIC BENCHMARK · LongMemEval

470 questions, each with its own 38 to 62 past chat sessions

93.8%

found in top 10

95% CI 91.3–95.7%

97.4%

found in top 50

95% CI 95.6–98.5%

How often the turn that holds the answer came back in the results.

These are search hit rates with no AI model grading anything: LOCOMO from the trw-memory 4.0.0 release candidate, LongMemEval from 2.0.0. They measure something different from the answer scores most memory products publish, so we don’t put the two side by side. The Mem0 comparison below is graded answers, run the same way on both systems.

KEYWORD + MEANING SEARCH

889 searches over real engineering notes. How often the right note made the top 10.

Keyword search86.9%
Meaning search91.4%
Both, combined93.8%

Combining the two scored highest of the three (point estimates; significance not assessed). Measured on trw-memory 0.9.12.

CATCHING REPEAT WORK

175 times an agent in our own project re-learned something it had already written down. Would a search have turned up the earlier note?

Keyword search72.0%
Both, combined94.3%

The two 95% confidence intervals do not overlap. Measured on trw-memory 0.9.12.

HEAD TO HEAD WITH MEM0

All 1,540 LOCOMO questions, answered and graded the same way for both systems.

Answer accuracy and AI calls to store, Mem0 and trw-memory
MeasureMem0trw-memory
Answers judged correct84.1%88.9%
AI calls to store 5,882 turns1 per turnnone

trw-memory answered 4.8 points more questions correctly, a statistically significant lead (paired 95% interval +2.9 to +6.8, McNemar p < 0.0001), and led in all ten conversations. By default, storing makes no AI calls: trw-memory keeps each turn as written, while Mem0 makes an extraction call for every write.

Method: Mem0’s evaluation harness on all ten LOCOMO conversations. Each system answered from its top 10 memories with the same reader and judge (gpt-4o-mini) and the same prompts. trw-memory 2.0.0 with bge-small-en-v1.5 against self-hosted mem0ai 2.0.20 with all-MiniLM-L6-v2; the embedders differed. September 2026.

COSTS THAT STAY SMALL AS IT GROWS

Time per operation on one machine, before and after our September 2026 work.

Time per operation before and after
OperationBeforeAfter
Ingest per conversation turn, shared store1,464 ms15 ms
Save with 20 projects sharing it708 ms15 ms
Housekeeping per search, 20,000 notes289 ms1.3 ms
Scan per search, 20,000 notes60.5 ms3.2 ms
Link related notes, 10,000 notes12.4 ms2.3 ms

Each of these used to slow down sharply as the store grew or as more projects shared it. Profiling cut them by 2× to over 200×. Single runs on one machine.

MEMORY ACROSS SESSIONS

58 / 58

with memory

0 / 50

without memory

Tasks finished

We built tasks that can only be finished with a fact from an earlier session. With memory, agents finished all of them. Without it, none, because the fact existed nowhere else (paired McNemar p = 3.6×10⁻¹⁵ over 49 matched pairs). The result held on a second model family.

The tasks were built to need a fact from an earlier session, so this shows what recall across sessions makes possible, not a general measure of coding performance.

LATTICE // GRAPH

A typed knowledge graph, not a flat index

Each learning can become a node and relationships can become typed edges. When a caller explicitly enables graph expansion, BFS traversal from a matched root can surface related entries that share no query keywords. Graph expansion is disabled on the default recall path; the hero demo visualizes the opt-in capability.

INFERRED SIMILARITY

  • similarity

    Cosine similarity above threshold

  • tag_cooccurrence

    Shared tags, Jaccard-weighted

  • related_to

    General associative relation

  • co_anchored

    Entries anchor to one source

LIFECYCLE + PROVENANCE

  • consolidation

    Merge lineage

  • anchored_to

    Bound to a source file

  • produced

    Action generated the entry

  • motivated_by

    Created in response to another

  • supersedes

    Newer entry replaces an older one

DECLARED REASONING

  • same_root_cause

    One failure mode

  • depends_on

    Validity depends on another entry

  • evidence_for

    Empirical support for another entry

  • conflicts_with

    Contradictory entries

When enabled, BFS traversal depth is capped at 3. Cross-edge propagation rates vary by type: evidence_for propagates impact at 30%, co_anchored at 20%, same_root_cause at 15%.

TRACE // SESSION_START

Required first call, inspectable recall path

TRW requires the agent to call trw_session_start() as its first TRW action. The call is explicit: storage does not autonomously place memories into a prompt, and optional client hooks are only additive reminders.

  1. 01Agent callsSession start supplies project and task context to the memory query.
  2. 02Memory ranksKeyword and dense search are fused and re-ranked into a bounded candidate list.
  3. 03Agent re-checksCandidates enter working context and must be verified against the current repository before reuse.

Explicit deposits use trw_learn(); targeted lookups use trw_recall().

ILLUSTRATIVE TRACESession start (example, not measured telemetry)
01trw_session_start() called
02Load learnings index
03BM25 keyword scan — 31 candidates
04Dense vector search — 28 candidates
05RRF fusion — 44 unique entries ranked
06Cross-encoder re-rank, weak matches dropped
07Inject top 8 learnings into context
→"JWT rotation required on every use" (0.91)
→"Env vars must not have prod defaults" (0.94)
→+6 more …

Order is real; timings are omitted deliberately. Run-to-run latency varies by index size and whether embeddings are enabled.

LEDGER // SPEC

Technical specification

DEFAULT PATH

StorageSQLite in WAL mode, one namespace per project
RetrievalKeyword/BM25 path with graceful fallback
LifecycleExplicit learn, recall, update, and forget tools

OPTIONAL CONTROLS

Dense retrievalsqlite-vec vectors + RRF fusion when embeddings are installed
Cross-encoder re-rankLibrary and MCP recall alike, when sentence-transformers and its model are available
Graph expansion13 edge types; opt-in recall expansion, disabled by default
SecurityRBAC, PII, and poisoning controls are configurable
Backup / syncYAML backup and remote sharing depend on configuration

PACKAGE SURFACE

ScoringRelevance, time decay, and recall-frequency decay
IntegrationsLangChain · LlamaIndex · CrewAI · OpenAI-compatible adapter
LicenseBSL 1.1 · converts to Apache 2.0 on 2030-03-21
Memory across project boundaries

Share with authorisation. Keep the source.

A useful discovery may apply beyond one repository. Choose the sharing boundary explicitly; relevance and supporting evidence do not grant permission to cross it.

Project recall stays scoped

MCP recall reads the current project namespace and machine-wide user-scope learnings. It does not search other projects' namespaces in that store. Keep secrets and project-specific sensitive knowledge out of user scope.

Shared stores are a separate choice

Standalone cross-validation uses explicitly co-located namespaces and compatible embeddings. Hosted team sync is opt-in. Namespace labels are not an access-control guarantee; verify storage access and configuration before sharing sensitive material.

Read the storage and sharing boundaries
LEDGER // CONSTRAINTS

What memory does not do

Accurate scoping saves debugging time later.

No pre-populated graph

The knowledge graph builds entirely from entries you deposit. A fresh install has no edges and no semantic clusters — those emerge over sessions.

Recall frequency cuts both ways

Search results are ordered by relevance; utility orders only a recall with no query and decides what is archived. Frequent recall adds a small, capped access boost, and a separate recall-frequency decay lowers importance, down to a floor. A learning recorded again decays more slowly.

Embeddings are optional

Dense vector search needs the [embeddings] extra, which the installer adds by default. Without it, retrieval falls back to BM25 keyword matching only — still useful, not identical.

Memory does not self-correct wrong entries

If an agent stores an incorrect learning, it persists until it is explicitly forgotten or superseded. Memory is as reliable as the agents depositing into it.

Not a replacement for checkpoints

Memory stores learnings — patterns, gotchas, decisions. Checkpoints save resumable execution state. They are complementary, not interchangeable.

Recall is an explicit action

The agent or client must call session start or recall. Optional hooks can remind or invoke compatible paths, but storage alone does not inject context.

Graph expansion is opt-in

Typed graph traversal is available when recall enables graph expansion. The default recall path does not traverse graph neighbors.

LEDGER // FAQ

Common questions

What is the difference between TRW Memory and Claude Code's built-in memory?

They are separate systems with different contracts. Claude Code supports project instructions plus auto memory, including a bounded startup index and topic files loaded on demand. TRW exposes an MCP-accessible project store with explicit learn, recall, update, and forget operations; optional dense retrieval, graph expansion, and cross-project sharing depend on configuration.

Does TRW Memory send code or project data to a server?

Learning sharing, telemetry uploads, and merging pulled team learnings stay off without opt-in configuration. A signed-in install checks for updates at session start and asks for team learnings every five minutes until you set `platform_contact_enabled: false`. trw-mcp keeps memory in the loopback daemon’s SQLite file, one namespace per project, by default `~/.trw/memory/memory.db`; the Python library on its own defaults to `.memory/` under the current directory. Installing, fetching models (`trw-mcp models fetch`), device sign-in, or explicitly invoking a networked tool use the network; loading a model at runtime does not, because models load from the local cache only. The opt-in decision judge sends redacted entry text to its judge endpoint (OpenRouter by default) only when `TRW_JEV_ENABLED` or `assess_enabled` is set and an `OPENROUTER_API_KEY` is present; leave both unset, or set `TRW_JEV_ENABLED=false`, to keep it off.

What happens to recalled learnings when context compacts?

The durable entries remain in SQLite when conversational context compacts. On continuation, the agent or client must call `trw_session_start()` or `trw_recall()` to retrieve relevant candidates again; optional client hooks are additive reminders, not the storage guarantee.

How long before Memory starts being useful in a new project?

A successfully stored learning can be recalled immediately. Usefulness depends on the quality, relevance, and validation state of the corpus—not a fixed session count. Cross-project recall additionally requires eligible namespaces and configured sharing policy.
TERMINAL // INSTALL

Give your agents persistent memory

Install the open framework, store one material project learning, then retrieve and re-check it from a later session. The tool signatures, defaults, and storage layout are in the memory spec.

TERMINAL~/repo

# install

$ curl -fsSL https://trwframework.com/install.sh | bash