Ragable

← All articles

How to Make an AI Assistant Cite the Documents It Used

5 min read
How to Make an AI Assistant Cite the Documents It Used

Every retrieval augmented assistant eventually runs into the same question from whoever has to sign off on it: where did that answer come from? Sounds like a formatting detail. It isn't. Citation is the line between an assistant that produces plausible text and one whose output someone can actually check before acting on it. We build these systems for companies whose documents are the whole point, and provenance turns out to be an ingestion problem far more than a prompting one.

What Citation Actually Means in a Retrieval System

A citation is not a footnote the model writes. It is a record of which retrieved chunks landed in the prompt. Three things get muddled here: the source list retrieval returned, the passages the model actually leaned on, and the link the reader sees. Ask a model to "add references at the end" and it will hand you convincing file names, because emitting a citation is the same token prediction as emitting prose. Nothing in that process touches your document store. Nothing. Trustworthy attribution comes from the retrieval layer, where real identifiers live, never from the generation layer inventing them.

Design the Chunk So It Can Be Pointed At

Every chunk needs a stable identity before anything else works. Document id, version, a page or heading anchor, a character offset range - carried intact through ingestion, the embedding store, the retrieval result, prompt assembly, and the final response payload. Boundaries that slice mid-sentence produce citations that look wrong even when retrieval was right, so respect structure when you split. Keep the original file addressable too, so a link opens the source at the correct page instead of dumping an entire PDF on someone. And re-ingestion that silently reassigns ids? That strips provenance from every answer you already stored.

Three Ways to Attach Sources to an Answer

  • List the retrieved documents under the answer. Cheap and honest, but coarse: it reports what was available, not what was used.
  • Inline markers tied to numbered context blocks. Sentence-level attribution that reads well, though the markers are model output and have to be validated against the real id list.
  • Post-generation verification of claims against passages. Costs an extra pass and latency. Worth it when a wrong attribution has consequences.

Most deployments end up combining them: a strict id whitelist for everything, plus a verification pass on the claims that actually matter.

Prompting for Grounded, Attributable Answers

Number the context blocks explicitly and tell the assistant to reference only those numbers, never file names it happens to recall. Give it an escape hatch too. Saying the documents do not cover a question is a correct answer, and without permission to say it, the model will quietly plug the gap from general knowledge. Keep answer and citation structurally separate so your parser does not depend on prose formatting staying put.

Tip: request structured output where the citation field is a list of context block ids, then map ids to documents in code. Reject or strip any marker that does not resolve to a block you actually sent.

Verifying That the Citation Is True

Build a small evaluation set of questions with known correct sources, and measure retrieval recall separately from answer quality. Two failure modes deserve their own tracking: a right answer with the wrong source, and a correct source propping up a claim it never made.

  1. Resolve every emitted id against the sent block list.
  2. Confirm the cited passage supports the sentence it hangs on.
  3. Confirm no substantive claim lacks a source.
  4. Confirm the assistant refuses when coverage is genuinely missing.

Tip: log the full retrieved set alongside every answer, so a disputed response can be reconstructed months later. Run this suite after re-chunking, model swaps, or embedding upgrades.

Permissions, Versions, and On-Premise Constraints

Citations expose document titles, which makes permission filtering a retrieval concern rather than an interface one. Hide a link in the UI while the title still renders and you have leaked exactly what you meant to protect. A visible citation the reader cannot open is worse than none at all, so line up access checks with what gets displayed. Pin each answer to the revision retrieved, and surface it when a newer one lands. Cloud or entirely on customer hardware - that changes where the index and logs live, not whether provenance works. The metadata contract holds either way. Regulated settings often keep the citation trail as an audit record, which drags storage decisions forward in the design.

Frequently Asked Questions

Can we just ask a general purpose model to cite its sources?

No. It produces convincing but unverifiable references, since nothing constrains the output to documents that exist. Real citation needs retrieval underneath it.

Do inline citations slow the assistant down?

Emitting markers costs almost nothing. A separate verification pass adds a real second round trip, so decide per use case whether that latency buys enough certainty.

What happens when an answer combines several documents?

Attribute per claim rather than per answer, and keep the complete retrieved set in the response payload so anyone can inspect what the model saw.

What We Would Build First

Start with stable chunk ids and a strict whitelist of context block references. That alone kills fabricated sources, which is the failure people actually lie awake over. Add sentence-level markers once the id plumbing has proven itself, then layer verification only where a wrong attribution carries real cost. Treat the citation as a product surface, not a debugging artifact: it is what turns an assistant answer into something a person can check, challenge, and act on. The engineering work lives in ingestion and metadata discipline, not in clever prompt wording.

Build your own AI assistant on your documents

Ragable indexes your files and answers from them, with citations. Start on SaaS or run it on your own infrastructure.

Start from $99/month