Claude API + Pinecone Vector Database Setup Guide
Why combine Claude API with Pinecone
Pairing Claude with Pinecone lets you build retrieval-augmented generation (RAG) systems: you store your documents as vector embeddings in Pinecone, retrieve the most relevant chunks for a given question, and pass them to Claude as context so it can answer accurately without hallucinating facts it was never trained on.
This setup solves a specific problem — Claude has no built-in long-term memory of your private data. Pinecone handles similarity search over millions of document chunks in milliseconds; Claude handles reasoning and synthesis over whatever chunks you hand it. Below is a complete, practical setup: creating the index, embedding your documents, running retrieval, and calling Claude with the retrieved context.
Architecture overview
A typical Claude + Pinecone RAG pipeline has four stages:
- Chunk and embed your source documents using an embedding model.
- Upsert those vectors into a Pinecone index with metadata (source text, document ID, etc.).
- Query Pinecone with the embedded user question to get the top-k relevant chunks.
- Send those chunks plus the question to Claude as context in the prompt.
Claude itself doesn't generate embeddings — you need a separate embedding model (OpenAI's text-embedding-3-small, Voyage AI, or Cohere are common choices for Claude-based RAG stacks, since Anthropic doesn't yet ship its own embeddings endpoint).
Step 1: Create a Pinecone index
Install the Pinecone client and create an index sized to your embedding model's dimensions (1536 for most OpenAI embedding models, 1024 for Voyage's voyage-2):
pip install pinecone-client
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="YOUR_PINECONE_API_KEY")
pc.create_index(
name="claude-rag-docs",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
index = pc.Index("claude-rag-docs")
Step 2: Chunk and embed your documents
Split documents into chunks of roughly 300–800 tokens with some overlap, then embed each chunk:
import openai
def embed(text):
response = openai.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
chunks = [
{"id": "doc1-chunk1", "text": "Your document chunk text here..."},
{"id": "doc1-chunk2", "text": "Next chunk of text..."},
]
vectors = [
{
"id": c["id"],
"values": embed(c["text"]),
"metadata": {"text": c["text"]}
}
for c in chunks
]
index.upsert(vectors=vectors)
Keep the original text in Pinecone's metadata field — you'll need it to build the prompt for Claude later, since Pinecone returns vectors and scores but not raw text unless you store it.
Step 3: Query Pinecone for relevant context
When a user asks a question, embed it the same way and query the index:
def retrieve_context(question, top_k=5):
query_vector = embed(question)
results = index.query(
vector=query_vector,
top_k=top_k,
include_metadata=True
)
return [match["metadata"]["text"] for match in results["matches"]]
Five matches is a reasonable starting point. If your chunks are small, go higher; if they're large, three is often enough to stay within a comfortable prompt size.
Step 4: Send retrieved context to Claude
Build a prompt that clearly separates retrieved context from the question, and send it to Claude. Here's how that looks against SubToAPI, which exposes Claude through a standard HTTPS API using sub_live_... application keys:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Context:\n[retrieved chunk 1]\n[retrieved chunk 2]\n[retrieved chunk 3]\n\nQuestion: What does the warranty cover?\n\nAnswer using only the context above. If the context does not contain the answer, say so."
}
]
}'
Or in JavaScript, wiring the full retrieval step together:
async function askWithContext(question, contextChunks) {
const contextBlock = contextChunks.join("\n\n");
const response = await fetch("https://api.subtoapi.app/v1/messages", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
"content-type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-4",
max_tokens: 1024,
messages: [{
role: "user",
content: `Context:\n${contextBlock}\n\nQuestion: ${question}\n\nAnswer using only the context above.`
}]
})
});
const data = await response.json();
return data.content[0].text;
}
Instructing Claude explicitly to rely only on the provided context — and to say when it can't find an answer — is the single most effective prompt-level guardrail against hallucination in a RAG pipeline.
Practical tips for production
- Namespace by tenant or document set. Pinecone namespaces let you isolate data per customer or per project within one index, which matters if you're building a multi-tenant product.
- Re-rank before sending to Claude. Pinecone's top-k results are ranked by vector similarity, not necessarily relevance quality. A lightweight re-ranking step (or just asking Claude to ignore irrelevant chunks) improves answer quality.
- Track token usage. Retrieved context adds up fast, especially with five or more chunks per query. SubToAPI's dashboard shows per-key usage metadata so you can see exactly how much context-heavy RAG queries are costing across your team — useful when you're tuning
top_kand chunk size for cost versus accuracy. - Stream the response. For chat-style RAG apps, streaming Claude's answer back to the user improves perceived latency while retrieval and generation both take time. See /docs/streaming for details on implementing this over SubToAPI.
- Use tool calling for structured retrieval. Instead of always retrieving before every call, you can give Claude a retrieval tool it invokes only when it decides it needs more context — see /docs/tools for how tool use works.
Getting Claude access without managing Anthropic infra directly
If you're prototyping a RAG pipeline and don't want to deal with raw Anthropic account setup, rate limits, or billing per seat, SubToAPI gives you a Claude-compatible HTTPS endpoint with application API keys, usage metadata, and team seats out of the box. Start with the /docs/quickstart guide, check the /docs/messages reference for request formats, and compare plans on /pricing — Solo is €9/month for individual projects, Team is €19/seat for shared dashboards. You can try it with a free trial at /signup before committing.
questions
Do I need Claude to generate the embeddings for Pinecone? No. Claude doesn't offer an embeddings endpoint. Use a dedicated embedding model like OpenAI's text-embedding-3-small or Voyage AI, then pass the retrieved text (not vectors) to Claude as context.
How many chunks should I retrieve per query? Three to five chunks of 300–800 tokens each is a reasonable default. Go higher only if your documents are dense and answers often span multiple sections — more chunks means more tokens and higher cost per request.
Can I use a different vector database instead of Pinecone? Yes — the same pattern (embed, store, retrieve, pass to Claude as context) works with Weaviate, Qdrant, or pgvector. Pinecone is popular mainly for its managed serverless scaling and simple API.