Source-Required LLM Research: No Citation, No Ship

By Simeon Matheka, Founder & Creative Director · Published 2026-10-01 · Updated 2026-10-01 · 15 min read

A research summary with no link is a rumor in a nice font. Make every claim carry a URL, a quote, and a retrieval date, validate that shape before a human sees it, and drop whatever cannot be sourced.

A research memo with a bold NO SOURCE stamp pressed over an unsupported line, beside a neat stack of citation cards

The summary reads well. Three competitors, a table of positioning, a confident line about who just raised prices. You paste it into a client deck. Later someone asks where the price line came from, and nobody can say. The model did not lie on purpose. It just wrote the likeliest sentence, and the likeliest sentence was not on any page.

Research is the job where a fluent wrong answer costs the most, because it looks finished. This page gives you a rule and a gate. The rule: no citation, no ship. The gate comes after you have run a workflow through an evaluation before production. Here the thing you evaluate is whether each claim can be traced.

The rule: a claim is a record, not a sentence

Stop asking a large language model (LLM) for a summary. Ask it for a list of claim records. Each record carries the statement, the URL it came from, a verbatim quote from that page, the date the page was fetched, and a source type. A summary for humans is rendered afterward from the records that pass.

flowchart LR
    A["Fetch page text"] --> B["LLM extracts claims"]
    B --> C{"Schema valid?"}
    C -->|No| X["Reject, log"]
    C -->|Yes| D{"Quote found in page text?"}
    D -->|No| Y["Drop claim, log"]
    D -->|Yes| E["Human review queue"]
    E -->|Approve| F["Ship"]
    E -->|Reject| X

Pin the shape with a schema

A claim record is a contract, so validate it before anything else happens. JSON Schema is the standard way to describe the shape of JSON data. Sourced: JSON Schema 2020-12 (checked 1 October 2026).

JSON Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": ["claim", "url", "quote", "retrieved_on", "source_type"],
  "properties": {
    "claim": { "type": "string", "minLength": 10, "maxLength": 240 },
    "url": { "type": "string", "pattern": "^https://" },
    "quote": { "type": "string", "minLength": 20, "maxLength": 400 },
    "retrieved_on": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
    "source_type": {
      "type": "string",
      "enum": ["primary", "vendor", "press", "forum", "unknown"]
    }
  }
}

Quote check (JS)

// pageText is the text YOUR workflow fetched, not text the model supplied.
const norm = (s) => s.replace(/\s+/g, ' ').trim().toLowerCase();

function quoteIsReal(record, pageText) {
  return norm(pageText).includes(norm(record.quote));
}

// Keep only records whose quote appears in the fetched page.
const kept = records.filter((r) => quoteIsReal(r, pageText));
const dropped = records.length - kept.length;
// Log dropped. A rising drop rate means the prompt or model changed.

Hypothetical claim record. The quote is required and capped, the date is a string your script parses, and source_type is a closed list.

The quote check is deliberately dumb. It does not understand meaning, so a model can still quote a real sentence and draw the wrong conclusion. What it catches is the invented quote and the invented page, and those are the loud failures. The human review step catches the misread.

Four checks, in order

CheckWho runs itFails when
Schema validScriptA field is missing, the URL is not https, or the source type is outside the list.
Quote present in fetched textScriptThe quote does not appear on the page your workflow actually downloaded.
Claim supported by quoteHuman reviewerThe quote is real but says something narrower, older, or different.
Source type fits the claimHuman reviewerA forum post is carrying a pricing or legal claim that needs a primary page.

Scripts go first because they are cheap and never tired. People go last because their attention is the expensive part. Do not hand a reviewer a record that already failed a machine check.

Source types and what each can carry

Not all citations weigh the same. Labeling the type lets a reviewer calibrate in a second instead of re-deriving it every time.

Source typeGood forNot enough for
Primary (spec, law, official docs)Technical rules, definitions, limits, legal wording.Opinions about how well a product works in practice.
Vendor pageWhat a company says it offers today, including its own prices.Independent performance claims or comparisons.
PressAnnouncements, funding, launches, with a named outlet and date.Product details the article may have simplified.
Forum or social postLeads and questions to investigate.Any claim you will print or send. Chase a primary source first.
UnknownNothing. It routes to a human to classify.Anything.

