Neither happens automatically. On write, invalidate_thought() closes a fact's valid-time window, and it's documented as doing no similarity search and no inference of any kind - your code has to call it, the store never notices on its own that a new fact conflicts with an old one.
Retrieval doesn't flag it either. Hybrid search ranks by keyword, vector similarity, recency, priority and graph signals - nothing in there compares two results against each other for agreement. If both facts are still valid-time-live, both can come back with no signal marking them as conflicting.
There's one adjacent thing, narrower than it sounds: the deterministic consolidation pass has a gate that skips building a summary over a cluster whose members look internally contradictory, but it's a small English sentiment lexicon (stopped/started, hate/love, can't/can) - a location change like Berlin to Lisbon wouldn't trip it, and it only decides whether a synthesized memory gets built, not what the raw facts return on a normal search.
So it's the caller's call, both times. Is anyone doing this well without a model in the loop, or is that the honest floor right now?
Kartik N V J K
Contradictions that "look like confidence" is the failure I underestimated longest, because a memory store never surfaces the two conflicting facts, it just returns the closest one. The Mem0 ADD-only issue you cite is telling: with no conflict resolution, the store quietly accumulates mutually exclusive "truths." Do you resolve contradictions at write time, or flag them at retrieval and let the agent decide?