Validity, not similarity
The retracted claim is the nearer match
Agent memory that keeps its history holds both the claim and the correction, and on cosine similarity the retracted claim often wins. One pair of memos from RE-call's own demo corpus shows the failure exactly, and why it is not a tuning problem.
An agent that runs for months accumulates memos: decisions, incident notes, configuration facts. Keeping the history is a feature, because the reason behind a change is worth as much as the change. But it means the corpus contains claims that were later retracted, sitting beside the corrections that retracted them. RE-call ships a small fictional corpus for its quickstart, and this pair from it is the whole argument in two files.
# Pricing snapshot cache TTL The cache TTL for the pricing snapshot is 15 minutes. Entries are refreshed lazily on the first read after expiry. Status: adopted.
--- supersedes: cache_ttl_v1.md --- # Snapshot caching revision After the stale-quote incident, snapshot entries now expire after 60 seconds and are refreshed proactively by a background worker. This replaces the original lazy expiry choice.
Now ask the question an agent would actually ask: how long do pricing snapshot cache entries live?
The first memo answers in the vocabulary of the question. It says cache, it says TTL, it says how long, and it states a number with the confidence of a document that was, at the time, correct. The revision is worded around an incident and a worker; it is the truer document and the worse lexical match. On a plain vector index, the retracted 15 minute answer comes back first, and it comes back looking exactly like a good result: high similarity, clean text, no hint that its own corpus disagrees with it.
Why a better ranker does not fix this
This is the point where the instinct is to reach for a stronger embedder or a cross-encoder. That instinct is wrong in an interesting way: a better model makes both memos rank higher, because both are genuinely about the question. The problem is not that the ranking is inaccurate. The problem is that similarity is the wrong axis. Whether a document is close to the question and whether it is still true are independent properties, and a ranker that only sees the first has no way to prefer the correction. The information that decides the case is not in either document's text; it is in the relationship between them.
Declare the relationship, then enforce it per hit
RE-call's answer is to make that relationship a first class part of the corpus. The revision declares supersedes: cache_ttl_v1.md in its frontmatter (the vocabulary is a small open spec, Validity Frontmatter, published separately under MIT). At query time, every hit carries a verdict, a confidence and provenance. The stale memo is still retrievable, because history is a feature, but it comes back marked superseded, pointing at the document that replaced it, and the revision wins the ranking it deserves.
PostgreSQL is not a storage detail in this design; it is the implementation. Retrieval fuses pgvector cosine search with PostgreSQL full-text search under reciprocal rank fusion. Tenant isolation is row-level security, not application code. Indexing is serialised with advisory locks, so two indexers cannot interleave. Corpora are promoted as immutable generations, which is what lets a calibration stay bound to the exact data it was fitted on. If you already run PostgreSQL, the memory layer lives under your roles, your backups and your monitoring, and with local embedding models it builds and answers without any memory layer LLM call.
The third question is refused
The quickstart asks three questions, and the third is one the corpus cannot answer: who painted the mural in the town library? Nothing in the corpus is about murals, but a nearest neighbour search does not know that; it returns the nearest neighbour regardless, because that is all it can do. RE-call fits a threshold to the corpus and refuses below it, with a reason, so the caller can say "I do not know" instead of paraphrasing an irrelevant document.
A detail from building the demo says more about this than any benchmark: the first candidate for that third question failed. Measured against this corpus on 2026-08-22, its top cosine was 0.505 against the 0.50 development threshold, so the demo would have answered over a caption claiming it refused. The replacement was chosen for its margin: top cosine 0.446, which is 0.054 clear of the threshold. Both measurements are recorded next to the query list in recall/quickstart.py, with the command that re-measures them. Abstention is a claim about a specific corpus and a specific threshold, and it has to be measured there, not assumed.
See it in two commands
pip install "recall-rag[fastembed]" recall quickstart
That provisions a throwaway PostgreSQL with pgvector in Docker, indexes the corpus above, and answers the three questions: one answered, one where the correction beats its own retraction, one refused. recall quickstart --remove tears it down.
Where the boundary is
Declared supersession beats similarity ranking on the cases where the edge is authored, and that is the honest scope of this post. RE-call does not infer missing supersession edges from prose, and its abstention works on far gaps while near misses need a stronger answerability layer, which is measured and stated rather than glossed over. The full interpretation, including the negative results, is in results/FINDINGS.md, and every published number is tied to a committed artifact checked in CI.
RE-call is Apache 2.0, on GitHub and PyPI. The setup guide is here.