Drop, do not repair

The tempting move is a second model pass that “fixes” a claim with a missing source. Do not. A repair pass asks the model to find support for a sentence it already wrote, and models are good at finding support that sounds right. Instead, move the claim to an unsupported list. A person can chase it by hand or let it die.

  • Dropped: Quote not found. The claim never reaches the output, and the drop is logged with the run id.
  • Parked: Quote found but the source type is weak for the claim. It goes to the reviewer with a flag.
  • Shipped: Schema valid, quote present, reviewer approved. The output keeps the URL and retrieval date next to the sentence.

Retrieval date is not decoration

Pages change. A competitor’s pricing page on Tuesday may not match the one a reviewer opens on Friday. Store the retrieval date, and if the stakes justify it, store a copy of the fetched text with the run. That gives you something to compare when someone says “that is not what the page says.”

Be careful about what the fetch is allowed to touch. The Robots Exclusion Protocol (RFC 9309) says plainly that it is not a substitute for real content security, and that paths listed in robots.txt are publicly discoverable. A fetch step should respect the rules a site publishes, stay on public pages, and never use a logged-in session you do not own. Sourced: RFC 9309, section 3 (checked 1 October 2026).

Filled hypothetical: a brief on a rival’s new offer

Hypothetical, not a client. You ask a workflow to summarize a rival’s new service page. It returns nine claims. The schema check passes all nine. The quote check drops two: the model paraphrased a sentence and presented the paraphrase as a quote. Of the seven left, a reviewer flags one that cites a forum thread for a pricing claim. Six ship, one is parked until someone finds the pricing page.

That is a boring result, and it is the right one. The brief is shorter than the model’s first draft and every line has a link. If a client asks where something came from, the answer is one click.

What this does not prove

A source-required workflow narrows one failure: claims with no support. It does not make the sources good, and it does not catch a misread of a real quote. It also does nothing about attacks hidden inside fetched pages. The Open Worldwide Application Security Project (OWASP) describes prompt injection as inputs that alter a model’s behavior, including inputs a human cannot see. Treat page text as data, never as instructions, and keep any tool that can send or write out of the same step.

Sourced: OWASP LLM01:2025 Prompt Injection (checked 1 October 2026). For the approval queue itself, see human-in-the-loop review for n8n and LLM jobs.

Print the blank source-required research card and tick it before a research workflow feeds anything a client will read. Pair it with a shared context pack so the workflow knows what it may and may not say. If you want a second pair of eyes on the schema or the review queue, get in touch.

Frequently asked questions

Why not just ask the model to cite its sources?

Because a model can produce a citation-shaped string that points at nothing. The fix is structural. The workflow fetches the page, passes the text in, and requires every claim to quote a span from that text. Then a script checks that the quote really appears in the fetched page. The model does not get to vouch for itself.

What is a claim-level source?

One URL, one verbatim quote, and one retrieval date attached to one statement. A bibliography at the bottom of a summary does not count. If a reviewer cannot click from a sentence to the exact supporting passage, the sentence is unsourced.

Does a source guarantee the claim is true?

No. It guarantees the claim is traceable. A vendor’s own page can be marketing, outdated, or wrong. Label the source type (primary, vendor, press, forum) so the reviewer weighs it correctly.

What should happen to a claim with no source?

Drop it from the shipped output and log it. You can keep it in an “unsupported” bucket for a human to chase, but it never enters a deck, a brief, or an email. No citation, no ship.

Can this run without a human?

For internal notes that nobody acts on, a weekly sample review can be enough. If the output feeds a customer message, a price, a campaign, or a decision, a person approves it. Use the human-in-the-loop (HITL) queue pattern.

Is search grounding the same thing?

Not necessarily. Grounding with a search tool can attach links, but you still need to confirm the quoted text exists on the page and that the page says what the summary claims. Treat any model-supplied link as a lead to check, not as proof.

Tags: LLM research, citations, source verification, JSON Schema, human in the loop, AI marketing, fact checking