DEV Community

Cover image for Nowhere to Put the Disagreement: What a Memory Store Cannot Tell Your Agent
Edward Izgorodin
Edward Izgorodin

Posted on Originally published at mnemoverse.com

Nowhere to Put the Disagreement: What a Memory Store Cannot Tell Your Agent

Ask a memory system what database production uses, and it can hand back two records that flatly contradict each other, each with a confident similarity score, and nothing else. Ken Alger opened his piece on this with exactly that shape: PostgreSQL at 0.94, MongoDB at 0.91, and a migration four months ago that neither number knows anything about.

He wrote it from the interface side. This is the same problem from the store side, and the uncomfortable part is that a store can hold everything it needs to see the conflict, both records and both timestamps, and still return it flattened. Disclosure up front: I work on Mnemoverse, a memory engine for AI agents, so read the parts about our own failures as the ones I am most sure of.

Why does a memory store hand back a contradiction without saying so?

Because the response has nowhere to put it.

A memory API returns a list of items with scores. That shape can express "here are five things, sorted by how well they match." It cannot express "these two are in conflict," "this one was superseded by that one," or "this is still true but no longer governs." Those are relations between records, and a flat list has no field for a relation.

So even a store that tracked the conflict perfectly will flatten it on the way out. The agent sees two ordinary hits, takes the top one, and 0.94 beating 0.91 quietly becomes conflict resolution, performed by a number that was never asked to adjudicate anything.

This is not a bug in anyone's ranker. It is a type problem. Fixing it means the response carries edges, not just items, and that is a much bigger change than adding a column.

What are the three operations hiding inside "update"?

This decomposition is Ken's, from the conversation that produced both pieces, and it is the sharpest thing either of us wrote:

  • Supersession: this was true, now this other thing is. The world changed.
  • Correction: this was never true. Our record was wrong, and it was load-bearing for whatever happened while we believed it.
  • Invalidation: this is accepted as true and no longer governs. Not a claim about the world at all.

At the storage layer all three look identical, because all three end up writing a value. They diverge the moment anyone audits. Supersession keeps the past explicable. Correction says the past was built on something false, which is a different and more expensive fact. And invalidation is not a truth claim: a record can be perfectly accurate and still stop being the thing that decides.

Most stores have one verb for all three, or none. Ours had none until this week, and what it has now is deliberately less than a verb: the REST write accepts a supersedes link, the old record stays and gains a pointer to its replacement, and the read side does not yet hide it, so for now that link is an audit trail rather than a correction. Over MCP there is still no update verb at all, and our own changelog says it plainly: a correction that is admitted at all lands as a second record beside its target. Two atoms, two timestamps, and unless someone linked them, no relation between them. Which means the store genuinely cannot distinguish "never true" from "no longer true."

Why can't you just add relationships to the response?

Because of a bootstrapping problem underneath the interface question.

To know whether a supersession edge is worth carrying, you have to already be holding the record it supersedes. So edge hydration cannot be a filter applied after the top-k cut. It has to influence which candidates are considered in the first place. The relations have to be visible before the ranking, not after it.

That turns a ranking problem into an allocation problem. Once a response can carry facts, relationships, authority and prior decisions, something has to decide what gets dropped when they do not all fit in the context budget. As Ken put it in the thread, a lower-ranked authority edge may matter more than the next highly relevant fact, and dropping a supersession relationship can change the meaning of the records that survive. Top-k knows none of this. It knows one number.

Ranked lists are impoverished. They are also cheap, and whatever replaces them inherits a harder question than the one it solved.

What identity does a disagreement need?

If yesterday's decision is going to be findable when the same disagreement comes back, the disagreement needs a durable identity of its own.

The obvious move is to key it on the pair: A conflicts with B. That breaks. The moment a third record arrives, A-conflicts-with-B is no longer the same object, and yesterday's decision points at a conflict that no longer exists in that shape. Key it on the subject the records argue about instead, and the identity survives however many records pile up under it. Participants change, the disputed thing does not.

Most stores key on the atom. We have not yet found one that keys on the question the atoms are arguing about.

Who is allowed to promote a memory, and who can revoke it?

The thread that produced this article converged on a spec none of us had written down, and it belongs to the people who said it.

