Skip to content
All guides

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:

  1. Corroboration is a count. How many documents support this fact is a query, not an estimate.
  2. Retraction has a rule. A fact is retracted when its last supporting document is removed — not when any one document changes.
  3. 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

  1. One record per fact and document, with per-document confidence.
  2. Retract a fact only when its last supporter is removed.
  3. Present corroboration as a floor, and gate nothing on it.
  4. Never cite a fact. Cite documents.

Try it on your own corpus.

The free RAG tier needs no card. Ingest a document and search it in the same session.