AI & LLM APIs cookbook · Intermediate
Answer with citations that point at the source text
Show users exactly which sentence in which document supports each part of the answer.
Approach
Send documents as document content blocks with "citations": {"enabled": True}. Text blocks in the response
then carry citations with the cited_text and its location, which you can render as footnotes. Citations
must be enabled on all documents in a request or none.
Solution
import anthropic
client = anthropic.Anthropic()
def doc_block(title: str, text: str) -> dict:
return {"type": "document", "title": title, "citations": {"enabled": True},
"source": {"type": "text", "media_type": "text/plain", "data": text}}
def cited_answer(question: str, documents: dict[str, str]) -> str:
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": [*(doc_block(t, body) for t, body in documents.items()),
{"type": "text", "text": question}]}],
)
parts, notes = [], []
for block in response.content:
if block.type != "text":
continue
parts.append(block.text)
for c in block.citations or []:
notes.append(f'[{len(notes) + 1}] {c.document_title}: "{c.cited_text.strip()}"')
parts.append(f"[{len(notes)}]")
return "".join(parts) + "\n\n" + "\n".join(notes)
print(cited_answer("What is the refund window?",
{"Refund policy": "Refunds are available within 30 days of purchase. Gift cards are excluded."}))
Pitfalls
- Enabling citations on some documents but not others in the same request.
- Showing citations without the document title or link, so users can't check them.
- Assuming a cited sentence means the whole answer is supported; review uncited text too.
Variations
- PDF documents (
"source": {"type": "base64", "media_type": "application/pdf", ...}) return page locations. - Use custom content documents to control the citation granularity (for example one block per paragraph).
Further reading: Citations
Reference: https://docs.anthropic.com/en/docs/build-with-claude/citations
More AI & LLM APIs recipes
- Build hybrid RAG search on PostgreSQL with pgvector
- Cache a long system prompt and documents
- Cache answers to frequent questions safely
- Classify thousands of items with the Batch API
- Compare two prompt versions with an unbiased model judge
- Expose an internal API as an MCP server
- Extract structured data with a schema
- Fit conversation history into a token budget