An answer says a device can operate at 40 °C. Its footnote opens a real manual, on a real page, and highlights a real sentence: the device can be stored at 40 °C. The citation works. The answer is still unsupported.
That small example captures the hardest part of citation engineering. A correct link is useful, but it cannot do the work of checking the claim. In this architecture note, the document and payload examples are illustrative.
Three checks with different meanings
| Check | What passing establishes | What it leaves open |
|---|---|---|
| Source location | The supplied quote exists in the pinned source representation. | Whether extraction matches the original document. |
| Evidence structure | Required fields and relationships satisfy the declared constraints. | Whether the source actually supports the claim. |
| Claim support | A review finds the cited passage supports this claim in context. | Reviewer or judge error, and the reliability of the source itself. |
The first two can be mechanical. The third may need domain rules, an audited model-based check, a human, or a combination. Keeping those results separate is more informative than a single green “grounded” badge.
Preserve the location at ingestion
A citation needs enough identity to survive another document arriving with the same filename. Pin a source version and a page or passage anchor when ingesting it, then carry that reference through retrieval and generation.
{
"claim_id": "claim-42",
"text": "The device operates between 0 and 40 degrees Celsius.",
"evidence": {
"document_id": "example-manual",
"document_version": "example-revision-3",
"page": 12,
"quote": "The unit operates in ambient temperatures from 0 to 40 °C."
}
}For PDFs, preserve the mapping between the extracted text and the original page. If extraction merged columns, changed a symbol, or dropped a table heading, a perfect substring match against the extraction can still validate the wrong reading. The source viewer gives the reviewer a way to inspect that gap.
Provider-native citation metadata can supply source references as part of the response. Normalize those references in a backend adapter, while retaining their original granularity. Do not present a document-level reference as an exact quote just because the UI would look more consistent.
Verify the quote before resolving the marker
Check the referenced source version, page, and quoted text. If offsets are used, define what they count: bytes, Unicode code points, or another unit. Whitespace normalization also needs to preserve a mapping back to the original text; normalizing first and reusing the old offsets can highlight the wrong passage.
A missing page, mismatched quote, or unavailable source should produce a visible failure state. It should never become a working-looking footnote.
flowchart LR
candidate["Candidate claim + citation"] --> source{"Source location valid?"}
source -->|"Yes"| shape{"Record well formed?"}
shape -->|"Yes"| support{"Passage supports claim?"}
support -->|"Yes"| answer["Answer + inspectable source"]
source -->|"No"| unresolved["Unresolved or unsupported"]
shape -->|"No"| unresolved
support -->|"No / uncertain"| unresolvedWhat SHACL can actually tell you
A graph can make evidence relationships explicit: claims reference passages, passages belong to source versions, and each relationship has constraints. W3C SHACL validates RDF graphs against declared shapes. For example, a shape can require each claim to reference at least one evidence node and require that node to include a source identifier.
That can catch orphaned claims and malformed records. It cannot infer, from those fields alone, that a storage-temperature quote supports an operating-temperature claim. A conforming graph can faithfully represent a false statement.
JSON Schema may be enough for a flat citation record. SHACL is useful when the relationships themselves need validation across a graph. Choose it for that need; adding RDF does not make an answer more factual.
Let the interface show what has cleared
Streaming makes this distinction visible. Text can arrive before its citation has passed validation. A placeholder marker should stay provisional until the source check completes. If the stream disconnects, the unfinished answer must stay unfinished; a closed connection is not a successful terminal event.
An answer can also have mixed coverage. Mark which claims have support, which are still being checked, and which cannot be supported from the supplied sources. For workflows that require every claim to be supported, withhold or remove the unsupported portion before finalization. Avoid saying “no evidence exists” when the system only knows that this retrieval and validation run found none.
The useful terminal message is specific: “No supporting passage was found in the supplied sources.” It tells the reader both the result and the search's limits.
The test that matters most
Keep deliberately misleading fixtures alongside fabricated citations:
- a real quote about the wrong entity;
- a table value with the wrong column heading;
- a passage whose next sentence reverses its meaning;
- a superseded source version;
- a valid quote that supports only part of a compound claim.
A citation system that rejects fake page numbers but accepts all five still has work to do. The front end's job is to make that distinction inspectable; the next note looks at how the same discipline applies to streamed answers and editable charts.