Memory

Recall should filter, not flood.

A bag of keywords gives every term the same voice, so retrieval either drags in everything that loosely matches or misses the one thing that mattered. Verity tags each memory from five distinct lanes and gives every tag a computed importance, then funnels a query through those weights before a single memory is scored.

entity0.75intent0.70domain0.55temporal0.40lexical0.20FUNNELscore survivors, keep top-kweak-onlyoverlapdropped
5extraction lanes
10+tags per memory
0.60importance gate
0.70bridge discount
Five lanes

Not every word deserves the same vote.

Each lane has a base weight. Entity and intent are what make a memory durable, so a single strong tag from either can carry a memory through the gate on its own. Lexical cannot, by construction.

entity0.75The nouns a memory is about: people, projects, files, tools.
intent0.70What the exchange was for: a preference, a decision, a correction, a mistake.
domain0.55The subject area the memory sits in.
temporal0.40When it applied, and whether it still does.
lexical0.20Bare surface words. Deliberately the weakest voice in the room.
The ceiling

A weak tag can never promote itself.

Base weights are modulated additively and clamped. Work the lexical lane all the way up (stated first, repeated to the cap, framed as a standing truth) and it still lands under the importance gate.

That is not a tuned threshold, it is arithmetic. It is why surface-word noise cannot smuggle a memory into your prompt.

  • +0.10positionStated early beats stated in passing.
  • +0.04repetitionPer extra occurrence, up to three.
  • +0.15durabilityThe user framed it as standing: always, never, from now on, I prefer.
lexical, fully modulated
0.20 base
+ 0.10 position
+ 0.12 repeat ×3
+ 0.15 durable

= 0.57 < 0.60 gate

A lone lexical tag is never enough to spend tokens on. Two of them, together, are, and that threshold is the only place the weak lane gets a say.

Recall, in order

Four steps, and no step is optional.

  1. 01ExtractThe query goes through the same five lanes as a memory does. Same text in, same tags out. The extractor is rules, not a model, so it never drifts.
  2. 02CandidatesThe tag index returns memories that share a tag. The cost is proportional to matched tags, not to how many memories you have.
  3. 03FunnelAny matched tag at or above the gate lets a memory through. Otherwise it needs at least two weak matches. One faint overlap is dropped, and a dropped memory is text that never reaches a prompt.
  4. 04ScoreRelevance scoring runs on survivors only, then top-k. The expensive step is the last step and sees the smallest set.
Per-tenant tag registry

The vocabulary is minted from your own words.

Weights alone still fail on wording. Ask about AI and you miss the memory filed under large language model.

So each tenant grows a registry as they use the system. A candidate tag is canonicalised before it is stored, near-duplicates are recorded as aliases of the canonical form, and tags that keep appearing together are bridged as siblings.

Alias

LLMslarge-language-model

Same concept, different words. Resolves at full weight, because nothing was actually different.

Bridge

artificial-intelligence large-language-model

Different concepts that this tenant keeps using together. The sibling rides in at a discount: enough to pull a memory through the gate, never enough to pretend it was a direct hit.

Bound

registryMAX_TAGS

Aliasing is what keeps the registry from growing without limit, and recall never adds to it, so a query cannot poison the vocabulary with its own noise.

BoundThe registry persists to Postgres, degrades to a JSON file in the vault, and degrades again to an in-process registry with a logged warning if both fail. Memory itself runs on cognee with an Obsidian vault as the durable fallback, so losing the graph costs you recall quality, not your notes.

Memory you can audit, in files you can read.

Every tag, weight and bridge lands in a vault you own. Open the workspace and watch a conversation get filed.