Max Quimby named the promotion boundary: an episode should not graduate into policy silently, because policy is expensive to change by design and should be expensive to create. Reid Marlow named the other end of it: every promoted item needs a revoker, or stale policy survives on sounding official. joinwell52 added the acceptance step in between, with scope and supersession kept separate. Suny Choudhary closed the loop from the security side: ten consistent episodes from untrusted documents should not outweigh one reviewed decision, or memory poisoning becomes a promotion attack rather than a retrieval one. anasbuilds997 named why the agent cannot be its own gate: two corroborating tool outputs are not authority, and self-promotion is how hallucinations harden into permanent truths.

Notice what all five are describing. Not better ranking. A write path with governance in it, and a read path honest enough to say which record is governing and on whose authority.

One thing worth stating for anyone building this: authority is not a score. Collapsing trust, recency, validity and usefulness into a single number is what produces systems nobody can explain, because once they are one number you cannot ask which of them decided.

What happens to a decision that is never recorded?

Mike Czerwinski made the point that reframed this for me: handing the contradiction back to the agent only closes the gap if the choice the agent then makes gets logged too. In his words, otherwise "silent resolution just relocates from the store to the inference step, same bug at a different address, and now it's harder to find because the store looks honest."

Tae Kim had already run into it, working on trade data, where the same company resolved to different nodes depending on whether you asked before or after an acquisition. They stamped time ranges on the relationships and started returning both versions to the reasoning layer, which helped. The part that stayed broken was that the agent's choice between them vanished without a trace. They started writing those choices back as events, and the honest reason was not architecture taste: a client asked about a strange output and there was nothing to point at.

That is the pressure that makes a field real. Not elegance, an audit.

One caution about where that record lives, and the thread supplied its own evidence for it. Giulio D'Erme went and counted his own corpus after reading the previous piece: zero of 152 memos and zero of 59 documents carried a validity window or a supersession edge. The engine could read those fields. Nothing was writing them. Availability is not usage.

So a decision log that sits beside memory, outside the retrieval path, will end up in exactly that state: readable, unread, technically shipped. If tomorrow's agent cannot get yesterday's decision back at the moment the same conflict returns, the log is, as Ken put it in the thread, forensic evidence for humans rather than operationally useful memory for the system.

What would a store that does this actually return?

Not a list. Something closer to: here are the records, here is the conflict they belong to, here is which one governs and under whose authority, and here is what was decided the last time this same conflict came up.

We do not ship that. In a personal domain, what we ship today decides admission with a novelty check against the nearest existing memory, which is not trust and not importance, and which has a failure mode we document publicly: a correction is phrased almost exactly like the thing it corrects, so it scores as a near duplicate, so it is the input most likely to be rejected. The stale record then survives as the only one on that subject and looks more authoritative than it did before anyone tried to fix it.

I would rather write that down than describe a nicer engine than the one we have. The three checks I would run against any memory vendor, us included, are still the cheap ones: store a fact, contradict it, and list everything the system holds on that subject; submit a correction phrased like the original and see whether it survives; and ask what the response can express beyond a score.

Ken's piece takes the same problem from the interface end and is worth reading alongside this one. Between us the argument is roughly complete: the store can know more than the response is able to say, and the part it does not know is what anyone did about it.


Disclosure: I work on Mnemoverse, a memory engine for AI agents connected over MCP. The failures described here as ours are documented in our own changelog rather than discovered for this article. Every argument credited above arrived in the comments of the previous piece, which is a better advertisement for writing honestly about your own defects than anything I could say here.

Top comments (3)

Collapse
 
izgorodin profile image
Edward Izgorodin

@kenwalger "I'd definitely like to read your treatment when it's ready" was where we left this, so here it is. Your two examples are in the piece with your name on them, and it is the store-side half of the argument your Reasoning Ledger makes from the write side: a response hands the agent records and has nowhere to put the relation between them, so the disagreement the store knows about never reaches the agent.

The paragraph I would most like your push-back on is the one on supersedes. Since Friday our write path records that one memory replaces another, and the link says replaced but not why, which is exactly the distinction your ledger keeps. If the boundary is drawn wrong anywhere, it is there.

Collapse
 
kenwalger profile image
Ken W Alger

