SKILL 21 / RESEARCH · DEEP-DIVE

Source Grounding & Citation Credibility

The three things a model fabricates most are URLs, quotes and dates · The fix is not "please be careful", it is making it point back

2026-09-22 · BigCat

Last issue nailed citation checking to the end of a research checklist. This one goes a layer down: before you can verify a citation, every sentence needs a position it can point back to — and the official API already has fields that do exactly that.

Prerequisite → Skill 20 Research as a Workflow Skill (where the citation-check step comes from)

// WHY THIS MATTERS

Last issue ended on a hard line: citation checking is not fact checking. A link returning 200 does not mean the sentence came from that page. This issue picks up there. Grounding does not ask "does the model know this". It asks "which document, which character offset, does this sentence come from". There are three tiers of answer: put it in the prompt (cheapest, least reliable), install a skill (portable, still relies on the model's diligence), or use official API fields (the model never gets a chance to invent anything). Below, real items in each tier, and at the end a set of criteria for choosing between them.

// 01

What it kills for you: the three things it almost always invents

Claim: fabrication is not evenly distributed. URLs, verbatim quotes and dates are what a model invents most confidently without tools — they are regular in shape and look like ten thousand it has seen.

The official docs already name the fix

Reduce hallucinations gives three basic strategies, each with a prompt you can lift whole: (1) let it say "I don't know" — the page's own words: This simple technique can drastically reduce false information; (2) extract verbatim quotes before analyzing (for documents over 20k tokens especially); (3) after drafting, find a supporting quote for every claim and delete the ones that have none — the sharp part of that example is its last line: remove that claim from the press release and mark where it was removed with empty [] brackets. Four advanced ones follow: chain-of-thought verification, best-of-N verification, iterative refinement, external knowledge restriction. Free, zero dependencies, and the first thing to read this issue.

Then install these two skills

# Official: makes you look back once it has answered
/plugin marketplace add anthropics/skills
# discernment-nudge lives under skills/, one of 19 official skill dirs

# First usable move: have it pull the quotes first, then you pick
# "Extract exact quotes from this document relevant to X. If you can't find
#  relevant quotes, say 'No relevant quotes found.' Then answer using only
#  those quotes, referencing them by number."

discernment-nudge (official): it does not verify — it makes you verify. After answering, it appends A few things worth a second look: plus 2–3 short questions, each tied to a specific element of the reply and phrased so you could ask them back verbatim. Two hard constraints are worth copying: offer the nudge at most once per conversation, and an explicit skip list — creative writing, casual chat, simple lookups, purely educational questions, and whenever the user has already asked you to verify, cite, or flag uncertainty. When not to install it: you want answers, not follow-up questions, or you already have automated verification in the pipeline — then it is just text you will not read.

truth-first (Agensi marketplace) covers the other half: no claiming "done" without having actually run it. It demands real reads of file contents, configuration and system state before a conclusion. Full disclosure: agensi.io was blocked by this machine's egress policy for this issue, so the page could not be opened — which means no install-count figure and no copied install command here, only its position on the map. If you want the same job with source you can read, see the two GitHub implementations in the next section.

Source · anthropics/skills · skills/ (per the repo directory listing, 2026-09: 19 skill directories, discernment-nudge among them)
// 02

Mechanism: pointing back is an engineering problem, not an attitude problem

Claim: "please cite your sources" in a prompt gets you sources the model generated. Official Citations gets you locations the API parsed. These are not in the same reliability class.
prompt: "cite sources" -> model generates citation-shaped text -> may not exist skill: "quote first" -> model quotes, then checks itself -> diligence, skippable citations:{enabled:true} -> API parses char/page/block locations -> pointer always valid

Official Citations: turning citation from generation into parsing

Set "citations": {"enabled": true} on each document and the reply's text blocks come back carrying citation objects. The official doc's comparison against prompt-based approaches is this issue's core line: citations are guaranteed to contain valid pointers to the provided documents. Three engineering details:

Two server tools, two ways of grounding

web_search: {"type":"web_search_20250305","name":"web_search","max_uses":5}. Citations are forced on — the doc's words: Citations are always enabled for web search. Each web_search_result_location carries url, title and cited_text (up to 150 characters), and those fields likewise cost no tokens. Use allowed_domains to pin searching to official domains. When not to use it: stable knowledge. It bills at $10 per 1,000 searches, plus every retrieved page counting as input tokens.

web_fetch: no additional charge, but citations are off by default — you set "citations": {"enabled": true} yourself. It also has the prettiest mechanism in this issue: it can only fetch URLs that already appeared earlier in the conversation — in user messages, in client-side tool results, or in prior search/fetch results. A URL that exists only in the model's own output cannot be fetched; the tool returns url_not_in_prior_context. A link it invented is physically unreachable. (The design intent is exfiltration defense; the docs carry a Warning against enabling it where the model handles untrusted input alongside sensitive data — see Skill 12 on this site.) Cap long pages with max_content_tokens: a 100 kB doc runs about 25,000 tokens, a 500 kB PDF about 125,000.

The common illusion: believing that "I asked it to cite sources in the prompt" equals grounding. An ungrounded citation is just a correctly formatted string. The reason the API extracts cited_text rather than letting the model emit it is precisely that the model-emitted version is still, fundamentally, generated.
// 03

Real use and limits: four candidates, four criteria

Claim: the items above do not solve the same problem. Decide which class of fabrication you are blocking first — pick the wrong class and you pay the full cost while the incident still happens.

Two more implementations whose source you can read

daymade/claude-code-skills · fact-checker (MIT): takes a finished document and pulls out factual claims to check — context window sizes, pricing, version numbers, release dates, benchmark scores. It hardcodes a source hierarchy: product official pages > API documentation > official blog announcements > GitHub releases, and says explicitly to be careful with third-party aggregators. Whatever it cannot check gets marked ❓ Unverifiable with a recommendation to soften the wording, and no correction lands without your explicit approval. When not to install it: subjective claims, paywalled sources, genuinely disputed facts — it declares all three out of scope itself.

geigermatic/claude-craft · verify-claim (MIT, one of 6 skills in the repo): aimed at what it calls the single most expensive failure mode of AI-assisted coding: confident wrongness. The method turns assertions into runnable evidence: state the claim as one specific, falsifiable sentence, match it to a mechanism (file read, grep, curl), run it, then report exactly one of three verdicts — Verified / Refuted / Inconclusive — with file:line, and do not summarize prematurely (three grep hits means report all three). When not to install it: it draws the line itself — things obvious from a file you just read, and trivial claims with low blast radius, do not deserve the ceremony.

michaelwjohnson/claude-skills · check-claims: a set of three — occams-razor, check-claims, writing-review — installed individually after claude plugin marketplace add michaelwjohnson/claude-skills. Its ordering argument is the interesting part: run the razor before the fact check, because "cutting changes which claims are still load-bearing, and because a cut leaves orphans that are themselves often false." Honest cost: per the GitHub repo page, 2026-09, it has 0 stars, 0 forks and 11 commits on main — its value is that the ordering argument copies straight into your own process, not that it has been validated. Same for frmoretto/source-of-truth-creator (CC BY 4.0), whose list of overconfidence traps (unmarked estimates, self-assessment bias, absence-as-proof, illustrative-as-data, staleness) is worth reading as a checklist — but per its repo page, 2026-09, it has 3 stars and 2 commits. Read it; don't depend on it.

The criteria: choose by which class of fabrication you are blocking

  1. It invents links or quote locations → only API fields stop this. Citations for documents you hold; web_search (forced citations) or web_fetch (opt in) for the web. Skills are powerless in this cell.
  2. It invents numbers and versions → fact-checker; its source hierarchy was written for this cell. Stack last issue's verify_citations.py on top to sweep the link layer.
  3. It invents "I ran it / I confirmed it" → verify-claim or truth-first. Both want tool output as evidence, not phrasing.
  4. You are the one who will not double-check → discernment-nudge. Its only output is three things worth re-checking; it treats the human, not the model.
This section's hard line: secondary aggregators are not sources. Name-checking for this issue hit it twice — an SEO site put source-of-truth-creator's failure modes at 6 where the repo itself lists 8; another rendered the official web-artifacts-builder as artifacts-builder. Use aggregators to discover candidates; take every name, number and count back to the GitHub directory or the official page.
// 04

Costs and alternatives: grounding is not free, and one cell stays empty forever

Claim: grounding can prove "this sentence came from here". It can never prove "what is here is correct". Treating that cell as solved is where the real incidents come from.

Three bills

What to do if you install nothing at all

  1. Copy the three official prompts. "Say I don't know", "extract quotes before analyzing", "delete any claim with no supporting quote and leave empty [] brackets" — zero cost, covers most of it.
  2. Add one hard rule to CLAUDE.md: any number someone will act on must carry its source and the source page's own date; every name comes from a GitHub directory or an official page. (This repo's rule reads exactly that way, and it is what caught the two wrong names in the previous section.)
  3. Make "actually retrieved" a precondition: no URL appears in a finished draft unless it was really fetched. web_fetch's url_not_in_prior_context turns that into an error code — you can also just make it a rule of your own.
