How to Build a RAG Application Using Claude?

Asked 20 days ago Updated 17 days ago 74 views

1 Answer


0

Build it in one of two patterns:

  1. Classic vector RAG: chunk your documents, create embeddings, store them in a vector DB, retrieve the top matches, then send those snippets to Claude. Anthropic’s docs say Claude itself does not provide an embedding model, and recommend using an embeddings provider such as Voyage AI for vector search. 
  2. Search-results RAG: have your retrieval layer return search_result blocks to Claude, and Claude can produce natural citations with source attribution from those results. Anthropic documents this both for tool-returned results and for top-level content you already fetched. 

For most production apps, I would use vector retrieval for recall, then pass the best snippets into Claude as search results so the answer is easier to cite and verify. Anthropic explicitly recommends RAG when prompts would otherwise get too large, because it reduces cost, latency, and context-window pressure.

Recommended architecture

Ingestion

  • Load documents.
  • Chunk them into small, semantically coherent pieces.
  • Create embeddings with Voyage AI or another embedding provider. Anthropic’s docs note that Claude does not ship its own embedding model. 
  • Store vectors plus metadata in your DB.

Retrieval

  • Embed the user question.
  • Retrieve top-k chunks.
  • Optionally rerank them.
  • Send only the most relevant chunks to Claude.

Generation

  • Wrap the retrieved chunks as search_result blocks.
  • Ask Claude to answer using only those sources.
  • Enable citations so Claude can cite the retrieved text. Anthropic’s search-results feature supports this and is designed for RAG use cases. 

Performance

  • Use prompt caching for repeated prefixes like system instructions, policies, and stable retrieved context. Anthropic says prompt caching reduces cost and latency and supports automatic caching across active Claude models.

Minimal Python example

# Import the Claude SDK client and the content block types used for RAG.
from anthropic import Anthropic
# Import the helper types for messages and search results.
from anthropic.types import MessageParam, TextBlockParam, SearchResultBlockParam

# Create the Anthropic client with your API key configured in the environment.
client = Anthropic()

# Pretend this function retrieves the top matching chunks from your vector DB.
def retrieve_top_chunks(question: str):
    # Search your embeddings index here.
    # Return chunks with source metadata, titles, and text.
    return [
        {
            "source": "https://docs.example.com/billing",
            "title": "Billing Guide",
            "text": "Invoices are generated on the first day of each month...",
        },
        {
            "source": "https://docs.example.com/refunds",
            "title": "Refund Policy",
            "text": "Refunds are available within 14 days for eligible plans...",
        },
    ]

# Get the user's question.
question = "How do monthly invoices and refunds work?"

# Retrieve the best supporting passages.
chunks = retrieve_top_chunks(question)

# Convert retrieved passages into Claude search_result blocks.
search_results = []
for chunk in chunks:
    # Each search result needs source, title, and a text content block.
    search_results.append(
        SearchResultBlockParam(
            type="search_result",
            source=chunk["source"],
            title=chunk["title"],
            content=[
                TextBlockParam(
                    type="text",
                    text=chunk["text"],
                )
            ],
            citations={"enabled": True},
        )
    )

# Ask Claude to answer using the retrieved evidence.
response = client.messages.create(
    model="claude-opus-4-8",
    matokens=800,
    messages=[
        MessageParam(
            role="user",
            content=[
                # Provide the retrieved evidence first.
                *search_results,
                # Then ask the actual question.
                TextBlockParam(
                    type="text",
                    text=question,
                ),
            ],
        )
    ],
)

# Print Claude's answer.
print(response)

Practical tips

Use small chunks, clear source URLs, and descriptive titles so citations stay precise. Anthropic notes that breaking long content into logical text blocks gives Claude finer citation boundaries.

Use tool-based search results when retrieval is dynamic, and top-level search results when you already fetched or cached the content. Anthropic documents both patterns.  

If your app needs real-time facts like account balances or live policy data, retrieval alone may not be enough; Anthropic recommends tool use for live system lookups in those cases. 

The simplest mental model

Claude is the reasoning layer, not the vector store. Your retrieval stack finds the evidence; Claude turns that evidence into a grounded answer with citations. Anthropic’s current docs are aligned around that architecture. 

Write Your Answer