skip to content

When a new fact contradicts a stored agent memory, how should the write path resolve it?

level: seniorimportance: must knowfreq 56%

answer

  1. look before you write
  2. overwrite is cheap and lossy
  3. two clocks, not one
  4. did the world change or did we misread it
  5. who is the more trusted source

basics

~20 s

Detect the conflict before inserting, then choose deliberately: overwrite (last-writer-wins) is simple but destroys history and breaks on out-of-order input. Superseding keeps the old record, marks it replaced, and records both when the fact was stated and when it was written.

solid answer

~50 s

The write path should retrieve related records for the candidate fact *before* inserting, so a conflict is detected rather than silently appended. Then classify. **Last-writer-wins** overwrites the stored value: cheap, easy to reason about, and wrong whenever writes arrive out of order — a re-processed old transcript will clobber a newer truth — and it leaves no trail when the new fact turns out to be the bad one. **Supersede-with-history** keeps the old record, marks it replaced by the new one, and stores two timestamps: when the fact was *stated* and when it was *written*. Ordering by stated time is what stops a late-arriving old statement from winning. A third case matters: distinguish "the world changed" (a CTO left; the old value was true then) from "the extraction was wrong" (it never was true). The first is history worth keeping, the second is an error to retract.

code

json · 11 lines
json
{
  "id": "acme:cto@1",
  "key": "account:acme/cto",
  "value": "Dana Reyes",
  "stated_at": "2025-11-04T14:02:00Z",
  "written_at": "2025-11-04T14:31:00Z",
  "status": "superseded",
  "superseded_by": "acme:cto@2",
  "superseded_reason": "world_changed",
  "source": {"session": "s-7710", "message": 18, "extractor": "v3"}
}

go deeper

for a junior

Know that a new fact can conflict with something already stored, and that the write path must check for that instead of storing both. Be able to say what overwriting costs: the old value is gone.

for a middle

Explain the two strategies: last-writer-wins versus superseding with history, and why the store keeps both the time a fact was stated and the time it was written.

for a senior

Demonstrate judgment: out-of-order writes from backfills and retries, source trust beating recency, holding low-confidence contradictions for confirmation, and separating a genuine change from a faulty extraction.

for a principal

Own the policy: which classes of fact may be resolved automatically versus escalated to a human, what audit trail the domain requires, how a bad extractor version gets identified and its whole batch retracted, and what a user is entitled to see about why a belief changed.