The cell that stays empty: Citations guarantees the pointer resolves, verify_citations.py guarantees the DOI exists, web_fetch guarantees the link was really retrieved — none of them can judge whether the correctly cited passage actually supports the conclusion you wrote. That step is still a human one.

// ONE-PAGE BUYING CARD

Do these three first: (1) read Reduce hallucinations and copy the "say I don't know" and "delete unsupported claims, leave empty []" prompts into your template. (2) /plugin marketplace add anthropics/skills, enable only discernment-nudge at first, and let it name three things per conversation that deserve a second look. (3) If you have documents to ask about, add "citations": {"enabled": true} to every document in your API calls — it is the only tier here that yields a pointer guaranteed to be valid.

Add as needed: web_search (you need current information and accept $10/1,000) · web_fetch + citations.enabled (you already have URLs and need passage-level citations, in a trusted environment) · daymade/claude-code-skills's fact-checker (drafts heavy on numbers and versions) · geigermatic/claude-craft's verify-claim (to block "I ran it") · truth-first (same job, Agensi marketplace, read its SKILL.md yourself before installing) · 199-biotechnologies/claude-deep-research-skill's verify_citations.py (sweep the link layer before filing).

Explicitly don't: treat "please cite your sources" in a prompt as grounding · treat michaelwjohnson/claude-skills (0 stars) or source-of-truth-creator (3 stars) as a validated dependency rather than reading material · copy names and numbers from secondary aggregators · assume that passing grounding and citation checks means the conclusions were checked.

// GLOSSARY

grounding
Making every sentence in an output point back to a specific position in a specific piece of material. It governs locatability, not correctness.
Citations (the official feature)
With citations.enabled set on a document, the API parses citations into structured objects carrying locations. The doc's own claim: the pointers are guaranteed valid.
char_location / page_location / content_block_location
The three citation location types, for plain text (character offsets), PDFs (page numbers) and custom content (block indices) respectively.
cited_text
The quoted passage, extracted by the API rather than generated by the model, counting toward neither input nor output tokens.
url_not_in_prior_context
web_fetch's error code for a URL that never appeared earlier in the conversation. A link the model invented therefore cannot be retrieved.
load-bearing claim
verify-claim's term: a claim you intend to act on, where being wrong costs real work. Only these deserve the full verification procedure.
Verified / Refuted / Inconclusive
The three verdicts. The third matters most — it means "not found", not "false". Conflating them turns absent evidence into counter-evidence.

// FURTHER READING