AI RAG July 26, 2026

Types of RAG Explained — With Architecture & Implementation for Each Pattern

July 26, 2026 · By Vibhor Sharma · Updated
Abstract illustration of retrieval-augmented generation knowledge flow

Retrieval-Augmented Generation (RAG) is not one architecture. It is a family of patterns for grounding model answers in your data.

This guide walks through the five patterns you will actually meet in enterprise designs — Naive, Advanced, Modular, Agentic, and GraphRAG — using one shared business scenario, a solution architecture, and a sample implementation sketch for each.

If you only remember one rule: complexity should follow failure modes, not LinkedIn trends.

Layered illustration of RAG patterns from simple retrieval to agent loops
Same goal — grounded answers. Different control planes for retrieval, routing, and reasoning.

Shared scenario (used for every pattern)

Company: Northwind Mobility, a global automotive OEM.

Use case: an internal assistant for dealer support and warranty analysts.

Questions look like:

Knowledge sources:

We will solve the same question across patterns:

Q: “Can we approve a goodwill battery replacement for VIN WNW123 in Bavaria, and who must sign off?”

1. Naive RAG

Linear pipeline: chunk → embed → top‑k similarity → stuff into prompt → generate.

When it fits

POC on a clean corpus (e.g. one warranty PDF library). Breaks on multi-hop questions, ACL, and “similar but wrong” chunks.

Solution architecture

┌──────────────┐    ┌─────────────┐    ┌──────────────┐
│ Ingestion    │───▶│ Vector DB   │◀───│ Query Embed  │
│ (chunk+embed)│    │ (policies)  │    │              │
└──────────────┘    └──────┬──────┘    └──────┬───────┘
                           │ top-k            │
                           ▼                  │
                    ┌─────────────┐           │
                    │ Prompt+LLM  │◀──────────┘
                    └──────┬──────┘
                           ▼
                      Answer text

Components: object storage → chunker → embedding model → vector index (e.g. pgvector / OpenSearch kNN) → chat LLM. No rerank, no hybrid search, no tools.

Example behaviour on our question

Retrieves chunks about “battery goodwill” and “Germany warranty,” but may miss Bavaria sign-off matrix and live claim status. Risk: confident wrong answer.

Sample implementation

def naive_rag(question: str, k: int = 5) -> str:
    q_vec = embed(question)
    chunks = vector_db.similarity_search(q_vec, k=k)
    context = "\n\n".join(c.text for c in chunks)
    prompt = f"""Answer using ONLY the context. If missing, say you don't know.
Context:
{context}

Question: {question}
Answer:"""
    return llm.generate(prompt)

Ingest sketch:

for doc in load_pdfs("s3://nw-warranty/"):
    for chunk in split(doc, size=800, overlap=120):
        vector_db.upsert(id=chunk.id, vector=embed(chunk.text),
                         metadata={"source": doc.path, "region": doc.region})

2. Advanced RAG

Same backbone, but quality controls at every stage: better chunking, query rewrite, hybrid retrieval (BM25 + vectors), reranking, compression, citations.

When it fits

Default production pattern for knowledge Q&A. This is where most enterprise assistants should live before agents or graphs.

Solution architecture

User Q
  │
  ▼
┌─────────────────┐
│ Query transform │  (rewrite / expand / HyDE optional)
└────────┬────────┘
         ▼
┌─────────────────┐     ┌──────────────┐
│ Hybrid retrieve │────▶│ Reranker     │
│ BM25 + vectors  │     │ (cross-enc.) │
└─────────────────┘     └──────┬───────┘
                               ▼
                        ┌──────────────┐
                        │ Compress +   │
                        │ cite chunks  │
                        └──────┬───────┘
                               ▼
                        ┌──────────────┐
                        │ LLM answer   │
                        │ + citations  │
                        └──────────────┘

Enterprise add-ons: metadata filters (region=DE), document ACL from IdP, evaluation set (groundedness / citation precision).

Example behaviour

Query rewritten to “Germany MY2024 battery goodwill approval authority Bavaria.” Hybrid search finds the regional exception table; reranker promotes the sign-off matrix chunk; answer cites policy §4.2.

Sample implementation

