Retriever handles the full pipeline: splitting documents into chunks, embedding them, storing vectors, and retrieving the most similar chunks for any query. The retrievalContext step wires this directly into the agent loop so relevant chunks appear in the system prompt automatically.
Core concepts
Retriever
Orchestrates chunking, embedding, and indexing. Call
index() to add documents and retrieve() to query them.Embedder
Converts text to vectors. Use
HashEmbedder for dev/tests, or plug in an OpenAI/Gemini provider embedder for semantic similarity.VectorStore
Persists and queries
(id, text, embedding) records. Choose MemoryVectorStore for tests or SqliteVectorStore for persistence.retrievalContext
A
ContextStep that auto-retrieves chunks for the current query and appends them to the agent’s system prompt before the model call.Setting up a Retriever
Import the pieces you need and assemble aRetriever:
Constructor options
RetrieverOptions
RetrieverOptions
| Option | Type | Required | Description |
|---|---|---|---|
embedder | Embedder | ✅ | Converts text to vectors |
store | VectorStore | ✅ | Persists and queries vector records |
chunk | ChunkOptions | — | Chunking configuration (see below) |
Indexing documents
Callretriever.index(docs) to chunk, embed, and store documents. It returns the number of chunks added.
IndexDoc fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | — | Stable document identifier. Auto-generated as doc-N if omitted |
text | string | ✅ | Full document text to chunk and embed |
metadata | Record<string, unknown> | — | Arbitrary metadata returned with each result |
Retrieving chunks
Callretriever.retrieve(query, options?) to get the top-K most similar chunks for a query string.
VectorQueryResult[] sorted by descending cosine similarity:
| Field | Type | Description |
|---|---|---|
id | string | Chunk identifier (docId#chunkIndex) |
text | string | Chunk text |
score | number | Cosine similarity (0–1) |
metadata | Record<string, unknown> | Metadata from the original IndexDoc |
RetrieveOptions
| Option | Type | Default | Description |
|---|---|---|---|
topK | number | 4 | Maximum number of chunks to return |
trace | TraceHandle | — | Records a retrieval span visible in the Anvil dashboard |
parentSpanId | string | — | Parent span for nested trace trees |
Embedders
HashEmbedder (dev/test)
HashEmbedder is a zero-dependency, deterministic embedder that uses a hashed bag-of-tokens approach. It requires no API key and no network calls, making it ideal for local development and CI. Because it is not semantic, replace it with a provider embedder before going to production.
Provider embedders
Any object that implements theEmbedder interface works as a drop-in replacement:
- OpenAI
- Gemini
Vector stores
MemoryVectorStore (tests)
In-process, zero-dependency brute-force cosine search. Data is lost when the process exits.SqliteVectorStore (production)
Persistent SQLite-backed store. Requires thebetter-sqlite3 optional peer dependency. Similarity search runs in JS over all stored records — appropriate for small-to-medium corpora embedded in an application.
Install
better-sqlite3 when you use SqliteVectorStore. The package loads lazily so it never breaks builds that use only MemoryVectorStore.Custom chunking
chunkText(text, options?) splits text into overlapping chunks, preferring natural paragraph and sentence boundaries. You can call it yourself before indexing if you need fine-grained control.
Retriever via the chunk constructor option:
Using RAG in an agent
retrievalContext from anvil/agent is a ContextStep that retrieves chunks for the current user query and appends them to the agent’s system prompt before each model call. This is the recommended way to integrate RAG into an agent loop.
Complete example
Custom chunk rendering
Override how retrieved chunks appear in the system prompt with thetemplate option: