Skip to content
← Work

Agent memory & data systems

Engram

A bitemporal memory store for agents that won't let late-arriving or contested facts overwrite what is currently true.

Solo — data model, conflict rules, storage engine & evaluation2026In progress6 min read
TypeScriptNode.js 22 · node:sqliteSQLite FTS5node:testGitHub Actions
0/6
stale answers · baseline 3/6
19/19
correct answers · baseline 11/19
25
contract tests in CI
0
runtime dependencies

The domain

Agents that remember things accumulate facts that change: a release cadence moves from weekly to biweekly, a region migrates, two sources disagree about the same moment. Engram stores every fact with two times, when it became true and when it was learned, and resolves each conflict with a named, logged rule instead of letting the latest write win. It is a TypeScript library on Node's built-in SQLite and FTS5 with no runtime dependencies. The source, tests and benchmark are public.

01 · Problem

The problem

Most agent memories are append-only: every observation is stored, and retrieval ranks by relevance and recency. That works until facts change. A piece of history learned late, such as "the cadence was weekly in production from Jan 10" recorded on Feb 5, is the newest write, so a recency-ranked memory presents it as current even though a revision made it obsolete on Jan 20.

Contested claims are the second failure. Two sources assert different values for the same moment, or a low-confidence report contradicts an established fact. An append-only memory has no notion of either, so whichever ranks higher wins.

The first version could not demonstrate any of this. Its test suite did not load, the store failed on its first insert, and its benchmark's baseline read through the same time-aware query path as the governed store, so the quality gate it defined could never pass.

02 · Approach

Approach & key decisions

Store two times, read as of either

Each fact carries validFrom (when it became true) and writtenAt (when it was learned). An as-of query returns only facts written and in effect at that moment, including facts superseded later, with the status they held then. "What did we believe on Jan 5?" stays answerable after the Jan 12 revision.

Resolve conflicts with named, logged rules

A newer fact in the same scope supersedes an older one (R1). Distinct contexts such as prod and staging coexist (R2). Late history, same-time disagreements, and claims more than 0.1 less confident than an established fact are flagged for review instead of applied (R3). Every decision is written to a resolution log in the same transaction as the insert.

Make writes idempotent and recall auditable

A fact's id is a SHA-256 of its subject, text and valid time, so replays keep the first provenance. Recall uses SQLite FTS5 over subject and text, kept in sync by triggers, and a regression test checks the index against its content table with FTS5's integrity check.

Repair the foundation before measuring anything

Getting the suite to run surfaced nine store defects. They ranged from statements prepared before their tables existed and an insert binding 13 values to 14 columns, to an as-of filter that made the supersession branch dead code and a context rule that made the final state depend on insertion order. Each was fixed in its own commit against the contract suite.

Give the baseline a real chance to fail

The original append-only arm read through engram's own time-aware queries, so it could never return a stale fact and the stale-recall gate was unreachable. The redesigned baseline models a typical agent memory: known once written, no valid time, latest write wins ties. It keeps relevance-first ranking, so the comparison isolates governance rather than ranking strategy.

Fix the answer key, then probe the failure directly

Nine expectations contradicted the data or the rules, including stale probes that rewarded the stale answer, a query term that matched nothing, an inclusive as-of boundary scored as exclusive, and a revision scored as a contradiction. Three new probes ask in outdated terms, such as "beta region us-east" after the move to us-west, which is how stale answers reach users in practice.

Prove where the gain comes from

A sabotage arm keeps engram's time-aware reads but bypasses write-time governance. It scores exactly like the baseline (3/6 stale, 11/19 correct) and fails the gate, so the improvement comes from supersession, not the read path. The gate runs in CI with its original thresholds, and disabling supersession fails the test suite.

Check the limitations by running them

While this case study was written, a suspected limitation was reproduced instead of being described, and it turned out to be a bug: a contested fact that was later superseded came back as the answer for earlier dates. The fix records each fact's status at supersession, under a new versioned schema whose migrations also rebuild indexes from older databases. A backdated write is now also checked against facts recorded after it, so out-of-order imports converge on the same state as in-order ones.

03 · Architecture

How it fits together

Engram — governed writes, bitemporal readsArchitecture

Write path

Incoming fact
valid time + write time
Stable id
sha-256 · idempotent
Conflict plan
R1 supersede · R2 coexist · R3 flag
One transaction
fact + links + resolution log

Read path

As-of query
any past moment
FTS5 recall
subject + text
Status at time t
written ≤ t · valid ≤ t
Current fact
or nothing known

Benchmark gate in CI

Governed
0/6 stale · 19/19 correct
Append-only baseline
3/6 stale · 11/19 correct
Governance bypassed
baseline numbers · gate fails
Versioned schema, migrations on open
25 contract tests · strict typecheck · WAL
Every write is planned against what was already known and committed together with its resolution log. Reads filter on both times, so history stays queryable. The benchmark's sabotage arm keeps the reads but drops governance, which is how the gain is attributed.

04 · Results

Results

  • Governed store: 0/6 stale facts returned and 19/19 correct answers, counting correct "nothing known" abstentions. Append-only baseline: 3/6 and 11/19.
  • With governance bypassed but engram's reads kept, results matched the baseline exactly and the quality gate failed, which isolates the gain to write-time supersession.
  • Contradiction detection found all 3 same-time conflicts in both arms. Precision was 3/5 governed against 3/8 append-only.
  • The gate's thresholds (a 15-point stale-recall improvement and 80% contradiction recall) are the original ones. The governed store clears them with a 50-point improvement and 100% recall.
  • Write-ahead logging more than halved the cost of a durable governed insert, from 3.9 ms to 1.8 ms over 3,000 conflicting writes, with every commit still synced.

05 · Tradeoffs

Honest limitations

  • The benchmark is 29 events and 27 queries, written by hand, and its answer key was corrected by the implementation's own author rather than an independent reviewer. Perfect governed scores show the rules behave as specified, not that they generalise.
  • Recall is lexical: FTS5 with every query term required. Paraphrases and synonyms are not found, and the outdated-phrasing probes depend on that behaviour.
  • Contradiction precision is 60% because detection also pairs flagged revisions with the fact they failed to replace. Those pairs are pending review rather than true same-time contradictions.
  • Out-of-order writes converge to the same state as in-order ones, with one exception: a stored later fact that R3 would have flagged because of a backdated fact is not retroactively flagged, so the pair surfaces as an unresolved contradiction.
  • Engram is a library with no production deployment yet.

06 · Next

What I'd do next

  • Add semantic recall alongside FTS5, and evaluate against an independently written query set so the result no longer depends on wording chosen by the author.
  • Retroactively re-flag stored facts when a backdated write would have contested them, closing the last gap between out-of-order and in-order imports.