def advanced_rag(question: str, user_region: str) -> dict:
    rewritten = llm.generate(
        f"Rewrite for retrieval. Keep entities. Question: {question}"
    )
    dense = vector_db.similarity_search(embed(rewritten), k=20,
                                        filter={"region": ["DE", "GLOBAL"]})
    sparse = bm25_index.search(rewritten, k=20)
    candidates = rrf_fuse(dense, sparse)  # reciprocal rank fusion
    ranked = reranker.rank(question, candidates)[:6]
    context = format_with_citations(ranked)
    answer = llm.generate(f"""Use context. Cite sources like [1],[2].
If policy conflicts, state the conflict.
Context:
{context}

Question: {question}""")
    return {"answer": answer, "sources": ranked}

3. Modular RAG

Composable pipelines with a router. Different question types hit different indexes/tools. Feels like an integration flow — because it is.

When it fits

Multiple domains (policy vs CRM vs product), strict permissions, or different SLAs per corpus.

Solution architecture

                    ┌──────────────────┐
                    │ Intent router    │
                    │ (LLM or rules)   │
                    └────────┬─────────┘
           ┌─────────────────┼─────────────────┐
           ▼                 ▼                 ▼
    ┌────────────┐   ┌────────────┐    ┌────────────┐
    │ Policy RAG │   │ CRM RAG    │    │ Live API   │
    │ (Advanced) │   │ + ACL      │    │ (claims)   │
    └─────┬──────┘   └─────┬──────┘    └─────┬──────┘
          └────────────────┼─────────────────┘
                           ▼
                    ┌────────────┐
                    │ Synthesizer│──▶ Answer
                    └────────────┘

Platform view: API gateway / MuleSoft exposes GET /claims/{vin}; RAG orchestrator is just another consumer with scoped credentials. Identity (OIDC) propagates into metadata filters.

Example behaviour

Router emits: policy + claims_api + org_matrix. Policy module returns goodwill rules; claims API returns open claim state for VIN WNW123; synthesizer merges “eligible / not eligible + approver role.”

Sample implementation

def modular_rag(question: str, user: User) -> str:
    plan = router.classify(question)
    # plan.routes eg: ["policy", "claims", "org"]
    bundles = []
    if "policy" in plan.routes:
        bundles.append(advanced_rag(question, user.region))
    if "claims" in plan.routes:
        vin = extract_vin(question)
        bundles.append({"claims": claims_api.get_status(vin, token=user.token)})
    if "org" in plan.routes:
        bundles.append(org_index.search("battery goodwill approver Bavaria"))
    return synthesizer.merge(question, bundles, cite=True)
# Router can be rules-first for production predictability:
RULES = [
  (r"VIN|claim|status", ["claims", "policy"]),
  (r"who (approves|signs)|sign-off", ["org", "policy"]),
  (r".*", ["policy"]),
]

4. Agentic RAG

An agent decides when and how to retrieve, can loop, call tools, and stop when evidence is enough. Retrieve is a tool — not a single forced step.

When it fits

Multi-step investigate → gather → decide workflows. Higher cost/latency; needs guardrails.

Solution architecture

┌─────────────────────────────────────────┐
│ Agent orchestrator (ReAct / plan-exec)  │
│  memory · policy guardrails · budget    │
└───────────────┬─────────────────────────┘
                │ tool calls
     ┌──────────┼──────────┬────────────┐
     ▼          ▼          ▼            ▼
 search_policy claims_api org_lookup  ticket_search
     │          │          │            │
     └──────────┴─────┬────┴────────────┘
                      ▼
               final answer + audit trail

Controls: max steps, allow-listed tools, human escalate if confidence low, full tool-call audit log.

Example behaviour

  1. Agent extracts VIN + region
  2. Calls claims_api
  3. Searches policy with rewritten query
  4. Looks up approver role for Bavaria
  5. Stops with a structured recommendation + citations + next human action

Sample implementation

TOOLS = {
  "search_policy": lambda q: advanced_rag(q, "DE")["sources"],
  "get_claim": lambda vin: claims_api.get_status(vin),
  "get_approver": lambda region, topic: org_api.approver(region, topic),
}

def agentic_rag(question: str, user: User) -> str:
    state = {"question": question, "notes": [], "steps": 0}
    while state["steps"] < 6:
        decision = llm.plan_next_action(state, tools=TOOLS.keys())
        if decision.action == "answer":
            return llm.final_answer(state, decision.draft)
        result = TOOLS[decision.action](**decision.args)
        state["notes"].append({"tool": decision.action, "result": result})
        state["steps"] += 1
    return escalate_to_human(state)
# Tool contract example (OpenAPI-ish)
# POST /tools/get_claim
# body: { "vin": "WNW123" }
# auth: user-delegated OAuth (no god-mode service account)

