Claude API RAG: Retrieval-Augmented Generation Guide
Retrieval-augmented generation (RAG) with the Claude API means retrieving relevant documents from your own knowledge base and feeding them into Claude's context window before it generates an answer. Instead of relying on what Claude learned during training, you give it fresh, grounded, verifiable facts at request time — your internal docs, product catalog, support tickets, or codebase — and ask it to answer based on that.
This matters because Claude, like every LLM, doesn't know your private data and can hallucinate when asked about it. RAG fixes that by splitting the problem into two parts: a retrieval step (find the right chunks of text) and a generation step (have Claude reason over those chunks and produce a grounded answer). The rest of this article walks through how to build that pipeline against the Claude API, including chunking strategy, prompt structure, and a working code example.
Why RAG instead of fine-tuning
Fine-tuning bakes knowledge into model weights. It's slow to update, expensive, and still doesn't guarantee factual recall. RAG keeps your data external and searchable, so:
- Updating a document updates what Claude can answer — no retraining.
- You can cite sources, since you control which chunks went into the prompt.
- You avoid context bloat: only relevant chunks are injected, not your entire knowledge base.
- You can swap embedding models or vector stores without touching your Claude integration.
For almost all internal tools, support bots, and documentation assistants, RAG is the right default over fine-tuning.
The RAG architecture, step by step
A typical Claude RAG pipeline has four stages:
- Chunk and embed your source documents.
- Store the chunks and their vector embeddings in a vector database.
- Retrieve the top-k relevant chunks for a given user query.
- Generate — send the query plus retrieved chunks to Claude and return the answer.
1. Chunking
Split documents into overlapping chunks of 300–800 tokens. Too small and you lose context; too large and retrieval gets noisy. A common pattern:
function chunkText(text, chunkSize = 500, overlap = 50) {
const words = text.split(/\s+/);
const chunks = [];
for (let i = 0; i < words.length; i += chunkSize - overlap) {
chunks.push(words.slice(i, i + chunkSize).join(" "));
}
return chunks;
}
Keep metadata (source file, section title, URL) attached to each chunk — you'll want to cite it later.
2. Embedding and storage
Embed each chunk with an embedding model (OpenAI, Voyage, or any provider you already use) and store the vectors in something like Pinecone, pgvector, Weaviate, or even a local FAISS index for small datasets. Claude doesn't provide embeddings itself, so this step uses a separate service.
3. Retrieval
At query time, embed the user's question with the same model, then run a similarity search to pull the top 3–8 chunks:
const queryEmbedding = await embed(userQuestion);
const results = await vectorStore.query({
vector: queryEmbedding,
topK: 5,
includeMetadata: true,
});
const context = results.map(r => r.metadata.text).join("\n\n---\n\n");
4. Generation with Claude
Build a prompt that clearly separates retrieved context from the question, and instruct Claude to answer only from that context (or say it doesn't know).
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 800,
"system": "Answer only using the provided context. If the context does not contain the answer, say you do not know. Cite the source file for each claim.",
"messages": [
{
"role": "user",
"content": "Context:\n'"$CONTEXT"'\n\nQuestion: '"$QUESTION"'"
}
]
}'
This structure — a strict system prompt plus explicit context injection — is the core of every production RAG system built on Claude. The quality of your answers depends far more on retrieval precision and prompt discipline than on the model itself.
Practical tips that improve RAG quality
- Use re-ranking. Vector similarity alone is noisy. Retrieve 20 candidates, then re-rank with a cheaper model or a cross-encoder before picking the final 5.
- Instruct Claude to decline gracefully. Without an explicit "say you don't know" instruction, Claude will try to be helpful and may fill gaps with plausible-sounding but unsupported text.
- Keep context budget in mind. Claude's context window is large, but stuffing in 50 chunks degrades focus. Fewer, higher-quality chunks beat volume.
- Stream the response for chat-style RAG apps so users see tokens as they arrive instead of waiting for the full answer — see /docs/streaming for details on consuming streamed responses.
- Use tool calling for live lookups. If part of your "knowledge" is dynamic (pricing, inventory, ticket status), combine RAG with Claude's tool-use feature so Claude can call a function instead of relying only on static retrieved text. See /docs/tools.
Where SubToAPI fits in
RAG pipelines call the generation step repeatedly — every user question, every retry, every re-ranking pass if you use Claude for that too. SubToAPI turns your existing Claude access into a standard HTTPS API with application keys (sub_live_...), so your RAG backend, retrieval worker, and any internal admin tools can all call the same endpoint with separate keys, usage tracking, and team seats instead of sharing one raw credential. That's useful once a RAG project moves from a prototype script to something with multiple services and multiple engineers touching it.
Getting started takes a few minutes: sign up at /signup, grab a key, and follow /docs/quickstart. The /docs/messages reference covers the full request and response shape for the generation step described above, and plans start at €9/month on the Solo tier — see /pricing for Team and Scale options if you need shared usage across a group.
Putting it together
A minimal but production-viable Claude RAG stack looks like: a chunking job that runs on document updates, an embedding call per chunk, a vector store for retrieval, a re-ranking pass (optional but recommended), and a tightly scoped generation prompt sent to Claude with explicit grounding instructions. None of these pieces are exotic — the hard part is tuning chunk size, retrieval k, and prompt wording for your specific data, which usually takes a few iterations of testing against real questions your users actually ask.
questions
Does the Claude API have built-in RAG or a vector database? No. Claude handles the generation step only. You need a separate embedding model and vector store (Pinecone, pgvector, Weaviate, etc.) to handle chunking, storage, and retrieval before sending context to Claude.
How many retrieved chunks should I send to Claude per query? Start with 3–5 well-ranked chunks rather than many loosely relevant ones. Precision in retrieval matters more than volume — too much context dilutes Claude's focus and can increase latency and cost.
Can I combine RAG with Claude's tool use? Yes, and it's common in production. Use RAG for static or slow-changing knowledge (docs, policies, FAQs) and tool calls for live or structured data (database lookups, pricing, order status). See /docs/tools for the tool-use request format.