Read through the whole thing now, and I think we're landing in roughly the same architectural neighborhood from opposite directions. There are three places I'd push a little, including the supersedes question you called out.

First, I don't think replaced or even supersedes carries quite enough semantics by itself. If B replaces A because the world changed, that's supersession: A was valid and B governs now. If B replaces A because A was wrong when written, that's correction: A was never valid, even though it may have been load-bearing while the system believed it. If A remains perfectly true but loses its authority to govern, that's invalidation. The graph shapes look similar, but the historical claims are very different.

I don't think that means the store has to absorb the Reasoning Ledger. I'd probably want the edge to preserve the minimum semantic claim: relation_type: supersession | correction | invalidation, effective/transaction time, and a durable reference to whatever event or decision established it. The ledger can preserve the richer evidence for why the relationship was asserted. That leaves the store knowing what relationship exists while the ledger preserves why the system was justified in asserting it.

Second, I agree that A conflicts with B is an unstable identity for a disagreement, because C arriving shouldn't create an entirely new disagreement. I'm less convinced that the subject alone is sufficient, though. Vendor X could simultaneously have disagreements about whether it is approved for regulated workloads, whether its SOC 2 certification is current, and whether it can process EU customer data. Same subject, three disputes, three potentially different authorities and histories.

I think your later wording is actually stronger: key the durable identity on the question or claim under dispute, not merely the subject or pair of participants. Records can then enter and leave that disagreement without changing what the disagreement is about. Yesterday's decision can point to that durable question rather than A conflicts with B, and it remains addressable when C arrives tomorrow.

Third, I'd make one distinction around the decision-log/retrieval problem. I completely agree that a prior decision nobody retrieves is operationally useless. Where I'd be careful is concluding that the ledger itself therefore has to live "in the retrieval path." I think custody topology and context-assembly topology can remain different.

Durable Memory and the Reasoning Ledger can stay independently governed systems while a retrieval/hydration interface queries both and reunites the relevant pieces for the agent. So I'd phrase the requirement as retrievable together, not necessarily stored or retrieved together. That's where I've ended up with "separate custody, one interface": the agent shouldn't have to know which subsystem owned the evidence it needed, but that doesn't mean those subsystems need the same custody or integrity model.

Put together, I think that gives me something like:

  • Store: preserves the records and the minimum semantics of their relationships.
  • Ledger: preserves why, when, and on what evidence those relationships or decisions were asserted.
  • Retrieval/hydration: makes sure the relevant records, relationships, authority, and prior decisions survive into the knowledge state the agent actually receives.

The promotion/revocation section I wouldn't push on much at all. I agree with not collapsing authority, recency, validity, usefulness, etc. into another magic score. That feels like rebuilding the same problem similarity ranking created, only with a more sophisticated number.

And the novelty-filter example is wonderfully nasty. A correction being rejected because it resembles the thing it is correcting too closely is about as good a concrete demonstration as I've seen of why admission semantics can't be inferred from similarity alone.

Really good store-side companion to the API piece. I think the interesting part is that we're starting from different boundaries and mostly finding the same seams between them.

Collapse
 
izgorodin profile image
Edward Izgorodin

"Supersession, correction, invalidation" closes the gap I called out better than anything I had on the shelf. The link we shipped on Friday says replaced and stops there; your three relation types are the smallest vocabulary that also says why, and the division of custody that comes with them is right: the store carries the minimum claim about the relationship, with its two times and a durable reference, and the ledger carries the evidence that justified asserting it. Measured against that, our field is one enum short of saying something true instead of something vague, and I mean that as an assessment of the design, not a roadmap promise.

On identity, your own example settles it. One vendor, three simultaneous disputes, three authorities and three histories: subject-keying collapses them into mush, and the question under dispute is the only identity that survives records entering and leaving. I will stop defending the pair-of-records framing; it was the symptom-level view.

"Retrievable together, not necessarily stored or retrieved together" is the requirement stated at the right altitude, and here is our honest distance from it: today our read path could not reunite the pieces even if both systems existed, because the response is a ranked list and whatever the store knows about relationships dies at the cut. That is the piece the article was about, and your three-layer split names what has to exist on the other side of it. Different boundaries, same seams, and the seams are starting to read like a spec.