Grade and fall back (default)

Corrective RAG diagramQuestion, Retriever, Doc grader, Rewriter, Web search, Generator, Answer check, Answer. Step captions follow the diagram.QuestionRetrieverDoc graderRewriterWeb searchGeneratorAnswer checkAnswerCorrective RAG diagramQuestion, Retriever, Doc grader, Rewriter, Web search, Generator, Answer check, Answer. Step captions follow the diagram.QuestionRetrieverDoc graderRewriterWeb searchGeneratorAnswercheckAnswer

All steps

Retrieved docs are irrelevant

Good docs, but the draft fails the check

Parts of this pattern
Question Input / output
The user's question, e.g. 'Who is our current vendor for payroll?', sent to the internal index first.
Retriever Memory
Searches the internal index and returns the top documents for the question, relevant or not.
Doc grader Evaluator
Reads each retrieved document and returns JSON saying whether it contains facts needed for the answer.
Rewriter LLM call
When every document is rejected, turns the question into one sharp web query using the rejection reasons.
Web search Tool
External web search that replaces the failed internal retrieval with fresh documents.
Generator LLM call
Writes the answer from the kept or web documents, revising when the answer check flags claims.
Answer check Evaluator
Checks every claim in the draft against the documents and lists any unsupported claims.
Answer Input / output
The final answer: released once the check passes, or the best answer after retries run out.
Question → Retriever
The question goes to the internal retriever.Question: Who is our current vendor for payroll?
Retriever → Doc grader
The top retrieved documents are handed to the grader one by one.4 docs: [{"id": "kb-112", "text": "Payroll vendor evaluation notes, 2021..."}, ...]
Doc grader → Rewriterirrelevant
If no document is relevant, the grader's reasons go to the rewriter.{"relevant": false, "reason": "Discusses a 2021 payroll vendor evaluation, not the current vendor."}
Doc grader → Generatorrelevant
Documents graded relevant skip the web and go straight to the generator.{"relevant": true, "reason": "States the current payroll vendor and contract end date."} -> 2 docs kept
Rewriter → Web search
The rewriter's single query is sent to web search.Web query: "Acme Corp payroll provider 2026"
Web search → Generator
Web results become the generator's documents.web docs: ["Acme Corp switched payroll to Gusto in March 2025 (press release)", ...]
Generator → Answer check
Each draft answer goes to the check along with the documents it should rest on.Acme uses Gusto for payroll since March 2025, on a three-year contract.
Answer check → Generatorunsupported
Unsupported claims go back to the generator so it can drop or fix them.{"supported": false, "unsupported_claims": ["on a three-year contract"]}
Answer check → Answersupported
A fully supported answer leaves the pipeline unchanged.{"supported": true, "unsupported_claims": []}

Self-RAG

One model decides on demand whether to retrieve, then critiques each passage and its own output with reflection tokens; there is no separate grader.

Corrective RAG: Self-RAG diagramQuestion, Self-RAG model, Retriever, Answer. Step captions follow the diagram.QuestionSelf-RAG modelemits reflection tokensRetrieverAnswerCorrective RAG: Self-RAG diagramQuestion, Self-RAG model, Retriever, Answer. Step captions follow the diagram.QuestionSelf-RAGmodelemits reflectiontokensRetrieverAnswer

All steps

Retrieves, then critiques the passages

No retrieval needed

Parts of this pattern
Question Input / output
The user's question, e.g. 'Who is our current vendor for payroll?'.
Self-RAG model LLM call
One model that decides whether to retrieve, tags each passage's relevance and rates how well each segment is supported.
Retriever Memory
The internal index, searched only when the model emits Retrieve=Yes.
Answer Input / output
The answer built from the best-scored segments, each carrying its support tag.
Question → Self-RAG model
The question goes straight to the model; there is no up-front retrieval.Question: Who is our current vendor for payroll?
Self-RAG model → Retriever[Retrieve]
When the model emits Retrieve=Yes, the question plus the answer so far is sent to the index.[Retrieve=Yes] query: "current payroll vendor"
Retriever → Self-RAG modelpassages
Each passage gets its own candidate segment, and the model tags each passage's relevance.kb-112 2021 vendor review [IsRel=Irrelevant]; kb-207 Gusto contract, March 2025 [IsRel=Relevant]
Self-RAG model → Answer[IsSup]
The best-scored candidate, relevant and fully supported, becomes the answer.Acme has used Gusto for payroll since March 2025. [IsSup=Fully] [IsUse=5]

