Advanced RAG Patterns for ASP.NET Core Developers
Routing, decomposition, parent retrieval, HyDE, Corrective RAG, GraphRAG and bounded agentic retrieval
Standard retrieval-augmented generation has a useful shape:
- receive a question;
- retrieve relevant chunks;
- place those chunks into a controlled context;
- generate a grounded answer with citations.
Which delayed construction projects have problems similar to Riverside, and what actions worked previously?This requires the system to identify Riverside, establish its current problems, find genuinely comparable projects, retrieve historical actions, compare outcomes and separate evidence from recommendation. One vector query is unlikely to perform every operation reliably.
Advanced RAG is not one product or algorithm. It is a collection of patterns that make retrieval more selective, adaptive or capable when a measured failure demands it.
This guide uses BuildEstate Pro, my public property-development case study. The RAG designs are teaching extensions rather than claims that these features already exist in the repository.
The central engineering principle is:
Do not make RAG more complicated until you can explain exactly which demonstrated failure the additional complexity is fixing.
1. Standard RAG should remain the baseline
Before adding advanced patterns, build a dependable foundation:
- authoritative sources and permission-aware ingestion;
- meaningful chunks and provenance;
- keyword, vector or hybrid retrieval;
- current-version and tenant filters;
- calibrated evidence thresholds;
- controlled citations;
- separate retrieval and answer evaluation.
Advanced orchestration cannot repair a missing source, broken ACL, stale index or evaluation gap. It can make those weaknesses harder to diagnose by surrounding them with more model calls.
Begin with a labelled set of realistic questions. Know where the baseline fails. Then add one pattern, compare it with the baseline and keep it only when the improvement justifies its operational cost.
2. Start with a failure-to-pattern map
The most useful way to learn advanced RAG is to connect each pattern to a specific problem.
| Observed failure | Candidate pattern |
|---|---|
| Wrong source is searched | Query routing |
| One question contains several information needs | Query decomposition |
| Precise child chunk lacks an exception or scope | Parent retrieval |
| Retrieved section is relevant but excessively long | Contextual compression |
| Query and corpus use very different language | HyDE or controlled expansion |
| Retrieved evidence is weak or incomplete | Corrective retrieval |
| Whether to retrieve changes by question | Adaptive/self-reflective controller |
| Answer depends on relationships across a corpus | GraphRAG |
| Investigation needs several conditional steps | Bounded agentic RAG |
| Live facts and written explanations differ | Structured plus unstructured retrieval |
3. Query routing asks where to look
BuildEstate Pro might expose several knowledge sources:
- SQL Server for current project state and financial values;
- planning-report index for unstructured conditions and explanations;
- contract index for clauses and amendments;
- policy index for internal rules;
- correspondence archive for communications;
- approved external sources for current regulations.
What is Riverside's current budget variance?This belongs in an authorised SQL/API operation.
What does the signed contract say about delay damages?This belongs in the current contract index.
A router chooses retrieval capabilities; it does not answer the question.
public enum KnowledgeSource
{
ProjectDatabase,
PlanningIndex,
ContractIndex,
PolicyIndex,
ApprovedExternalRegulations
}
public sealed record RoutingDecision(
IReadOnlyCollection<KnowledgeSource> Sources,
bool RequiresCurrentData,
bool RequiresDecomposition,
string DecisionCode,
double Confidence);
Prefer deterministic routing when intent is clear: exact project metrics go to the project service; contract clause lookup goes to the contract index. A model-based router can handle ambiguous language, but use a structured output contract, an allow-list of sources and a safe fallback.
Never let the router invent a data source, bypass permissions or turn an internal question into unrestricted web search.
4. Treat routing as a security and reliability boundary
A routing decision changes which tools and data become reachable. Validate it in application code.
public sealed class AuthorisedRetrievalRouter(
IIntentClassifier classifier,
ISourceAuthorisation authorisation)
{
public async Task<RoutingDecision> RouteAsync(
RetrievalRequest request,
CancellationToken cancellationToken)
{
var proposed = await classifier.ClassifyAsync(request, cancellationToken);
var allowed = proposed.Sources
.Where(source => authorisation.CanUse(request.User, source))
.Distinct()
.ToArray();
return proposed with { Sources = allowed };
}
}
The simplified example illustrates a key rule: the model proposes; trusted code authorises.
Record the route, confidence, policy version and selected sources. Evaluate routing accuracy separately from retrieval quality. If the contract index was never searched, reranking its absent evidence cannot help.
5. Query decomposition handles multiple information needs
Consider:
Compare Riverside's current delay with similar projects and explain whether the contractor can be penalised.Useful subquestions are:
- What is Riverside's authoritative current delay?
- Which historical projects had comparable delay causes and scale?
- What actions were taken and what outcomes followed?
- Which current contract clauses govern damages?
- Do approved extensions or exceptions apply?
public sealed record RetrievalSubtask(
string Id,
string Question,
KnowledgeSource Source,
IReadOnlyCollection<string> DependsOn,
int MaximumCandidates);
Independent subtasks can run concurrently. Dependent subtasks must wait: finding “similar projects” may require Riverside's delay profile first.
Decomposition improves coverage and traceability. It also increases calls, latency and opportunities for the system to drift away from the original intent. Use a maximum subtask count, preserve exact entities and show how each subanswer contributes to the final result.
A simple question should stay simple.
6. Parent retrieval restores qualifications and exceptions
Small child chunks are precise search targets, but a nearby paragraph may change their meaning.
Matched child:
The contractor shall pay £10,000 per week of delay.Following paragraph:
This provision does not apply where an extension of time has been approved.Returning only the first passage could produce a dangerously incomplete answer.
Parent retrieval searches child chunks, then supplies the containing clause, section or bounded neighbourhood for understanding.
Search child C18 precisely
↓
Resolve parent section P4
↓
Load C18 + exception C19 + provenance
↓
Fit relevant section within evidence budget
Store ParentId, heading path and source offsets during chunking. At query time, expand only the strongest children and deduplicate shared parents.
This is one of the most practical advanced patterns. Consider it before introducing autonomous multi-step behaviour.
7. Contextual compression reduces distraction
Sometimes the right parent is long. Contextual compression selects or extracts passages relevant to the question before the final model sees them.
Broad retrieved section
↓
Question-aware extractor
↓
Relevant quotations + source offsets
↓
Final evidence package
Start with extractive compression: select original sentences or spans rather than rewriting them. It preserves evidence more faithfully.
Abstractive compression can summarise, but it may remove an exception, date, disagreement or numerical qualification. If used:
- keep the original chunk and source link;
- label compressed text as derived;
- preserve quoted spans for important claims;
- evaluate factual consistency and omission;
- never let the summary become the sole audit record.
public sealed record CompressedEvidence(
string DerivedSummary,
IReadOnlyList<SourceSpan> SupportingSpans,
string OriginalChunkId,
string CompressorVersion);
Compression improves attention and token cost only when it preserves the facts required to answer.
8. HyDE uses an unreal document as a search probe
HyDE means Hypothetical Document Embeddings. It was proposed for zero-shot dense retrieval when queries and relevant documents may use different language.
Question:
Why is the development slipping?Corpus terminology:
- programme variance;
- critical-path disruption;
- delayed material procurement;
- schedule overrun.
User question
↓
Hypothetical passage — may contain false detail
↓ embedding
Search vector
↓
Real indexed evidence
The hypothetical passage is never evidence. It must not be cited or included as a fact in the final answer.
public sealed record HydeProbe(
string OriginalQuestion,
string HypotheticalText,
ReadOnlyMemory<float> SearchVector,
string GeneratorVersion);
HyDE can improve vocabulary alignment, but a generated probe can also steer search toward an invented assumption. Compare it with ordinary query embeddings and hybrid search. Keep exact identifiers and server-side filters outside the hypothetical generation step.
9. Corrective RAG detects weak retrieval
Ordinary RAG can make an unsafe assumption:
Search returned five chunks, therefore the question is answerable.Corrective retrieval evaluates evidence quality before generation. A practical controller might classify the result:
- sufficient — direct, current and authoritative support exists;
- partial — useful evidence exists but a required fact is missing;
- irrelevant — the candidate set does not answer the question;
- conflicting — credible sources disagree;
- unauthorised/unavailable — required evidence cannot be accessed.
public sealed record RetrievalAssessment(
EvidenceQuality Quality,
IReadOnlyCollection<string> SupportedSubtasks,
IReadOnlyCollection<string> MissingSubtasks,
IReadOnlyCollection<string> Conflicts,
string RecommendedAction,
double Confidence);
Actions can include query rewrite, larger candidate set, alternate authorised source, parent expansion, user clarification or honest abstention.
The CRAG research architecture uses a retrieval evaluator and corrective actions when document quality is poor. A production ASP.NET Core implementation may borrow the principle without claiming to reproduce the paper exactly.
Retrieval failure should be visible. Fluent generation must not conceal it.
10. Correction needs strict stopping rules
A correction loop can become an expensive cycle:
weak evidence → rewrite → weak evidence → rewrite → ...
Bound it:
public sealed record RetrievalBudget(
int MaximumSearches,
int MaximumRewrites,
int MaximumExternalCalls,
TimeSpan MaximumElapsed,
int MaximumEvidenceTokens);
Stop when:
- required evidence is sufficient;
- a deterministic source says the fact does not exist;
- the authorised source set is exhausted;
- confidence does not improve;
- cost or time budget is reached;
- the user must clarify intent.
11. Self-RAG is a specific research architecture
The Self-RAG paper trains a model to adaptively retrieve, generate and critique using learned reflection tokens. It can decide whether retrieval is required and evaluate relevance and support during generation.
Prompting an ordinary model with “check your answer” is not automatically Self-RAG.
A business application can implement a simpler controller inspired by self-reflection:
Is external knowledge needed?
Did retrieved evidence cover every subquestion?
Is each important claim supported by an evidence ID?
Are sources current, permitted and non-conflicting?
Should the application search again, clarify or abstain?
Keep these judgements structured and independently testable. Models are imperfect judges of their own work. Whenever possible, verify deterministic properties in code:
- cited IDs exist in the evidence package;
- prohibited sources are absent;
- effective dates are current;
- all decomposed subtasks have coverage;
- numeric claims match structured results.
12. GraphRAG serves relationship-heavy questions
Vector search finds semantically related passages. Some questions depend on relationships distributed across a corpus:
Which subcontractors are connected to projects affected by the same supplier failure?
Supplier → delivery failure → subcontractor → project → delay → claim
Graph-based RAG extracts entities, relationships and claims, builds graph structures and combines them with source text. Microsoft's GraphRAG project supports local, global, DRIFT and basic query approaches over its generated indexes. Local search focuses on specific entities and nearby evidence; global search reasons over community reports across a dataset; DRIFT combines global context with more detailed follow-up exploration.
Use GraphRAG when questions genuinely require relationship traversal, multi-document themes or corpus-wide reasoning.
It adds substantial responsibilities:
- entity resolution and aliases;
- incorrect or missing extracted relationships;
- temporal and tenant boundaries;
- source-level provenance for graph claims;
- update and deletion propagation;
- indexing cost and operational complexity.
13. Do not build a graph when SQL already owns the relationship
BuildEstate Pro already has authoritative structured relationships:
Project → Contractor → Contract
Project → PlanningCondition
Project → Risk
Supplier → PurchaseOrder
Use SQL or APIs to traverse those relationships accurately. A knowledge graph may add value for entities and relationships hidden across unstructured reports and correspondence, but it should not duplicate a clean relational model without a reason.
A combined approach can be strongest:
- SQL identifies projects sharing supplier X.
- Document retrieval finds reports describing the failure.
- A graph projection connects aliases and unstructured claims.
- Citations return to original reports and authoritative records.
14. Agentic RAG performs conditional multi-step retrieval
An agentic controller can choose tools, inspect results and decide the next retrieval step.
Inspect question
↓
Read current project status
↓
Search delay reports
↓
Notice missing contract exception
↓
Retrieve signed contract section
↓
Find comparable completed projects
↓
Check evidence coverage
↓
Answer or abstain
This is useful for open-ended investigations where the next search genuinely depends on the previous result.
It also creates more latency, model cost, unpredictability, security exposure and debugging difficulty. An agent can make a plausible but wrong decision about which tool to call or when it has enough evidence.
Do not use an agent merely to run a fixed sequence. If the workflow is known, ordinary application orchestration is easier to test and operate.
15. Bound agent authority in ASP.NET Core
Define capabilities as narrow application tools with typed inputs and server-side authorisation.
public sealed record AgentRunPolicy(
IReadOnlySet<string> AllowedTools,
int MaximumSteps,
int MaximumSearchCalls,
TimeSpan Timeout,
decimal MaximumEstimatedCost,
bool RequireApprovalForExternalSearch);
Every tool call must:
- use the authenticated user's tenant and permissions;
- validate arguments independently of the model;
- enforce timeouts and result limits;
- return structured results and provenance;
- emit an audit trace;
- avoid exposing secrets or unrestricted queries.
An agent should have clear stopping conditions. “Continue until satisfied” is not an operational policy.
16. Combine structured and unstructured evidence
This remains one of the strongest advanced patterns.
Use structured sources for exact facts:
- current budget and variance;
- completion percentage;
- approved extension date;
- contractor identifier;
- open condition count.
- why delay occurred;
- what a contract permits;
- which risk was recorded;
- what action succeeded previously.
public sealed record AdvancedEvidencePackage(
IReadOnlyList<StructuredFact> Facts,
IReadOnlyList<DocumentEvidence> Passages,
IReadOnlyList<RelationshipEvidence> Relationships,
IReadOnlyList<EvidenceGap> Gaps,
DateTimeOffset AsOfUtc);
The model receives each type with a clear source label. It must not turn a historical document statement into current live state or present a database fact as a contractual interpretation.
17. Freshness is a retrieval constraint
Advanced orchestration is useless if it retrieves obsolete knowledge confidently.
Track:
- source publication and effective dates;
- current and superseded versions;
- ingestion completion time;
- index generation;
- deletion or withdrawal status;
- observation time for live facts.
Freshness is relative to the question, not simply “newer is always better.”
If the required source has not refreshed within its service-level expectation, mark the evidence gap. Do not hide stale state behind a current timestamp from the model call.
18. Cache by authority and security context
Caching can reduce search, embedding, graph and model costs. An unsafe cache can cross tenant or permission boundaries.
A retrieval cache key may need:
normalised question
+ tenant
+ user/group permission fingerprint
+ selected source set
+ project/business scope
+ index generation
+ source version/freshness marker
+ routing and retrieval policy versions
Do not cache generated answers longer than their evidence remains valid. Prefer caching reusable authorised retrieval results or embeddings where appropriate, while retaining versioned invalidation.
Never use only the question text as the key in a multi-tenant application.
19. Evaluate the controller, not only the answer
Advanced RAG adds decisions. Evaluate each one.
| Stage | Example measure |
|---|---|
| Routing | correct source selected; forbidden source absent |
| Decomposition | required subquestions covered; no invented task |
| Parent expansion | exception included; irrelevant parent text limited |
| Compression | required facts retained; no unsupported rewrite |
| HyDE | relevant recall improved without harmful drift |
| Corrective loop | weak evidence detected; useful correction chosen |
| Graph retrieval | relationships accurate and source-grounded |
| Agent | successful trajectory, bounded steps and valid tool calls |
| Final answer | claims entailed, complete and correctly cited |
Use representative questions, including cases that should remain simple and cases that should end in abstention.
20. Compare patterns through controlled experiments
For each observed failure:
- freeze an evaluation set;
- record baseline retrieval and answer results;
- enable one pattern behind a feature flag;
- compare quality, latency, cost and security outcomes;
- inspect regressions by question class;
- keep, revise or remove the pattern.
Capture the operational price:
- additional model and search calls;
- larger indexes or graph storage;
- background indexing time;
- cache invalidation complexity;
- support and incident investigation burden.
21. A staged ASP.NET Core orchestration design
Keep the controller explicit:
public sealed class AdvancedRagOrchestrator(
IRetrievalRouter router,
IQuestionDecomposer decomposer,
IEvidenceRetriever retriever,
IEvidenceAssessor assessor,
IEvidencePackager packager)
{
public async Task<EvidencePackage> RetrieveAsync(
RetrievalRequest request,
CancellationToken cancellationToken)
{
var route = await router.RouteAsync(request, cancellationToken);
var tasks = await decomposer.CreateTasksAsync(
request, route, cancellationToken);
var attempts = await retriever.RetrieveAsync(
request, route, tasks, cancellationToken);
var assessment = await assessor.AssessAsync(
request, tasks, attempts, cancellationToken);
return await packager.CreateAsync(
request, tasks, attempts, assessment, cancellationToken);
}
}
Production code also needs correction budgets, telemetry, retries and source adapters. The important point is separation: routing, decomposition, retrieval, assessment and packaging remain independently testable.
Do not bury the complete workflow in one enormous prompt. Application code should own security, budgets, state and deterministic validations.
22. BuildEstate Pro worked example
The user asks:
Which delayed projects have problems similar to Riverside, and what actions worked previously?
Step 1: route
The router selects the project database for current state, progress-report index for causes, project-history index for actions and outcomes, and no external web search.
Step 2: establish Riverside facts
SQL returns its current delay, stage, contractor and known coded risks. Hybrid document retrieval finds current reports describing steel delivery and approved design changes.
Step 3: decompose comparison criteria
The controller searches historical projects by comparable stage, delay scale and cause—not merely the word “Riverside.” Structured filtering narrows candidates before semantic retrieval compares reports.
Step 4: retrieve actions and outcomes
For each candidate project, the system retrieves decision logs and completion outcomes. Parent expansion preserves conditions and exceptions.
Step 5: assess evidence
The assessor rejects one project whose report is a draft and flags another whose outcome is missing. It does not let similarity substitute for authority.
Step 6: package a bounded comparison
The evidence package includes current Riverside facts, three permitted comparable projects, actions, observed outcomes, citations and explicit gaps.
Step 7: generate carefully
The model describes which historical actions correlated with improved outcomes. It labels recommendations as inferences rather than claiming the evidence proves causation.
This is advanced RAG because each additional step addresses a real requirement—not because an agent was allowed to search indefinitely.
23. Common mistakes
Adding every advanced pattern at once
Failures become impossible to attribute and operating cost rises before value is known.
Calling any answer review “Self-RAG”
Self-RAG is a specific trained research architecture. Use precise language for an application-level reflective controller.
Treating HyDE output as evidence
It is a hypothetical search probe and may contain invented facts.
Letting correction loop forever
Set search, rewrite, time, token and cost budgets.
Using a graph because relationships exist
SQL may already own those relationships more accurately.
Compressing away exceptions
Retain original spans and test omission of qualifications.
Giving an agent raw database or search access
Expose narrow authorised tools, not unrestricted infrastructure clients.
Measuring only final fluency
Evaluate routes, subqueries, evidence, trajectories and abstention.
24. A practical adoption order
- Prove standard hybrid RAG with permissions, citations and evaluation.
- Add SQL/API routing for exact current business facts.
- Add parent retrieval where small chunks omit scope or exceptions.
- Decompose only genuinely multi-part questions.
- Assess evidence sufficiency and support honest abstention.
- Add extractive compression for long relevant parents.
- Trial HyDE only for measured vocabulary mismatch.
- Add bounded corrective retries for known retrieval failures.
- Use graph retrieval only for relationship or corpus-wide questions.
- Introduce agentic control only when later steps must depend on earlier findings.
Final mental model
Advanced RAG is adaptive evidence engineering:
Question + trusted identity + business scope
↓
Route to the right authoritative sources
↓
Decompose only when the task requires it
↓
Retrieve precise children and sufficient parents
↓
Assess quality, freshness, permissions and conflicts
↓
Correct within explicit budgets
↓
Use graph or agentic exploration only for proven needs
↓
Package inspectable evidence or abstain
Routing solves the wrong-source problem. Decomposition covers compound questions. Parent retrieval restores context. Compression controls distraction. HyDE can bridge vocabulary mismatch. Corrective control detects weak evidence. GraphRAG supports relationship-heavy or corpus-wide questions. Bounded agentic retrieval handles genuinely conditional investigations.
None of these patterns removes the need for authoritative sources, permissions, provenance, evaluation and operational limits.
Continue through the AI Engineering learning journey, review RAG retrieval strategies, or revisit context engineering for trusted ASP.NET Core applications.
If this guide helped you, or you would like to discuss ASP.NET Core, Azure, SQL Server, Microsoft Foundry or RAG engineering, contact me at dotnetdeveloper20xx@hotmail.com.
