Core concepts
Provenance in RAG, and why it is usually wrong
Most systems keep one document reference per fact. That design breaks the second time two documents agree — here is what to store instead.
8 min read
Provenance is the record of which document said what. Every retrieval system claims to have it, and most have a version that works until two documents agree with each other. This guide walks through the designs in the order people usually try them, and where each one fails.
Attempt one: no provenance
You extract facts and store them as edges. Subject, predicate, object. Clean, small, fast.
It fails the first time anyone asks where a fact came from — which is immediately, because that is the only reason to build this instead of using a vector store. Worth mentioning only because it is a real intermediate state, and because a graph in this shape cannot be retrofitted: the information was never captured.
Attempt two: a document reference on the edge
Add a document identifier to the edge. Now every fact knows its source.
This fails the second time two documents assert the same thing. You have a choice, and both options are wrong:
- Overwrite the reference. The fact now claims to come from whichever document was processed last. Your citation is arbitrary, and re-ingesting in a different order changes it.
- Create a second edge. Now you have two edges between the same pair of nodes, which triples the apparent connectivity if a third document agrees, and makes any path scoring you do a function of how often something was said rather than how strongly it connects.
Attempt three: a reference set on the edge
Keep one edge and hang a set of document identifiers off it. Now the fact knows all of its sources, and the corroboration count is the size of the set. This is a real improvement and it is where a lot of systems stop.
What is still missing is per-document confidence. Extraction is not equally sure about every reading — one document states a relationship outright, another implies it in a subordinate clause. Collapsing those into one number per edge throws away the distinction between a fact resting on five confident statements and one resting on five hedges.
And there is a subtler problem: deletion. If a document is removed, you take its identifier out of the set. What if the set is now empty? You need a rule, and the rule has to be applied consistently, which means it wants to be a property of the data model rather than a line in a delete handler.
What to actually store
One record per fact-and-document pair, rather than one per fact. Each of those records needs its own confidence — how sure extraction was about this claim in this document — plus which source system the document arrived from. Everything below follows from that shape.
With that in place, three things become straightforward that were awkward before:
- Corroboration is a count. How many documents support this fact is a query, not an estimate.
- Retraction has a rule. A fact is retracted when its last supporting document is removed — not when any one document changes.
- Evidence is enumerable. Given a fact, every document that supports it is something you know rather than something you guess at.
The limitation nobody advertises
Corroboration counts are a floor, not a measurement, and you should know by how much before you put them in front of a user.
The reason is predicate variance. The edge identity includes the relation, so a document saying "reduces" and one saying "lowers" produce two edges, each with one supporter, even though a human would call them the same claim.
The practical consequence is that a displayed count of "1 source" frequently means "one phrasing of this claim was found", not "only one document says this". Treat the count as a floor: every document behind it is real and openable, and there may well be more. Show the counts, because they tell a reader how much stands behind a claim, and gate nothing on them — a floor is the right number to display and the wrong number to make a decision with.
Provenance is not citation
One boundary worth drawing explicitly, because conflating these two produces a specific and nasty failure.
Provenance is internal: which documents assert which facts. Citation is external: the markers in an answer that a reader can follow. They are related but they are not the same, and a graph fact must never be offered as a citation.
The reason is that a fact is a derived object. "Onboarding reduces churn" is our reading of three documents, not a sentence any of them contains. If that appears as a citation, a reader who follows it finds a document that does not say what was cited — which is worse than no citation, because it looks checkable and is not.
A checklist
- One record per fact and document, with per-document confidence.
- Retract a fact only when its last supporter is removed.
- Present corroboration as a floor, and gate nothing on it.
- Never cite a fact. Cite documents.