Skip to content

Build1 publisher3 min readPublished

Keying agent memory by session produced six copies of one test user's risk tolerance

A dev.to writeup by nasiko_labs describes a semantic memory tier whose first version inserted a row per session, so one agent could read "cautious" and "aggressive" at once. The rewrite keys each belief by fact type and archives the superseded version.

The Engineer · Build desk

What happened

  • The first version of the semantic tier keyed facts by session, and after a handful of sessions the store held six copies of one test user's risk tolerance, some contradicting each other, with nothing marking which was current.
  • Retrieval ranked those rows against each other, so a downstream agent could receive both "cautious" and "aggressive" in the same context window.
  • The rewrite keys every belief by fact type, such as risk_tolerance or house_goal, independent of session, so ten sessions restating "cautious" produce a single belief.
  • In the same version the transaction analysis agent invented income growth it had never been told, and the team added a grounding rule to answer "unknown" instead of estimating.
  • A second bug ran deeper: the store had been created without an embedding index, so nothing was ever vectorized and the supposedly semantic search was keyword matching.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Keying by fact type bounds the tier by how many distinct things are known about a user, so the size of the store stops tracking how long that user has been talking to the agents.
  • cost Each extracted fact now buys a key lookup and an LLM comparison before it can be written, and that bill lands on the post-session projector instead of inside the user's turn.
  • decision Anyone standing up a vector-backed memory store has a cheap acceptance test available: assert the vector table is populated, then ask a paraphrased question and check the right belief comes back.
  • exposure Whether a reversal is recorded as a contradiction now rests on an LLM's three-way classification, and the post publishes no accuracy figure for it.

Only one field is embedded. An asynchronous projector reads the raw episodic log and asks an LLM to break each entry into typed, self-contained fact sentences, and the store is configured to embed that text sentence alone [8]. Everything else stays plain metadata for identity, filtering and audit: the key, the version, the flags, the provenance [9]. At read time the agent's question goes through the same model and the nearest stored vectors win [10]. "What is her appetite for investment risk?" and the stored sentence share almost no vocabulary, and they still match, because both are compared by meaning [11].

Keeping those two moments apart is what makes the tier safe to run on a cheap embedding model. Which belief is which is decided by the stable key, and the embedding only decides ranking at retrieval time [12]. "A weak embedding model can degrade what surfaces first; it can never corrupt the record," nasiko_labs wrote [13]. The post compresses the division of labor to three words each: "embeddings retrieve, keys identify, metadata governs" [14].

Writes go through a search-then-decide loop. The projector fetches the existing belief under the key, then an LLM compares old against new and returns exactly one of three verdicts [6]. SAME appends the session to the provenance list and creates no version. UPDATE archives the old version and writes the new one. CONFLICT archives, supersedes, and sets the contradiction flag [7].

The flag is the part I would copy. A downstream agent can be told that the user reversed a stated preference, and it does not have to infer the reversal from two rows that happen to rank next to each other. The price is one key lookup and one LLM comparison per extracted fact, paid after the session by the asynchronous projector [21]. Under the session-keyed first version, ten sessions restating the same preference inserted ten rows for one key; the fact-keyed version ends with one belief and ten provenance entries [20].

For the index bug the fix was a runtime check: assert that the vector table is populated, and that a paraphrased query actually retrieves the right belief [17]. A paraphrase is the probe that separates the two implementations. Keyword matching returns something plausible whenever the query and the stored sentence share words, and it misses when they do not [11].

The post reports no accuracy, latency or cost figures, and the running example is Priya, a persona from the synthetic scenario the design was run against [22][18]. So the case for one belief per fact, current, with versioned history behind it, is an argument from construction [19]. It transfers if your agents read a single current value per fact type, and if the set of fact types stays bounded [5]. If what an agent needs is the trajectory, the current row is the wrong thing to query, and the versioned history is what the design keeps in order to answer it [19].

What to watch

  • Whether nasiko_labs publishes accuracy for the SAME/UPDATE/CONFLICT classification on anything other than the synthetic Priya scenario.
  • Whether the contradiction flag reaches downstream agents as a signal they can read, or stays an audit field.
  • Whether the fact-type key list is fixed in schema or extended by the LLM, since a drifting key set reintroduces duplicate beliefs under different names.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories