The Index Agent
Data comes in several shapes, and each shape wants a different retrieval strategy; matching the wrong one to your data is the most common reason an Index Agent fails silently in production.
The Index Agent applies that workflow idea to outside knowledge with a developer-defined pipeline. It embeds and indexes a corpus ahead of time, then retrieves matching passages and generates an answer from a bounded context bundle. The build follows that path for unstructured prose before wrapping retrieval as a tool that a surrounding ReAct loop can call. The other data shapes get pointers to where they go deeper.
Deep · HistoryTrace RAG from joint training to retrieval?
Where RAG came from: one system, trained end to end
The version of RAG everyone runs today drops most of what the original design did, and knowing that reframes the retriever you are about to wire in.
When Lewis and colleagues named retrieval-augmented generation in 2020, it was not a model with a search box bolted on. The retriever and the generator were trained together on the task they had to perform. Read the figure from left to right before looking at the arrow across the top.
The design lives in the arrow labelled "End-to-End Backprop through q and pθ". One loss updated both halves at once. The query encoder learned which passages the generator could use, and the generator learned to lean on retrieved evidence over its own memory.
The retriever began as part of the model, shaped by the task it had to perform, well before anyone described it as a search tool placed in front of one.
Why today's RAG drops the joint training
Almost nobody trains RAG that way now for two practical reasons. You cannot backpropagate into a frontier model you reach through an API, and even self-hosted end-to-end retrieval training is expensive and easy to destabilize.
Practice settled on a simpler assembly. You take a model that already exists, freeze it, and put a retriever in front of it so the prompt arrives pre-loaded with evidence and nothing is trained at all. The parts were built separately and bolted together, and over time "RAG" came to mean that bolt-on rather than the jointly optimized system the paper described.
The retrieve-then-generate pipeline you build
With that ceiling in mind, here is the whole assembly. A retriever runs in front of the frozen model across two separate timelines. One timeline builds the index ahead of time so the other can serve a live request against it. The figure below traces both.
Offline: build the index once by embedding every passage and storing it for fast lookup.
Live: embed the question, retrieve the top-K passages, and pass them to the model with the question.
The rest of this page builds the live path one stage at a time.
Applied · ScopeChoose bundles, boundaries, and data shapes?
Naming the context bundle before you pick a store
Before picking a retrieval primitive, you should first define a bundle. The bundle is the complete and bounded set of context that you intend your pipeline to pass around.
- For a simple single-turn question-answering system, the bundle can stay small: the user question, the few chunks retrieved to answer it, and the answer itself.
- For an autonomous agent, the bundle is the working memory it carries across many turns. That memory stores the agent's constraints, prior decisions, partial results, tool surfaces, and operating rules.
- For an arbitrary Index Agent, the bundle returned by the agent may only house the retrieved context chunks along with their chunk sources, relevance scores, and possibly a summary. A separate internal bundle may be the flat live-request-processing pipeline from above, or a ReAct-style loop that iterates, judges retrieval relevance, and retries until it has accumulated enough context.
The bundle principle is a planning discipline: define the bundle before you pick the database. Picking a vector store first and hoping it covers everything is the origin of most "worked in demo but failed in production" stories. The four-shape taxonomy below checks whether your candidate primitive can deliver the bundle for your task.
Where MCP fits in retrieval systems
MCP gives a retrieval system one boundary for discovering and calling external context sources. The agent still needs a runtime that decides when to retrieve, validates the result, and composes it with the rest of the active task state. Other boundaries can carry other parts of the same system: skills package reusable capability instructions, A2A can route work to remote specialists, and UI protocols can stream the generated state back to an application.
The figure below separates those boundaries. Read it left to right to follow MCP context ingress and A2A task delivery. Then read it bottom to top to follow skill brokerage, runtime execution, and generated UX. Choose the boundary that matches the bundle and the system state it must carry.
Matching a retrieval primitive to the shape of your data
Each data shape calls for its own retrieval primitive. Pick the wrong lane and retrieval keeps returning results that look fine while quietly missing what the query wanted, with no error to warn you. The table below tells you which primitive each shape calls for.
| Shape | Examples | Right primitive |
|---|---|---|
| Unstructured prose | Docs, articles, code comments, transcripts | Dense vector + cross-encoder rerank |
| Hierarchical docs | Legal contracts, technical manuals, nested specs | Tree index with parent pointers |
| Structured / governed tables | Customer records, financial ledgers, HR tables | Semantic layer over the source of truth |
| Relational / graph | Org charts, code dependencies, knowledge graphs | Graph traversal (Cypher, GraphQL, custom) |
The unstructured-prose example carries a corpus through retrieval and generation to a grounded answer.
Every request walks the same four steps:
- Embed the query into a vector.
- Search the passage index for the top-K nearest passages.
- Concatenate those passages onto the prompt.
- Generate an answer grounded in them.
Index agents that manage other primitives largely take the same shape while varying the search/embed/verification logic, so don't feel intimidated to experiment with shapes that better fit your data.
The embedding, the primitive everything else is built on
Each unstructured-prose Index Agent starts from the same primitive. An embedding is a learned numerical address for a piece of text, a fixed-length vector placed so that semantically similar texts land near each other in vector space. Two practical consequences follow:
Both rest on a single primitive, the embedding model. This course routes embedding
calls through helpers.embed, which proxies to the hosted NVIDIA embedding endpoint
so everything runs in the browser without a lab path or local server.
Applied · ContractNeed the embedding request contract?
The embeddings endpoint takes a JSON request with three fields and returns one array of vectors:
inputis the batch of texts to embed, typedstring[].modelnames the embedding model, typedstring.input_typeis either"query"or"passage".- The response carries a
dataarray whose entries each hold anembeddingofnumber[].
The NVIDIA embed models assign the same text a different vector depending on the
input_type you pass. The training objective pulls a question
toward the passages that answer it rather than toward texts that merely
repeat its words, so a cosine score between two correctly typed inputs
tracks relevance well. Embedding a query with the
"passage" type or the reverse breaks the score function
silently and produces lower recall with no error message.
A whole retriever in thirty lines of top-K cosine
A "vector database" dresses up a plain job the Index Agent already does. It stores each passage beside its embedding and returns the top-K closest passages to any query embedding by cosine similarity. In the browser that fits in thirty lines of JavaScript.
The cell below builds an Index Agent over a handful of documents and queries it. Edit the corpus and the query, then watch which passages bubble to the top and why.
A vector index is a cache of an embedding model's outputs. Production systems have to defend against a few specific failures:
- Swap the embedding model and every cached vector becomes meaningless until you re-embed every passage.
- The provider silently upgrades the model, and scores drift with no error raised.
- Two services share an index but pin different model ids; the index returns nonsense to one of them.
A reliable index pins the embedding model id alongside each cached vector
and refuses to mix versions. The canonical pin for this course is
nvidia/llama-nemotron-embed-1b-v2, served through the
course's hosted proxy at build.nvidia.com.
Applied · ChunksRetrieve small chunks with parent context?
Searching small chunks but returning the parent document
A bare top-K Index Agent has a recall-precision trade-off no embedding model solves. You must choose between short chunks and long documents:
- Short chunks embed precisely (the vector represents a focused idea) but lack context (one sentence is rarely enough to answer with).
- Long documents have context (every fact lands in its setting) but embed fuzzily (the vector is the average of many ideas).
The production pattern indexes at two levels. You embed the small chunks so retrieval stays precise, and when one matches you return its parent document so the model still sees the full context around it.
The exercise below builds this with three parent docs, each split into short sentence-chunks, and a query that returns the matching parent.
Applied · AgentLet the model decide when to retrieve?
Wrapping the index as a tool the model decides to call
A retrieval index on its own only answers when something queries it. It becomes an Index Agent once you wrap it as a tool the model can choose to call, letting the model decide when retrieval is worth running. The cell below does it in five steps:
- A corpus is embedded once and held in an in-memory index.
- A
retrieve(question, k)tool is declared with a JSON schema. - The agent receives the user's question. It chooses whether to call the tool.
- If yes, cosine retrieval runs over the index; the top-K passages are appended as a tool message.
- A second LLM call writes the final answer grounded in the retrieved passages.
The "retriever-as-tool" shape you just wired scales straight to production. Swapping the in-memory cosine function for a server-side FAISS+BM25+rerank pipeline changes only the executor; the tool schema, the agent loop, and the final answer step all stay identical.
Applied · ShapesCompare the other index shapes?
How the other three shapes are built
You just built the unstructured-prose lane from corpus to answer. The other three are named here so you can recognise them in the wild and reach for the right primitive. Each one has a well-worn production pattern, sketched below.
- Hierarchical docs. A chunker that preserves the heading hierarchy, plus atomic table extraction, parent pointers, and a dual index for structural and semantic search. You index the small child chunks for recall and fetch the enclosing parent on a hit, so the model reads the matched clause together with the section it belongs to.
- Page-image retrieval for figures and charts. A dual-vector setup that embeds the rendered page image alongside its text, so a query can also pull a figure or a slide when the answer lives there.
- Structured / governed tables. Not built in this course. The standard production pattern is a semantic layer sitting between the agent and the row-level data, exposing only the curated metrics the bundle requires.
- Relational / graph data. The agent calls a graph-traversal tool (Cypher, GraphQL, or custom) in place of a vector store. The bundle it gets back is a sub-graph whose explicit edges carry into the prompt, so the relationships between entities reach the model intact.
Deep · GraphRAGExplore corpus-wide retrieval with GraphRAG?
When top-K is the wrong tool: GraphRAG and global questions
Every retriever on this page answers a local question whose answer sits in a handful of passages that Top-K similarity can find for the model to read, the way asking what the contract says about termination or which paper introduced HyDE does. A whole different class of question has no answer in any single passage at all. Ask what the main themes are across a thousand documents and you find that the answer is too diffuse to live in any one passage and emerges only from the corpus taken as a whole.
Top-K hands back only its three best matches, so the model summarizes those three chunks while staying completely blind to the other nine hundred and ninety-seven passages in the corpus. GraphRAG (Edge et al. 2024) changes the shape of that problem instead of raising K. It spends an LLM up front at indexing time to:
- read the corpus and extract entities and the relationships between them into a knowledge graph;
- detect the communities in that graph, the clusters of densely connected entities;
- summarize each community on its own.
A global question is then answered at query time, by summarizing across the relevant community summaries and reducing those partial answers into one. The work is a map-reduce over structure rather than a lookup over similarity.
The cell below makes the difference concrete on a small corpus, and it runs the real pipeline rather than playing back a script. It asks one global question two ways: plain top-K retrieval, and GraphRAG's map-reduce over named communities. Watch top-K answer from whichever chunks happen to match the question's words while the community pass recovers the corpus-wide theme. Edit the corpus, the communities, or the question and run it again.
A frozen model with a top-K retriever in front answers local questions well and global ones not at all. Restructuring the corpus into summarized communities buys the global answer, paid for by an expensive indexing pass you run once.
Before you continue
- Cosine in Part 4 scores any two vectors the same way regardless of which is the
query, yet the NVIDIA embed model used here takes
input_typeto distinguish query from passage. What does that asymmetry buy you that pure cosine could not? - The index build embeds every corpus passage once, while the live path embeds each new question. Which changes require a full re-index, and which require only one new query embedding?
- Top-K always returns K passages, even when every score is weak. What signal should the agent inspect before letting those passages enter the prompt?
Deep · SourcesTrace the retrieval research sources?
References
- Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (NeurIPS 2020). The canonical retrieve-then-generate paper; the figure above is redrawn from it.
- Karpukhin et al., Dense Passage Retrieval (EMNLP 2020). The dual-encoder formulation behind query / passage embedding asymmetry that the NVIDIA embed model enforces.
- Johnson, Douze & Jégou, Billion-scale similarity search with GPUs (FAISS, 2017). The vector-index data structure used by every "vector database" you have ever heard of.
- Gao et al., HyDE: Precise Zero-Shot Dense Retrieval without Relevance Labels (2022). Generates a hypothetical answer and embeds that instead of the question; a quick win for short or ambiguous queries.
- Lin et al., Pretrained Transformers for Text Ranking (2020). The reranker pattern that a production retrieval stack uses as its second stage.
- Edge et al., From Local to Global: A Graph RAG Approach to Query-Focused Summarization (2024). Builds an LLM-derived knowledge graph and pre-summarizes its communities so global, corpus-wide questions can be answered; the pipeline figure above is redrawn from it.
Comprehensive list at Going Further · References.
Try it · retrieval, live
Ask a question. The artifact embeds it with the same endpoint from this page and ranks a small built-in corpus by cosine similarity. The bars show every score. It then answers from the top passages and cites them. Change the question and watch the ranking shift.
The corpus is embedded offline and shipped beside the page as a prebuilt index so that only your question gets embedded live. You are watching the indexing-versus-serving split from the diagram above run here. The example questions even carry prebuilt vectors and retrieve before you add a key, while editing a passage re-embeds only that one passage.