Groundedness loop

After generating, a grader checks that the answer is grounded and on-topic: ungrounded answers regenerate, and off-topic ones rewrite the query and retrieve again.

Corrective RAG: Groundedness loop diagramQuestion, Retriever, Generator, Answer grader, Rewriter, Answer. Step captions follow the diagram.QuestionRetrieverGeneratorAnswer graderRewriterAnswerCorrective RAG: Groundedness loop diagramQuestion, Retriever, Generator, Answer grader, Rewriter, Answer. Step captions follow the diagram.QuestionRetrieverGeneratorAnswergraderRewriterAnswer

All steps

The first answer misses the question

An ungrounded claim is dropped

Parts of this pattern
Question Input / output
The user's question, e.g. 'Who is our current vendor for payroll?'.
Retriever Memory
The internal index, searched with the question and again with any rewritten query.
Generator LLM call
Writes the answer from the retrieved documents, and rewrites it when claims are flagged as unsupported.
Answer grader Evaluator
Checks the answer twice: are its claims in the documents, and does it answer the question at all?
Rewriter LLM call
Turns a question the search missed into a sharper query.
Answer Input / output
An answer that is both grounded and on the question.
Question → Retriever
The question is the first search query.Question: Who is our current vendor for payroll?
Retriever → Generatordocs
The top documents go to the generator.4 docs: "Payroll runs on the 25th of each month...", "Payroll FAQ..."
Generator → Answer graderanswer
Each answer is graded with the documents it should rest on.Payroll runs on the 25th of each month.
Answer grader → Generatorredraft
If the answer is ungrounded, the claims not found in the documents go back so the generator can drop or fix them.{"grounded": false, "answers_question": true, "unsupported_claims": ["on a three-year contract"]}
Answer grader → Rewriteroff-topic
A grounded answer that misses the question means the search missed, so the query is rewritten.{"grounded": true, "answers_question": false, "unsupported_claims": []}
Rewriter → Retrievernew query
The rewritten query is searched, and the loop continues with the new documents.payroll provider contract vendor name 2025
Answer grader → Answergrounded
An answer that passes both checks leaves the loop.Acme has used Gusto for payroll since March 2025.

← → neighboursesc atlas

Knowledge & Memory

Corrective RAG

Also known as CRAG

Grade the retrieved documents. If they're irrelevant, rewrite the query and fall back to web search before generating.

Self-RAG: Introduced by Asai et al. (2023) · University of Washington, Allen Institute for AI and others

Self-RAG trains the model to emit the reflection tokens itself (ICLR 2024). With an untrained model, a prompt can ask for the same tags, less reliably.

Groundedness loop: No single inventor · see source

No single originator. It combines CRAG's query rewriting with Self-RAG-style checks of the answer for groundedness and relevance; LangChain's 'Self-Reflective RAG with LangGraph' (February 2024) describes this loop.

Measured over one run

Grade and fall back

Nodes
8. Boxes in the diagram: models, tools, stores, people and plain code.
LLM calls
4. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
Tool calls
1. Messages sent to a tool node in the first scenario.
Steps
5. Steps in the first scenario, with repeated steps counted every time they run.
Scenarios
2. Distinct example runs you can switch between on the diagram.
Loop
yes. Whether the flow cycles back on itself until a condition is met.
Parallel
no. Whether two or more messages are in flight at the same time.
Branch
yes. Whether the flow takes one path out of several, chosen at run time.
Human in the loop
no. Whether a person appears as a node, to approve, correct or answer.
Autonomy
low. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
Cost
medium. Relative token spend per request.
Latency
medium. Relative wall-clock time per request.

Self-RAG