## Detecting the conflict at all Contradiction handling begins before the write. When a candidate fact arrives, the write path retrieves records with the same subject and predicate within the same scope. Without that step there is no conflict to resolve — the store simply accumulates both "the CTO is Dana" and "Dana left in March" and becomes internally inconsistent, with whichever record happens to surface deciding what the agent believes. The classification that follows has three outcomes: the claims agree (a duplicate — merge), they disagree (a contradiction — update or supersede), or one strictly invalidates the other's existence (a deletion). Systems in this space, mem0 among them, expose exactly this as an add/update/delete decision made by a model over the candidate and the retrieved neighbours. ## Last-writer-wins Overwrite the stored value with the new one and move on. - **Why it is attractive:** one record per fact, no history to query, no ambiguity about what the agent currently believes. - **Where it breaks:** ordering. Memory writes are not guaranteed to arrive in the order the facts were stated. An imported transcript, a delayed async job, a backfill of old sessions, a retry — any of these can deliver a *stale* statement after a fresh one, and last-writer-wins will happily install the stale value. - **The other cost:** the old value is gone. When the new fact turns out to be a bad extraction, there is nothing to roll back to and no way to explain to a user why the agent's belief changed. Last-writer-wins is defensible for low-stakes preference data with a single ingestion path. It is a poor default for anything a decision hangs on. ## Supersede-with-history Keep the old record, mark it superseded by the new one, and write the new record with a link back. What this buys: - **Ordering safety.** Store two times per record: when the fact was **stated** (event time, drawn from the conversation) and when it was **written** (ingestion time). Resolution compares stated times, so a late-arriving old statement is recorded but does not displace a newer one. - **Auditability.** "Why did the agent think Dana was the CTO?" is answerable: this record, from this session, this message, stated on this date, superseded on that date by this one. - **Correction versus change.** These are different events and superseding lets you record which. Dana genuinely was the CTO until March — that old record was *true and is now historical*. Contrast an extraction that misheard a name: that record was *never* true and should be retracted, not archived as history. Conflating the two produces a store that cannot distinguish real history from its own mistakes. The cost is complexity: more records, an explicit notion of the current version, and a garbage-collection story for old versions. ## Deciding who wins Recency is the usual tiebreak, but not the only signal, and a good answer says so: - **Source trust.** A value confirmed by an authoritative system of record should outrank one inferred from a chat message, regardless of which arrived later. - **Explicitness.** A user directly stating a correction ("no, my address is X") should outrank a model's inference. - **Confidence.** If the extractor was unsure, prefer flagging the conflict over silently replacing a well-supported fact. - **Blast radius.** Some facts are load-bearing enough that a contradiction warrants asking the user rather than resolving unilaterally. A reasonable default: recency wins among same-trust sources; higher-trust sources win outright; low-confidence contradictions of high-confidence facts are held for confirmation. ## Cascades One contradiction can invalidate dependents. If "Dana is the CTO" is superseded, then "escalate approvals to Dana" is now questionable even though nothing contradicted it directly. Fully solving this needs an explicit relation between records, which most systems do not have; the pragmatic mitigation is to store facts atomically and self-contained, so the number of records that silently depend on another is small, and to re-derive rather than store anything that is a consequence of something else. ## Idempotency and re-processing Systems reprocess: a better extractor is deployed, an old corpus is imported, a failed batch is replayed. Any of these can generate contradictions against records the same pipeline produced earlier. Two habits keep this survivable — record the extractor version on every record so a whole bad batch can be identified and retracted, and make resolution depend on stated time and source trust rather than on arrival order alone. ## What interviewers are checking That you look before you write; that you can state the failure mode of last-writer-wins in one sentence (out-of-order writes install stale values, and history is gone); that you separate event time from ingestion time; and that you distinguish a change in the world from a correction of a bad extraction.

  • Why store both when a fact was stated and when it was written?
    Because writes arrive out of order. A backfilled transcript, a delayed async job or a retry can deliver an older statement after a newer one, and resolving on write time alone installs the stale value. Stated time is the fact's real event time, so ordering on it keeps resolution correct while write time still tells you what your pipeline did and when — which is what you need to debug an ingestion bug.
  • How do you handle a contradiction where the new claim is less trustworthy than the stored one?
    Do not let recency win by itself. Weight the source: a value from a system of record or an explicit user correction outranks a model inference, whenever it arrived. If a low-confidence new claim contradicts a well-corroborated record, the right move is usually to flag it — hold it as a pending conflict, or ask the user — rather than to overwrite quietly. Silent replacement of a strong fact by a weak one is the failure this rule exists to prevent.
  • Superseding a fact leaves dependent memories that nothing contradicted. What can you do about it?
    Mostly prevention. Store facts atomically and self-contained so few records silently depend on another, and prefer re-deriving consequences at use time over storing them. Where a dependency is real and important, make it explicit — record which fact a derived memory rests on — so superseding the parent can mark the child for re-validation. Full dependency tracking is rare in practice, which is why atomicity matters.
  • When is last-writer-wins actually the right choice?
    When the data is low-stakes, single-sourced and genuinely current-state-only — UI preferences, formatting choices, a chosen language. There is one ingestion path, ordering is effectively guaranteed, history has no value and a wrong write costs one annoyed user rather than a wrong decision. The moment a second ingestion path, a backfill, or an auditable decision appears, the simplicity stops paying.

saying these in an interview costs you the question

  • Appending the new fact without ever checking for an existing one
  • Assuming the newest write is always the newest truth
  • Deleting the old value so nobody can see what changed
  • Treating a bad extraction and a real-world change as the same event
  • Resolving conflicts on arrival order when transcripts can be imported late

context