HazelJS LogoHazelJS
HazelJS Blog

RAG vs CAG vs KAG: Choosing the Right Context Layer in HazelJS

Author
HazelJS Team
10/15/2026
General
RAG vs CAG vs KAG: Choosing the Right Context Layer in HazelJS
← Back to Blog

A practical cross-comparison of RAG, Cache-Augmented Generation, Knowledge-Augmented Generation, and Memory — when each wins, how HazelJS ships them, and offline labs in Meridian Ops.

Retrieval-Augmented Generation (RAG) solved a real problem: LLMs alone don't know your documents. But not every agent question is “find the right passage.” Sometimes you need stable context reused across thousands of requests. Sometimes you need structured entities, facts, and relationships with provenance. That is why HazelJS treats context as four complementary layers — RAG, CAG, KAG, and Memory — and ships first-class packages for each.

This post is a practical cross-comparison: what each layer is for, when it wins or loses, how we built @hazeljs/​rag, @hazeljs/​cag, and @hazeljs/​kag, and real use cases you can run offline in hazeljs-meridian-ops.


Packages & Links

Runnable labs (no API keys): meridian-ops/examples — example:rag · example:cag · example:kag · example:context


One Picture

                 HazelJS Agent
                      │
                      ▼
              Context /​ Reasoning
                      │
        ┌─────────────┼─────────────┐
        │             │             │
        ▼             ▼             ▼
       RAG           CAG           KAG
        │             │             │
        └─────────────┼─────────────┘
                      │
                    Memory
                      │
                      ▼
                     LLM
LayerCore questionTypical answer shape
RAGWhat information should I retrieve for this query?Ranked passages + citations
CAGWhat context can I preload, reuse, and cache?Fingerprinted policy / schema blobs
KAGWhat entities, facts, and relationships do I know?Evidence path + provenance
MemoryWhat has this agent learned or experienced with this user?Preferences, session facts

They are complementary. CAG is not a RAG wrapper. KAG is not “GraphRAG renamed.” Memory is not a knowledge graph.


What Each Layer Is

RAG — Retrieval-Augmented Generation

Idea: At request time, embed the question, search a vector (and optionally keyword) index, optionally rerank, then stuff passages into the prompt.

Request → Embedding → Vector /​ hybrid search → Documents → LLM

HazelJS surface: @hazeljs/​rag — loaders, chunking, embeddings, vector stores, hybrid search, GraphRAG for document-derived graphs, RAGService / RAGPipeline. Meridian’s helpdesk agent uses the same mental model with an in-memory KB (no Qdrant required to learn the pattern).

Best when: answers live in a large, changing corpus and relevance depends on the query.

Lab: examples/​rag-helpdesk-agent → npm run example:rag

CAG — Cache-Augmented Generation

Idea: Relatively stable knowledge is prepared once, fingerprinted, cached (memory / Redis / provider prompt-cache hints), then reused — without embedding + search on every request.

Knowledge sources → Prepare → Context cache → Request → Cached context → LLM

HazelJS surface: @hazeljs/​cag — CagModule / CagService, sources, fingerprints, TTL / version invalidation, token budgets, optional compression, multi-tenant keys.

Best when: the same policies, schemas, catalogs, or tenant config are needed on almost every turn.

Lab: examples/​cag-support-agent → npm run example:cag

KAG — Knowledge-Augmented Generation

Idea: Domain knowledge as typed entities, relations, and time-scoped facts — with provenance, confidence, contradictions, and traversable evidence — then optional LLM phrasing of that evidence.

Data → Extract /​ ingest → Knowledge graph → Traverse /​ plan → Evidence → LLM

HazelJS surface: @hazeljs/​kag — KnowledgeGraph / KagService, in-memory tenant store, entity resolution, temporal facts, heuristic (industry-pluggable) query planner, ask({ explain: true }), GraphRAG import adapters (not a GraphRAG fork).

Best when: the question is multi-hop, causal, or “why did X change?” over structured domain state — not “which PDF page mentions X?”

Lab: examples/​kag-commerce-agent → npm run example:kag

Memory — continuity (not knowledge)

Memory answers “what do we already know about this user / this run?” It is orthogonal to RAG/CAG/KAG. Promote a preference into KAG only when it becomes validated domain truth.


Cross Comparison

Capability matrix

DimensionRAGCAGKAGMemory
Unit of contextPassages / chunksAssembled stable text blocksEntities, relations, factsEpisodes / preferences
Hot pathEmbed + search every requestCache hit → assembleGraph traverse / planLookup by user/session
Data freshnessGreat for frequently updated docsGreat for slowly changing knowledgeGreat for operational / transactional truthGreat for conversational state
Latency profileSearch + embed costNear-instant on hitTraversal (cheap at small/medium scale)Near-instant
ExplainabilityCitations to passagesSource id + version / fingerprintEvidence path + provenance“You said X earlier”
Multi-tenancyNamespaces / metadata filtersCache keys include tenantIdStore partitioned by tenantIdScoped by user / agent
Failure modeWrong or missing passageStale cache if invalidation is wrongWeak graph / low confidenceStale or over-trusted preference
Typical cost driverEmbeddings + vector DBPrompt tokens (mitigated by cache)Ingestion + occasional LLM phrasingStorage + retrieval of history
Update cadenceContinuous ingestVersion bump / TTL / invalidateEvent-driven graph writesPer turn / session
HazelJS package@hazeljs/​rag@hazeljs/​cag@hazeljs/​kag@hazeljs/​memory

Same question, four wrong tools

User asksIf you only use…What goes wrong
“What’s our return policy?”RAGYou pay embed+search every time for text that never changes per tenant version.
“How do I rotate staging API keys?”CAGYou either miss the right runbook or stuff the entire handbook into every prompt.
“Why was settlement €1,420 short?”RAGPassages mention refunds; they don’t reconstruct merchant→order→payment→refund→settlement with sources.
“Remember I exclude VAT.”KAGYou pollute the domain graph with a personal preference that isn’t operational truth.
Mix of policy + ledger + preferenceAny single layerIncomplete answer — needs @hazeljs/​context.

Pros and cons (short)

WinsLoses when
RAGLarge unstructured corpora; query-dependent relevance; mature toolingMulti-hop structured “why”; always-on policy paragraphs
CAGLatency/cost for stable tenant context; fingerprints; priority budgetsQuery-specific doc lookup; forgotten invalidation
KAGCausal paths, contradictions, provenance, industry profilesFree-form prose; “drop PDFs and go”
MemoryContinuity and personalizationTreating preferences as ledger truth

How HazelJS Built These Packages

We did not invent three parallel frameworks. We extended the Agent OS context substrate with clear boundaries and heavy reuse.

  1. Composition over duplication — CAG reuses RAG loaders for files/URLs when present; it does not reimplement vector search. KAG can import GraphRAG graphs; it does not own community detection or embeddings.
  2. Native HazelJS shape — @HazelModule, forRoot / forRootAsync, @Service(), typed XxxError + codes, Jest, peer @hazeljs/​core.
  3. Multi-tenant by default where it matters — CAG cache keys and KAG store scopes always include tenantId.
  4. Agent OS ports, not hard couples — AgentRuntimeConfig takes duck-typed ragService / cagService / kagService / contextService. DNA declares intent; apps inject services.
  5. Toward a unified planner — @hazeljs/​context calls the same contributor shape (contribute) so auto strategy can pick CAG / RAG / KAG / Memory per query.

Real-World Use Cases

Each scenario below maps to a Meridian lab (or live Meridian route). Run the lab after reading the section.

1) Help center / FAQ over a large handbook → RAG

Industries: SaaS support, internal IT, compliance Q&A, product docs.

Problem: Hundreds of docs, changelogs, and runbooks. The right answer depends on the question wording and may live in an obscure page updated last week.

/​/​ Pattern (production: @hazeljs/​rag ingest + vector store)
const docs = await rag.search('How do I rotate API keys on staging?', { topK: 3 });

Why not CAG? You cannot sensibly preload the entire doc set into every prompt.
Why not KAG? The knowledge is narrative procedure text, not a fact graph (unless you later extract entities).

Lab / live: Offline rag-helpdesk-agent mirrors Meridian’s helpdesk KB. In the running app: POST /​api/​helpdesk/​chat.

npm run example:rag
# ask: "What is the refund SLA?" → hits refund-sla doc, not the whole policy blob

2) Multi-merchant support: always-on return policy → CAG

Industries: Marketplaces, payment platforms, white-label SaaS, any multi-tenant agent.

Problem: Every merchant chat asks about returns, hours, and fee schedules. Running RAG every time burns embeddings and latency for text that rarely changes — and tenant A must never see tenant B’s policy.

cag.register(
  {
    id: 'return-policy',
    priority: 100,
    compressible: false,
    version: '2026-10',
    source: { type: 'text', content: loadMerchantPolicy(tenantId) },
  },
  'support'
);

const { context, hit } = await cag.getContext({
  namespace: 'support',
  tenantId: 'merchant-123',
});

Why not RAG? The answer is not “find a similar paragraph” — it is “always include this policy.”
Why not KAG? There is no multi-hop entity reasoning; it is static prose.

Lab: cag-support-agent — cold miss → warm hit, tenant isolation, version bump invalidates cache.

npm run example:cag
# firstHit: false, secondHit: true, otherTenantHit: false, afterVersionBumpHit: false

Other CAG fits: OpenAPI / tool schemas stuck in every tool-calling turn; compliance disclaimers; product catalog summaries that change weekly under a version key.


3) Ops / finance: “Why was settlement short?” → KAG