Nodes
4. Boxes in the diagram: models, tools, stores, people and plain code.
LLM calls
4. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
Tool calls
0. Messages sent to a tool node in the first scenario.
Steps
4. Steps in the first scenario, with repeated steps counted every time they run.
Scenarios
2. Distinct example runs you can switch between on the diagram.
Loop
no. Whether the flow cycles back on itself until a condition is met.
Parallel
no. Whether two or more messages are in flight at the same time.
Branch
yes. Whether the flow takes one path out of several, chosen at run time.
Human in the loop
no. Whether a person appears as a node, to approve, correct or answer.
Autonomy
low. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
Cost
medium. Relative token spend per request.
Latency
medium. Relative wall-clock time per request.

Groundedness loop

Nodes
6. Boxes in the diagram: models, tools, stores, people and plain code.
LLM calls
5. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
Tool calls
0. Messages sent to a tool node in the first scenario.
Steps
4. Steps in the first scenario, with repeated steps counted every time they run.
Scenarios
2. Distinct example runs you can switch between on the diagram.
Loop
yes. Whether the flow cycles back on itself until a condition is met.
Parallel
no. Whether two or more messages are in flight at the same time.
Branch
yes. Whether the flow takes one path out of several, chosen at run time.
Human in the loop
no. Whether a person appears as a node, to approve, correct or answer.
Autonomy
low. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
Cost
medium. Relative token spend per request.
Latency
medium. Relative wall-clock time per request.

Counted from the first scenario's timeline when the site is built.

Problem

A RAG pipeline trusts its retriever. Whatever the vector search returns, relevant or not, is stuffed into the prompt, and the model dutifully writes an answer from it. When the index has nothing useful, the result is a fluent answer built on the wrong documents, which is worse than no answer.

How it works

The retriever fetches candidate documents for the question as usual. Before the generator sees them, a document grader scores each one for relevance. This is the correction step.

If the grader keeps some documents, they go straight to the generator. If it rejects all of them, a rewriter turns the question into a better query and a web search supplies fresh documents instead. Imagine asking about a library’s breaking change released last week: an index built in spring returns docs about old versions, the grader rejects them, and the web query “libfoo 4.0 breaking changes” finds the release notes.

A second check runs after generation. An answer check verifies that every claim is supported by the documents. Unsupported claims loop back to the generator as feedback, and a supported answer goes to the output.

This page shows a simplified composite of two papers. Real CRAG grades retrieval as correct, incorrect or ambiguous and refines documents by decomposing and recomposing them, and the answer check here is Self-RAG-style critique done with a separate prompt. The Self-RAG tab shows the original, where one model decides when to retrieve and critiques passages and its own output with trained reflection tokens. The Groundedness loop tab grades the answer instead of the documents, and retrieves again when the answer misses the question.

When to use

  • Your index is incomplete or stale, so retrieval sometimes misses entirely.
  • A confidently wrong answer costs more than a slow one.
  • You have a fallback source, such as web search or a second index.

When to avoid

  • The index is small and curated and retrieval nearly always hits.
  • Latency is tight. Grading each document adds calls before generation even starts.
  • You cannot write a relevance rubric the grader can follow consistently.

Trade-offs

Grading adds one call per retrieved document (batch them or use a small model) and a possible extra web round trip. You pay that on every query, including the easy ones, in exchange for catching bad retrievals. The post-generation check adds another call per draft.

Failure modes

  • Over-rejection: a strict grader throws away useful documents and forces needless web searches. Test the grader against labelled examples.
  • Under-rejection: a lenient grader passes plausible but off-topic text. Require the grader to quote the supporting fact.
  • Bad fallback: the web returns noisy pages that are just as irrelevant. Grade the fallback results too.
  • Check loops: the answer check never passes. Cap the rounds and return the best draft with a caveat.

Build it with your AI

Grade and fall back

Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.

Implement the Corrective RAG pattern in this codebase, using the LLM client and language we already use.

## Goal

Answer a question from an internal index, but grade the retrieved documents first, fall back to a rewritten web search when none is relevant, and check the answer against its documents.

## How it works

1. Retrieve the top 4 documents for the question from the internal index.
2. Grade each document with the Document grader prompt, parsing its JSON into relevant and reason, and keep the relevant ones.
3. If none is relevant, call the Query rewriter prompt with the question and the rejection reasons, run its query on web search, and use the web results as the documents.
4. Generate an answer from the documents, then run the Answer check prompt on it and parse the list of unsupported claims.
5. If any claim is unsupported, regenerate with that list, telling the model to drop or fix those claims, and check again.

