Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
lebsral avatar

Dspy Citations

  • 2 installs
  • 11 repo stars
  • Updated June 28, 2026
  • lebsral/dspy-programming-not-prompting-lms-skills

Adds structured source attribution to DSPy outputs so answers link claims to specific passages in source documents, for RAG and compliance use cases.

About

Guides using dspy.experimental.Citations and Document to produce machine-readable citations that identify which passage supports each claim. A developer uses it for grounded RAG answers and legal or compliance cases needing source traceability.

  • Works natively with Anthropic's Citations API, falls back to prompt-based extraction
  • Returns machine-readable citation objects with cited_text and document_index

Dspy Citations by the numbers

  • 2 all-time installs (skills.sh)
  • Ranked #13,958 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/lebsral/dspy-programming-not-prompting-lms-skills --skill dspy-citations

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs2
repo stars11
Last updatedJune 28, 2026
Repositorylebsral/dspy-programming-not-prompting-lms-skills

What it does

Adds structured source attribution to DSPy outputs so answers link claims to specific passages in source documents, for RAG and compliance use cases.

Files

SKILL.mdMarkdownGitHub ↗

Add Structured Citations to DSPy Outputs

Guide the user through adding structured citations to DSPy outputs so AI answers can be traced back to specific source passages.

What are DSPy Citations

dspy.experimental.Citations provides structured source attribution for LM outputs. Instead of inline quotes, you get machine-readable citation objects that identify exactly which passage from which document supports each claim. Works natively with Anthropic's Citations API and falls back to prompt-based extraction for other providers.

When to use Citations

Use Citations when...Use something else when...
You need to verify which document supports a claimSimple RAG where inline quotes are enough
Legal/compliance requires source traceabilityOutput does not reference source material
Users need clickable references back to source docsYou only have one source document
You want machine-readable citation metadataHuman-readable quotes in text are sufficient
Building fact-checking or grounding verificationThe task is creative generation (no sources)

Step 1: Set up Documents

Create Document objects from your source material:

import dspy
from dspy.experimental import Citations, Document

lm = dspy.LM("openai/gpt-4o-mini")  # or "anthropic/claude-sonnet-4-5-20250929", etc.
dspy.configure(lm=lm)

# Create documents from your sources
documents = [
    Document(
        text="DSPy is a framework for programming language models. It replaces prompting with composable modules that can be optimized.",
        title="DSPy Overview",
        source_id="doc-001",
    ),
    Document(
        text="MIPROv2 is the most powerful DSPy optimizer. It jointly optimizes instructions and few-shot demonstrations.",
        title="Optimizers Guide",
        source_id="doc-002",
    ),
]

Step 2: Build a signature with Citations output

class CitedQA(dspy.Signature):
    """Answer the question using the provided context. Cite your sources."""
    context: list[str] = dspy.InputField(desc="source documents")
    question: str = dspy.InputField()
    answer: str = dspy.OutputField()
    citations: Citations = dspy.OutputField(desc="structured citations for claims in the answer")

Step 3: Use with a standard module

qa = dspy.ChainOfThought(CitedQA)

# Format documents as context strings
context = [f"[{doc.source_id}] {doc.title}: {doc.text}" for doc in documents]

result = qa(
    context=context,
    question="What is the most powerful DSPy optimizer?",
)

print(result.answer)
# "MIPROv2 is the most powerful DSPy optimizer..."

for citation in result.citations:
    print(f"  Cited: '{citation.cited_text}' from document {citation.document_index}")

Step 4: Anthropic native Citations API

For Anthropic models, enable native citation support for higher accuracy:

lm = dspy.LM("anthropic/claude-sonnet-4-5-20250929")
dspy.configure(lm=lm)

# Enable native citations via adapter feature
dspy.configure(
    lm=lm,
    adapter=dspy.ChatAdapter(
        adapt_to_native_lm_feature=["citations"],
    ),
)

# Now Citations output uses Anthropic's built-in citation extraction
# instead of prompt-based parsing -- higher accuracy, structured response
result = qa(
    context=context,
    question="How does DSPy replace prompting?",
)

Native mode advantages:

  • Citations are extracted by the model during generation (not post-hoc)
  • cited_text exactly matches source text (character-level accuracy)
  • document_index reliably maps to the input document list

Step 5: Parse and validate citations

# Each citation has these fields
for citation in result.citations:
    print(f"Cited text: {citation.cited_text}")
    print(f"Document index: {citation.document_index}")
    print(f"Start char: {citation.start}")
    print(f"End char: {citation.end}")

# Validate that cited text exists in the source document
for citation in result.citations:
    source_doc = documents[citation.document_index]
    if citation.cited_text in source_doc.text:
        print(f"VALID: Citation found in {source_doc.title}")
    else:
        print(f"INVALID: Citation not found in source")

Step 6: Citations with streaming

Stream answers while accumulating citations:

from dspy.streaming import streamify, StreamListener

qa = dspy.ChainOfThought(CitedQA)

answer_listener = StreamListener(signature_field_name="answer")
streaming_qa = streamify(qa, stream_listeners=[answer_listener])

async for chunk in streaming_qa(context=context, question="..."):
    if hasattr(chunk, "answer"):
        print(chunk.answer, end="", flush=True)
    elif isinstance(chunk, dspy.Prediction):
        # Citations are available in the final prediction
        for citation in chunk.citations:
            print(f"\n[{citation.document_index}] {citation.cited_text}")

Step 7: Non-Anthropic fallback patterns

For providers without native citation support, use prompt engineering:

class CitedAnswer(dspy.Signature):
    """Answer using ONLY information from the provided documents.
    For each claim, include [doc_N] inline where N is the document number."""
    context: list[str] = dspy.InputField(desc="numbered source documents")
    question: str = dspy.InputField()
    answer: str = dspy.OutputField(desc="answer with [doc_N] inline citations")

# Number your documents explicitly
numbered_context = [
    f"[doc_{i}] {doc.title}: {doc.text}"
    for i, doc in enumerate(documents)
]

qa = dspy.ChainOfThought(CitedAnswer)
result = qa(context=numbered_context, question="...")
# Parse [doc_N] references from the answer text

Gotchas

1. Claude omits the `Citations` type import. You must import from dspy.experimental -- it is not in the main dspy namespace. Use from dspy.experimental import Citations, Document. 2. Native citations only work with Anthropic models. If you configure adapt_to_native_lm_feature=["citations"] with OpenAI, it silently falls back to prompt-based parsing which may be less accurate. 3. Claude hardcodes document indices. The document_index in citations maps to the position in the context list. If you reorder documents, indices change. Always use the index to look up the source, do not hardcode. 4. Citations are experimental. The API is in dspy.experimental and may change between versions. Pin your DSPy version in production. 5. Claude generates citations without source material. Citations only make sense when you provide context documents. Without context, the model fabricates citation metadata. Always pair Citations with a retrieval step.

Additional resources

Cross-references

Install any skill: npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill <name>
  • Stopping hallucinations with grounding -- see /ai-stopping-hallucinations
  • Searching docs for RAG pipelines -- see /ai-searching-docs
  • Retrieval modules for getting context -- see /dspy-retrieval
  • Streaming citations progressively -- see /dspy-streaming
  • Install `/ai-do` if you do not have it -- it routes any AI problem to the right skill and is the fastest way to work: npx skills add lebsral/DSPy-Programming-not-prompting-LMs-skills --skill ai-do

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.