Agentic Search
Agentic Search helps agents answer questions when the answer is not in the first chunk returned by retrieval. Instead of searching again and hoping for a better result, the model can work inside the corpus: search to find a source, open it, move through nearby chunks, grep for exact terms, and search again without repeating chunks.
In short, retrieval finds likely sources. Agentic Search lets the model inspect those sources and gather enough evidence to answer. You can use it as a set of MCP tools that drop into any agent, or as part of the Search Toolkit SDK for custom retrieval pipelines. It works in Studio, in open-source deployments, and in Libraries.
Retrieval primitives and the agentic loop
Agentic Search is not another retrieval method next to keyword or semantic search. Keyword and semantic search are retrieval primitives. Agentic Search is an orchestration layer that uses those primitives, adds navigation, and iterates until the model has enough evidence.
| Layer | How it works | Best for |
|---|---|---|
| Keyword (lexical) | Matches exact terms or phrases | Known identifiers, code, exact quotes |
| Hybrid or semantic retrieval | Combines keyword and vector search, or uses vector search alone | Natural-language questions over a corpus |
| Agentic Search | Calls retrieval tools, navigates inside documents, excludes already-seen chunks, and searches again | Complex questions that require source verification or evidence across documents |
Most production search setups start with hybrid retrieval because it combines keyword precision with semantic recall. Agentic Search builds on that foundation: search uses semantic or hybrid retrieval, and grep adds targeted keyword matching inside a specific document.
How Agentic Search works
Agentic Search runs a retrieval loop. The model does not just receive chunks and stop. It can inspect a result, drill into the source document to read surrounding context, then re-query with what it learned.
The retrieval loop
- Search: The model runs a query across the collection and receives the most relevant chunks.
- Inspect: The model picks a promising hit and reads the surrounding context within that document, without re-running a global search.
- Grep: The model searches for an exact term or phrase inside the same document to jump to a more specific region.
- Navigate or read: The model steps through adjacent chunks or reads a known source range to gather evidence.
- Re-query: Armed with new context, the model runs another search with
exclude_idsso already-seen chunks don't come back again.
The loop continues until the model has enough evidence to answer the question. exclude_ids makes corpus-level pagination possible: the agent can move through new results instead of cycling over the same chunks.
The model calls the following tools inside the loop. Each one operates on the search index and returns chunks with their content, score, and position metadata.
| Tool | What it does |
|---|---|
search(query, top_k, exclude_ids) | Runs semantic or hybrid retrieval across the collection. Pass exclude_ids to avoid returning chunks the agent already inspected. |
open(source_id, start_offset, end_offset, window) | Expands context around a retrieved chunk. Returns adjacent chunks in reading order. |
navigate(source_id, start_offset, end_offset, direction, top_k) | Steps forward or backward through a document from a known position. |
read(source_id, start_offset, end_offset, top_k) | Reads chunks from a known source range returned by search or navigation results. |
grep(source_id, pattern, mode, top_k) | Lexical search for an exact term or phrase within a single document. |
ingest(uri) | Adds a document to the index. Accepts a local path, file:// URI, or http(s):// URL. |
delete(source_id) | Removes a document and all its chunks from the index. |
Agentic navigation requires a NavigableIndex. When you define your schema migration, set IndexingMode.DOCUMENT_PER_CHUNK so that chunks carry source offsets and can be walked in order.
Get started with the starter app
The fastest way to try Agentic Search is with the search-starter-app template. It is a Copier template that scaffolds a project with ingestion pipelines, a Vespa search index, an MCP server exposing the navigation tools, and sample data.
The starter app is designed to be driven by an agent. You scaffold the project, start Vespa, then launch an agent like Vibe that discovers the MCP server and calls the search and ingestion tools through natural language.
Prerequisites
- A Mistral API key from console.mistral.ai
- Docker for running Vespa locally
- uv for Python package management
- Copier for scaffolding the project
- Vibe (or any MCP-compatible agent) to drive the search loop
Scaffold and start the index
Create a new project from the template, then start Vespa and apply the schema migrations. Use the tabs to copy the commands or inspect the generated structure.
uvx copier copy gh:mistralai/search-starter-app my-search-project
cd my-search-project
make setup-vespaCopier asks for your Mistral API key and a collection name. The make setup-vespa target starts a Vespa container with Docker and deploys the schema migrations. When it finishes, the search index is ready.
Ingest and search with an agent
The starter app registers an MCP server in .mcp.json that exposes the search and navigation tools. When you launch Vibe in the project directory, it discovers the server and its 7 tools automatically. Use the tabs to follow the same flow as the demo: start Vibe, ingest a document, then ask a question.
vibe --trustVibe detects the MCP server and the search skill. You can verify the connection with /mcp, which lists the server and its tools.
You can also run ingestion and search directly from the shell with make ingest path=sample_data/hello.txt and make search query="hello world". The MCP server is the recommended path for agentic workflows.
Use Agentic Search as MCP tools
The MCP server exposes seven tools that any MCP-compatible agent can call. The starter app registers the server in .mcp.json so Vibe discovers it automatically, but you can also connect from Studio or a custom agent.
Run the MCP server
The MCP server starts automatically when Vibe launches in the project directory. To run it standalone, use the tab that matches your transport mode.
uv run python -m entrypoints.mcp_serverUse stdio mode for local agents such as Vibe.
Register with an agent
- Vibe: The
.mcp.jsonfile in the generated project registers the server. Runvibe --trustin the project directory and Vibe discovers it. - Studio: Add the server as a connector or MCP server in the agent configuration.
- Custom agents: Connect any MCP-compatible client to the server's stdio or HTTP endpoint.
The MCP server includes instructions that describe the retrieval loop, so the agent knows to start with search, drill into results with open, grep, navigate, and read, then call search again with exclude_ids to connect information across documents without repeating the same chunks.
To scope a search to a single document, include the document title or source_id in the query. This narrows the global search and reduces latency.
Use Agentic Search with the SDK
If you need more control than the MCP server provides, build retrieval pipelines directly with the Search Toolkit SDK. The SDK gives you the same QueryEngine and VectorRetriever that the MCP server uses, plus advanced features like query rewriting, multi-retriever fusion, and semantic caching.
Core SDK patterns
The SDK snippets build from the smallest setup to more advanced retrieval. Use the tabs to start with the client, run a query, then add preprocessing or hybrid retrieval.
from mistralai.client import Mistral
from mistralai.search.toolkit.embedders import MistralEmbedder
client = Mistral(api_key="your-api-key")
embedder = MistralEmbedder(client=client)Ingest documents
The ingestion pipeline loads files, extracts text, splits into chunks, optionally enriches them, generates embeddings, and indexes the result. The starter app routes files by extension: text files use plain-text extraction, and everything else uses Mistral OCR. Use the tabs to compare the two extractor paths.
from mistralai.search.toolkit.ingestion.pipelines import Pipeline
from mistralai.search.toolkit.ingestion.loaders import FilesystemFileLoader
from mistralai.search.toolkit.ingestion.extractors import PlainTextExtractor
from mistralai.search.toolkit.ingestion.text_splitters import (
MarkdownTextSplitter,
MarkdownTextSplitterConfig,
)
pipeline = Pipeline(
loader=FilesystemFileLoader(),
extractor=PlainTextExtractor(),
text_splitter=MarkdownTextSplitter(
MarkdownTextSplitterConfig(chunk_size=4096, chunk_overlap=50)
),
embedder=embedder,
stores=vector_store,
)
total = await pipeline.run(documents=["doc.txt"], use_checkpoint=False)
print(f"Indexed {total} chunks.")You can also ingest documents through the MCP server's ingest tool, which accepts local paths, file:// URIs, and HTTP URLs. The server handles the routing automatically.
Latency and tradeoffs
Each tool call has a cost, but navigation can reduce end-to-end latency and token usage because the model converges faster. Instead of repeatedly issuing broad searches, the agent can stay inside the right source, use grep to jump to specific terms, and use exclude_ids to avoid revisiting the same chunks.
In the Agentic Search benchmarks cited in the Search Toolkit launch materials, the full agentic loop with navigation improved FinanceBench accuracy from 27% for single-shot RAG to 86%. Compared with a search-only loop, the full navigation and tool stack reduced FinanceBench p90 latency by 40%, reduced OfficeQA token usage by 1.8x, and shortened a Vibe task from 368 seconds to 227 seconds. For background on Search Toolkit, see Introducing Search Toolkit.
To keep the loop efficient:
- Use
exclude_idson follow-up searches so the agent sees new chunks instead of repeated results. - Scope searches to a single document by including its title or
source_idin the query. - Use
grepbefore broad re-querying when the agent already knows the term or phrase it needs. - Tune
top_kper hop to keep context windows manageable. - Use a semantic cache to skip redundant retrieval across similar queries.
- Bound the number of hops in your agent definitions to limit the loop depth.
For an overview of semantic caching, see the Search Toolkit retrieval guide.
Integrate into agents, workflows, and deployments
Agents
Register the search MCP server so an agent can call the search and navigation tools autonomously. With Vibe, the .mcp.json file in the generated project handles registration. Run vibe --trust in the project directory, then use /mcp to verify the connection. The server's instructions describe the retrieval loop, so the agent knows to start with search, drill into results, then re-query to connect information.
Workflows
Use the Mistral Workflows API to orchestrate ingestion and retrieval as workflow activities. Start from the starter app's src/entrypoints/ scripts when you need workflow tasks that ingest documents or query an index.
Customer deployments
- Self-host the index with Vespa and Docker, or use a managed backend.
- Expose the MCP server in HTTP mode behind your own authentication for production agents.
- Generate a
vespa.locksnapshot for CI reproducibility withmake generate-vespa-lock.
Next steps
- Search Toolkit: learn about ingestion pipelines, retrieval strategies, and the full SDK.
- Libraries: use managed document ingestion and search for built-in RAG.
- Connectors: connect models and agents to external tools and data sources.
- Agents: combine language models with built-in tools for multi-step reasoning.
- search-starter-app: the Copier template for bootstrapping a Search Toolkit project.