## Prompts

### Document grader prompt

```markdown
You grade whether a retrieved document helps answer a question.

<question>{{question}}</question>
<document>{{doc}}</document>

Respond in JSON: {"relevant": true|false, "reason": "one sentence"}
Mark relevant only if the document contains facts needed for the answer.
A document on the same topic that does not answer the question is not relevant.
```

### Query rewriter prompt

```markdown
The internal search returned nothing useful for this question.

<question>{{question}}</question>
<rejected_reasons>{{reasons}}</rejected_reasons>

Write one web search query that would find the missing facts. Use specific
terms and names, not the full question. Return only the query.
```

### Answer check prompt

```markdown
Check whether every claim in the answer is supported by the documents.

<documents>{{docs}}</documents>
<answer>{{answer}}</answer>

Respond in JSON:
{"supported": true|false, "unsupported_claims": ["claim", "..."]}
```

## Stop rule

Stop when the check finds every claim supported, or after 2 regenerations. At the cap, return the last answer with its unsupported claims removed, and a status saying the check did not fully pass.

## Requirements

- Make the documents retrieved (default 4) and the regeneration cap (default 2) parameters.
- If a grader reply is not valid JSON, treat that document as not relevant and log the raw reply.
- If web search fails or returns nothing, reply that the answer could not be found rather than generating from rejected documents.
- Log every grade with its reason, the rewritten query and each check result.
- Add a test with a stub grader that rejects all 4 documents and a stub web search; assert the rewriter ran once, web search ran once, and the generator received only the web documents.

Self-RAG

Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.

Implement the Corrective RAG pattern (Self-RAG variant) in this codebase, using the LLM client and language we already use.

## Goal

Let one model decide on demand whether to retrieve, judge each passage's relevance and its own output's support with reflection tokens, and keep the best-scored continuation.

## How it works

1. Use a model trained, or prompted with the Self-reflective answer prompt, to emit reflection tokens: Retrieve (yes, no, or continue to reuse the current passages), IsRel (relevant or irrelevant), IsSup (fully, partially or not supported) and IsUse (1 to 5).
2. Generate the next segment. If the model emits Retrieve=yes, search the index with the question plus the answer so far and take the top 4 passages.
3. For each passage, generate a candidate segment in parallel and read the IsRel and IsSup tokens the model emits for it.
4. Score each candidate as a weighted sum of its IsRel, IsSup and IsUse tokens, keep the best one and append it to the answer (the paper keeps the top 2 with a beam search).
5. When the model emits Retrieve=no, generate the segment without passages.
6. If a candidate's reflection tokens cannot be parsed, give it the lowest score instead of failing the request.

## Prompts

### Self-reflective answer prompt

```markdown
Answer the question one short segment at a time.

<question>{{question}}</question>
<answer_so_far>{{answer}}</answer_so_far>
{{#if passage}}<passage>{{passage}}</passage>{{/if}}

Before each segment, write [Retrieve=Yes] if you need a new document,
[Retrieve=Continue] to keep using the current passage, else [Retrieve=No].
If a passage is given, write [IsRel=Relevant] or [IsRel=Irrelevant] for it.
If a passage was given, after the segment write [IsSup=Fully], [IsSup=Partially]
or [IsSup=No] for how well it supports the segment.
Finally write [IsUse=1..5] for the segment's usefulness.
```

## Stop rule

Stop when the model ends its answer, or after 6 segments. Return the answer with each segment's IsSup tag, so partly supported text can be shown as such.

## Requirements

- Make the segment cap (default 6), the passages per retrieval (default 4) and the score weights (defaults IsRel 1.0, IsSup 1.0, IsUse 0.5) parameters.
- Expose a retrieval threshold: retrieve when the probability of Retrieve=yes is above it (default 0.2), where the model exposes token probabilities.
- Log every segment's candidates with their reflection tokens and scores.
- Add a test with a stub model that emits Retrieve=no for a rewording task; assert the retriever is never called and one segment is returned.

Groundedness loop

Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.

Implement the Corrective RAG pattern (Groundedness loop variant) in this codebase, using the LLM client and language we already use.

## Goal

Answer from retrieved documents, then grade the answer itself: regenerate when it is not grounded in the documents, and rewrite the query and retrieve again when it does not answer the question.

## How it works

1. Retrieve the top 4 documents for the question and generate an answer from them.
2. Grade the answer with the Answer grader prompt, parsing its JSON into grounded, answers_question and unsupported claims.
3. If both checks are true, return the answer.
4. If grounded is false, regenerate from the same documents, passing the unsupported claims to drop or fix.
5. If grounded is true but answers_question is false, call the Query rewriter prompt for a new query, retrieve again and regenerate.
6. If the grader's JSON does not parse, retry once; if it fails again, treat the answer as not grounded.

## Prompts

### Answer grader prompt

```markdown
Grade an answer against the documents it was written from and the question.

<question>{{question}}</question>
<documents>{{docs}}</documents>
<answer>{{answer}}</answer>

Respond in JSON:
{"grounded": true|false, "answers_question": true|false,
 "unsupported_claims": ["claim", "..."]}
grounded is true only if every claim is stated in the documents.
```

### Query rewriter prompt

```markdown
The answer below did not address the question, so the search missed.

<question>{{question}}</question>
<answer>{{answer}}</answer>

Write one search query that would find the missing facts. Use specific
terms and names, not the full question. Return only the query.
```

## Stop rule

Stop when both checks pass, or after 3 loops in total, regenerations and re-retrievals together. At the cap, reply that no supported answer was found and return the last documents.

## Requirements

- Make the total loop cap (default 3) and the documents per retrieval (default 4) parameters.
- Cap re-retrievals separately (default 2), so a poor index cannot use up every loop. If a retrieval fails or returns nothing, reply that no supported answer was found.
- Log each grade with the loop it triggered.
- Add a test with a stub grader that returns answers_question=false once and then passes both checks, and a stub rewriter that returns 'payroll vendor contract'; assert two retrievals, the second with the query 'payroll vendor contract', and that the second answer is returned.

Prompt templates

Grade and fall back

Document grader prompt
You grade whether a retrieved document helps answer a question.
<question>{{question}}</question>
<document>{{doc}}</document>
Respond in JSON: {"relevant": true|false, "reason": "one sentence"}
Mark relevant only if the document contains facts needed for the answer.
A document on the same topic that does not answer the question is not relevant.
Query rewriter prompt
The internal search returned nothing useful for this question.
<question>{{question}}</question>
<rejected_reasons>{{reasons}}</rejected_reasons>
Write one web search query that would find the missing facts. Use specific
terms and names, not the full question. Return only the query.
Answer check prompt
Check whether every claim in the answer is supported by the documents.
<documents>{{docs}}</documents>
<answer>{{answer}}</answer>
Respond in JSON:
{"supported": true|false, "unsupported_claims": ["claim", "..."]}

Self-RAG

Self-reflective answer prompt
Answer the question one short segment at a time.
<question>{{question}}</question>
<answer_so_far>{{answer}}</answer_so_far>
{{#if passage}}<passage>{{passage}}</passage>{{/if}}
Before each segment, write [Retrieve=Yes] if you need a new document,
[Retrieve=Continue] to keep using the current passage, else [Retrieve=No].
If a passage is given, write [IsRel=Relevant] or [IsRel=Irrelevant] for it.
If a passage was given, after the segment write [IsSup=Fully], [IsSup=Partially]
or [IsSup=No] for how well it supports the segment.
Finally write [IsUse=1..5] for the segment's usefulness.

Groundedness loop

Answer grader prompt
Grade an answer against the documents it was written from and the question.
<question>{{question}}</question>
<documents>{{docs}}</documents>
<answer>{{answer}}</answer>
Respond in JSON:
{"grounded": true|false, "answers_question": true|false,
"unsupported_claims": ["claim", "..."]}
grounded is true only if every claim is stated in the documents.
Query rewriter prompt
The answer below did not address the question, so the search missed.
<question>{{question}}</question>
<answer>{{answer}}</answer>
Write one search query that would find the missing facts. Use specific
terms and names, not the full question. Return only the query.

Related patterns

Composes well with:

Sources

  1. Corrective Retrieval Augmented Generation (Yan et al., 2024)
  2. Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection (Asai et al., 2023)

From the Agentic Atlas by Joran Kikke · Edit on GitHub · Suggest a correction