Provenance travels with the claim
- Search subagentclaim + URL + quote + date
- Analysis subagentadds method, keeps source fields
- Synthesismerges, marks conflicts and gaps
- Reportevery claim cited; contested ones flagged
Where provenance gets lost
Each time information passes between agents it is usually condensed. A search subagent reads twenty pages and returns a summary; an analysis agent summarises the summaries; a synthesis agent writes prose. If attribution is not carried as data, it is the first thing to go: “according to the 2025 regulator report, p. 14” becomes “reports suggest”, and by the final draft nobody can say which claim came from where. Anthropic’s multi-agent research write-up describes the same risk as a game of telephone, and lets subagents write outputs to external storage and pass lightweight references rather than routing everything through the lead agent’s retelling.
Passing findings between agents
Flattened into prose
- “Studies show adoption rose sharply”
- Which studies? Which year?
- Two sources merged into one claim
- Report cannot be checked
Structured claim records
- Claim, source, location, quote
- Publication and data dates
- Each source kept separate
- Every sentence traceable
{
"claim": "Adoption among mid-size firms reached 41%",
"source": "https://example.org/survey-2025.pdf",
"location": "page 14, table 3",
"quote": "41% of firms with 50–249 employees…",
"published": "2025-11-03",
"data_period": "Q2 2025",
"method": "survey, n=1,200",
"found_by": "search-subagent-2"
}Instruct every subagent to return findings in this shape, and instruct the synthesis agent to preserve the source fields for every claim it keeps. Anthropic’s long-context guidance points the same way from the input side: wrap each document in its own tagged block with its source as metadata, so the model always knows which text came from where.
Let the API carry the citations
When Claude is answering from documents you supply, the Citations feature removes most of the guesswork. Set citations: {"enabled": true} on document blocks and the response comes back with each supported sentence tied to a location: character ranges for plain text, page numbers for PDFs, block indices for custom content, each with the cited_text. The documentation reports that these citations are more reliable than asking for quotes in the prompt, because the API parses them into guaranteed-valid pointers, and cited_text does not count toward output tokens.
For retrieval systems, search result blocks do the same for your own content. A tool can return search_result blocks, each with a source (a URL or an internal ID such as kb://article-1234), a title and text content; with citations enabled, Claude’s answer carries search_result_location citations that name the source and title you supplied.
def kb_search_result(hits):
# One search_result block per retrieved passage; the source travels with it.
return [{
"type": "search_result",
"source": h.url, # URL or internal ID
"title": f"{h.title} ({h.published})", # dates help explain conflicts
"content": [{"type": "text", "text": h.passage}],
"citations": {"enabled": True},
} for h in hits]
tool_result = {
"type": "tool_result",
"tool_use_id": block.id,
"content": kb_search_result(hits), # all blocks must be search_result
}
# Later, read citations off the answer's text blocks:
for part in response.content:
for c in getattr(part, "citations", None) or []:
print(c.source, "→", c.cited_text[:60])When sources disagree
Conflicting sources are normal in research, and the worst response is a silent one: picking one figure without saying so, or averaging two figures into a number nobody published. Many apparent conflicts are explained by metadata — different years, different definitions, different populations — which is why dates and methods belong in the claim record. When a conflict remains, report both values with their sources and say what might explain the difference.
Two sources give different figures
- Different dates or periodsReport both, datedthe difference may be real change
- Different definitionsReport both, definedstate what each measured
- One source clearly strongerLead with itnote the other and why
- No explanation foundFlag as contestedboth values, both sources
A synthesis sentence, before and after
Smoothedtext
The market grew about 10%
last year.Attributedtext
Estimates differ. Source A
reports 12% growth for 2025
(published Feb 2026, revenue
basis). Source B reports 8%
for FY2025 (Jul–Jun, unit
volume basis). The gap may
reflect the different
measures; no source
reconciles them directly.Show how sure the report is
A useful synthesis distinguishes well-established findings (several independent, strong sources agree) from contested ones (credible sources disagree) and from thin ones (a single source, or a weak one). Structure the output so that difference is visible — separate sections or explicit labels — rather than writing every claim in the same assured tone. Report coverage gaps too: if a source type could not be searched, say so (see 5.3).
Anthropic’s guide to reducing hallucinations adds three habits that fit here: allow the model to say it does not know; have it find supporting quotes before making claims and retract any claim it cannot support; and restrict it to the provided sources when general knowledge should not leak in. Their multi-agent research system ends with a dedicated citation agent that goes through the documents and the report to find a specific source location for each claim. Source quality matters as much as attribution — the same write-up notes that early agents favoured SEO-heavy content farms over authoritative sources until quality heuristics were added to the prompts.
Traps the wrong answers are built from
| Tempting but wrong | Do this instead |
|---|---|
| Passing findings between agents as flowing prose | Pass structured claim records with source, location, quote and dates. |
| Silently choosing one of two conflicting figures | Report both with sources and dates, and explain or flag the conflict. |
| Averaging conflicting values into one number | Keep each value tied to its source; nobody published the average. |
| Writing contested and established claims in the same tone | Label or separate findings by strength of support. |
| Asking the model to add citations at the end from memory | Use API citations or search result blocks, or carry sources from the first hop. |
You should now be able to
- Design claim–source records that preserve provenance across agent hops.
- Enable Citations on documents and use
search_resultblocks for retrieved content. - Handle conflicting sources by reporting both with attribution and explaining differences.
- Use publication and data dates to interpret apparent contradictions.
- Structure synthesis output to separate established, contested and thinly supported findings.
- Know that Citations cannot be combined with structured outputs, and what to do instead.