5. GraphRAG

Build a knowledge graph (entities + relationships + communities). Retrieve by neighbourhood / community summaries — not only vector similarity. Strong when the answer is in the links.

When it fits

“Who owns what,” dependency chains, org/product hierarchies, multi-document relationship questions. Costly to build/maintain — use when Advanced RAG keeps missing relationships.

Solution architecture

Documents ──▶ Entity/Rel extract ──▶ Graph DB (Neo4j etc.)
                      │                      │
                      │                      ├─ local search (entity neighbourhood)
                      │                      └─ global search (community summaries)
                      ▼
              Vector index (optional hybrid)
                      │
                      ▼
                 Graph+text context ──▶ LLM answer

Inspired by community-summary approaches (e.g. Microsoft GraphRAG style pipelines): extract → graph → Leiden/community summaries → local/global retrieval modes.

Example behaviour

Graph paths:

(VIN WNW123)-[:IN_REGION]->(Bavaria)-[:IN_COUNTRY]->(Germany)
(BatteryGoodwill)-[:REQUIRES_APPROVAL]->(Role: Regional Warranty Lead)
(Regional Warranty Lead)-[:FILLED_BY]->(Persona / queue)

Answer names the role and why — even if those facts never co-occur in one PDF chunk.

Sample implementation

def build_graph(docs):
    for doc in docs:
        ents, rels = llm.extract_entities_relations(doc.text)
        graph.upsert_entities(ents)
        graph.upsert_relations(rels)
    graph.run_community_detection()
    graph.materialize_community_summaries()

def graph_rag(question: str) -> str:
    mode = "local" if looks_entity_specific(question) else "global"
    if mode == "local":
        seeds = entity_linker.link(question)
        subgraph = graph.expand(seeds, hops=2)
        context = render_subgraph(subgraph)
    else:
        communities = graph.top_communities_for(question, k=5)
        context = "\n".join(c.summary for c in communities)
    return llm.generate(f"Answer from graph context:\n{context}\n\nQ:{question}")
// Cypher-ish local retrieval
MATCH (v:VIN {id:$vin})-[:IN_REGION]->(r:Region)-[:IN_COUNTRY]->(c:Country)
MATCH (p:PolicyTopic {name:'BatteryGoodwill'})-[:REQUIRES_APPROVAL]->(role:Role)
WHERE c.code = 'DE'
RETURN r.name, role.name, p.clauseRef

Side-by-side: same question, different patterns

Pattern What you get for the VIN goodwill question Main risk
Naive Generic warranty blurb Misses sign-off + live claim state
Advanced Cited policy answer for DE/MY2024 Still no live claim / org path unless in docs
Modular Policy + claims API + org matrix merged Router mistakes / integration auth
Agentic Multi-step investigation with audit trail Latency, cost, runaway loops
GraphRAG Relationship-native “who approves” Graph build & drift over time

Reference enterprise architecture (production)

┌──────────── users / IdP (SSO) ────────────┐
│  Assistant UI  →  Orchestration API       │
└─────────────┬─────────────────────────────┘
              │
     ┌────────┴────────┐
     │ Policy engine   │  (PII redaction, tool allow-list)
     └────────┬────────┘
              │
 ┌────────────┼────────────┬──────────────┐
 ▼            ▼            ▼              ▼
Vector/BM25  Graph DB   Systems APIs   Eval/Obs
indexes      (optional) (CRM/Claims)   (traces,
                                        groundedness)

Non-negotiables in enterprise RAG:

  1. User-delegated auth to tools (no shared god account)
  2. Document ACLs enforced at retrieval time
  3. Citations + refusal when evidence is weak
  4. Evaluation set before you celebrate a demo
  5. Ownership for ingestion freshness (stale index = silent failure)

This is why RAG is an API and integration problem as much as an LLM problem.

Adoption path that works

  1. Naive — prove value on one trusted corpus (1–2 weeks)
  2. Advanced — hybrid + rerank + citations + eval harness
  3. Modular — split domains / add live APIs behind the router
  4. Agentic — only when multi-step tool use is the real job
  5. GraphRAG — when relationship questions keep beating vector search

Final take

Don’t ask “Which RAG is best?” Ask “Which failure is killing trust today?”

Start simple. Measure groundedness. Graduate on purpose.

That is how RAG becomes a durable capability — not a weekend demo.

← Back to articles