Introducing open source Cambrian Core. Explore
Back to the blog
Engineering 4 min read

Facts that disagree: keeping history instead of overwriting it

Company knowledge contradicts itself, and the contradiction is often the most useful thing in it. Cambrian keeps every statement and derives what it currently believes, so a new fact never erases an old one. Here is how, and how we checked the move changed nothing it should not.

By Doruk Eray, Founder ·

Ask two people in a company when a purchase order ships and you can get two answers. Sales told the customer Friday. Operations planned Monday. Both statements exist, in different systems, and the fact that they disagree is exactly what someone needs to know.

Most memory systems for AI agents store one value per question. A new statement replaces the old one, and the last write wins. That loses two things at once: the history of what was said, and the disagreement itself. By the time anyone looks, only Monday is left, and nobody can see that the customer was promised Friday.

Cambrian Core stores knowledge differently. Statements are never overwritten. What the system currently believes is computed from them, and can always be computed again.

Statements are append-only

Each statement is a knowledge item: who or what it is about, the claim with a typed value, who made it and when, where it came from, and whether it retracts an earlier claim. Items are only ever added.

There is deliberately no uniqueness rule on "one value per subject and attribute". Two items that contradict each other must be able to sit side by side, because the disagreement is the signal.

When someone changes their mind, the new statement is a new item, and the earlier one stays. When someone withdraws a claim, that is also a new item, a negation, rather than a deletion. The only true deletion in this layer is erasure for compliance, such as removing everything about a person who asks for it.

Beliefs are derived

On top of the items sits a resolution: the current answer for one subject, kind of claim and speaker. Resolutions are a projection, which means they can be rebuilt from the items at any time. When the answer changes, the current resolution is closed and a new one is opened, so "what did we believe on 3 September?" has an answer too.

Resolutions are per speaker. Cambrian does not decide whether Sales or Operations is right. It keeps each one's latest position, and a query for contradictions returns both values side by side, each with where it came from. Deciding which source wins is a judgement we have not automated, and I would rather show the conflict than hide it behind a guess.

Arrival order must not change the answer

Data reaches Cambrian out of order all the time. A retry lands late, a connector backfills last week, two messages arrive in the same millisecond. If the current belief depended on which item happened to arrive last, replaying the same data could produce a different answer.

So resolution is a pure function over the full set of items, never a comparison with "the previous row". It sorts by when the claim was made, then by source reference, then by whether it is a retraction, and takes the last. Every tie has a defined winner. If a retraction and an assertion carry the exact same timestamp, the assertion wins: withdrawing a statement you are making in the same instant is the less destructive reading, and what matters most is that the choice is always the same.

The test for this does not sample a few orderings. It runs the resolution over every permutation of its input items and fails if any ordering gives a different answer.

Moving a real feature onto it

A storage design is easy to admire in isolation. The real test was moving an existing feature onto it without changing its behaviour.

The first feature we moved tracks commitments found in company records and flags when reality drifts from them. It is part of our commercial product and had its own private table. We rebuilt its storage on knowledge items and resolutions, without touching how it detects, reconciles or alerts, so any difference in results could only come from the storage.

Then we ran that feature's benchmark twice from the same build, once on each storage backend, and compared every row:

GateResult
Rows that differed between old and new storage0 of 244, on three runs
Rows that differed after switching the default to the new storage0 of 244
Extra write-cycle time at the 95th percentileabout 2 ms

These are gate results recorded on 1 August 2026, and they need a caveat. A parity gate shows the move changed nothing it should not have. It does not measure how good the feature is at detecting drift, and it is not a benchmark of contradiction handling. The timing came from an instrument that could not separate the two code paths cleanly, so treat it as a rough figure.

The new storage became the default the same day. The old backing is still there as an explicit rollback switch.

What is not done

  • Nothing ranks sources by authority yet. Contradictions are kept and shown. They are not resolved by judgement.
  • Linking items to evidence is partial. Every item records its source, but the link from an item to the stored original it was read from is not filled in for every path yet.
  • Erasure has the mechanism but no public entry point. The deletion path exists and is tested. The operator call that will use it has not been built.

Sources

Build with Cambrian

Cambrian Core is open source. Run it on your own machine.