Industries: Commerce / payments, logistics (shipment→exception→claim), healthcare ops (patient→encounter→claim), ITSM (incident→change→outage).

Problem: The answer is a path through merchant → orders → payments → refunds → fees → settlement, with source systems and confidence — not a single handbook paragraph.

const knowledge = new KnowledgeGraph({
  tenantId: 'merchant-123',
  industry: COMMERCE_INDUSTRY_PROFILE, /​/​ opt-in vocabulary
});

await knowledge.relate({ from: 'payment-1', to: 'refund-1', type: 'HAS_REFUND' });
await knowledge.fact({
  subject: 'refund-1',
  predicate: 'amount',
  object: 1420,
  confidence: 0.98,
  source: { type: 'database', id: 'refund-456', authority: 90 },
});

const result = await knowledge.ask(question, { explain: true });
/​/​ result.evidence + result.sources — auditable, not hidden CoT

Why not RAG alone? Passages might mention refunds but won’t reliably reconstruct the causal path with provenance.
Why not CAG alone? The graph changes with every day’s ledger; caching a frozen narrative goes stale immediately.

Lab: kag-commerce-agent — builds the graph, asks the settlement question, prints evidence + contradiction handling.

npm run example:kag
# explanation includes merchant → order → payment → refund → settlement + sources

4) Hybrid desk: policy + ledger + handbook + preference → @hazeljs/context

Industries: Any production support desk that already has RAG and needs policy + ops truth.

Problem: “Why was settlement impacted by a refund, given our refund policy and my VAT preference?”

Slice of the questionLayer
Stable refund policyCAG
Relational “why” on the ledgerKAG
Optional handbook passageRAG
“exclude VAT” preferenceMemory
const context = new ContextService({
  strategy: 'auto',
  sources: ['cache', 'rag', 'knowledge', 'memory'],
  cag,
  kag,
  rag,
  memory,
});

const assembled = await context.assemble({
  query,
  tenantId: 'merchant-123',
  userId: 'ops-1',
});
/​/​ assembled.plan.rationale explains which layers fired

Lab: context-auto-agent — auto-plans all four contributors and prints labeled assembly.

npm run example:context
# plan.sources: cag, rag, kag, memory — with per-layer rationale

5) Industry cheat sheet

DomainPrefer RAGPrefer CAGPrefer KAG
E‑commerce / paymentsHelp center, shipping FAQsMerchant return/fee policySettlement, chargeback, refund causality
SaaS / developer platformsAPI docs, changelogsPer-tenant feature flags / schemas in promptEntitlement → usage → invoice disputes
Healthcare opsClinical guidelines PDFsFacility policy snippetsEncounter → claim → denial paths
LogisticsCarrier manualsLane / SLA templatesShipment → exception → claim chains
Internal ITRunbooks, wikiOrg security policy always-onAsset → ticket → change → outage

When two columns apply in one utterance, reach for @hazeljs/​context.

6) Quick decision matrix

If the user asks…PreferLab
“What’s in the docs / handbook about X?”RAGexample:rag
“What is our always-on policy / schema / catalog?”CAGexample:cag
“Why did entity A’s metric change given related entities?”KAGexample:kag
“Remember that I prefer…”Memory(wired inside example:context)
A mix of the above@hazeljs/​context autoexample:context

Common Mistakes

  1. Using RAG for static policies — you pay retrieval forever for text that should be CAG.
  2. Using CAG for the whole knowledge base — prompts explode; retrieval exists for a reason.
  3. Treating GraphRAG as KAG — GraphRAG is document-extraction RAG; KAG is operational knowledge with facts, time, and contradictions.
  4. Auto-merging uncertain entities — HazelJS KAG keeps candidates below threshold; don’t turn that off casually.
  5. Skipping tenant in cache/graph keys — never acceptable for multi-merchant agents.
  6. Exposing raw model chain-of-thought as “explanation” — KAG explanations are evidence (entities, relations, sources).
  7. Putting user preferences only in Memory forever — promote to KAG when they become validated domain rules; keep Memory for soft personalization.

Where This Is Going

HazelJS is moving from “we have RAG, and also CAG, and also KAG” to a single context substrate:

Query → ContextPlanner → CAG | RAG | KAG | Memory → Assembly → LLM

@hazeljs/​context is the first cut of that planner. Each package remains independently useful for teams that only need one layer. Meridian Ops is the teaching app: DNA + Skillgate + HITL in the live server, and offline context labs under examples/​.


Try It

# from hazeljs-meridian-ops/​
npm run example:install
npm run example:rag      # handbook retrieval
npm run example:cag      # cached policy + tenant isolation
npm run example:kag      # settlement evidence path
npm run example:context  # auto planner over all four

Docs: RAG · CAG · KAG · Context


RAG optimizes retrieval. CAG optimizes reuse. KAG optimizes structured knowledge. Memory optimizes continuity. Together they are the context engine of HazelJS Agent OS.