Wire RAG into an ElevenLabs Agent
Connect external documents to your ElevenLabs Conversational AI agent so it retrieves relevant context before answering — and attributes answers to source titles.
Why RAG
An ElevenLabs agent without RAG answers from its training data. That is fine for general knowledge. It is wrong for specific knowledge: your product docs, your pricing, your runbooks, your blog posts. The agent will hallucinate confidently about things it was never trained on.
Retrieval-augmented generation fixes this. Before the agent answers, it queries a vectorized knowledge base of your documents, pulls the relevant chunks, and grounds its response in what you actually wrote. The result is specific, attributable, and updatable.
What you'll build
- A knowledge base inside ElevenLabs — a collection of your documents, vectorized for semantic search.
- An auto-update pipeline — a GitHub Action that re-indexes your content every time your site rebuilds.
- A prompt update — instructions that tell the agent when to retrieve and how to attribute sources.
Prerequisites
- An ElevenLabs account with Conversational AI access.
- An existing agent you want to add RAG to.
- An ElevenLabs API key with permissions for knowledge-base and agent editing.
- A source of documents (blog, docs site, Notion exports, PDFs).
- If your site is on GitHub Pages: a repo with GitHub Actions enabled.
Step 1 — Create knowledge-base entries
Each document becomes a knowledge-base entry via the ElevenLabs API. You can do this manually in the dashboard for a quick test, but for a real pipeline you'll script it.
First, create a knowledge base document from a URL:
curl -X POST https://api.elevenlabs.io/v1/convai/knowledge-base \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Product Docs",
"type": "url",
"url": "https://your-site.com/docs/"
}'
Or upload a file directly:
curl -X POST https://api.elevenlabs.io/v1/convai/knowledge-base \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: multipart/form-data" \
-F "name=Runbook" \
-F "file=@/path/to/runbook.pdf"
Save the returned id for each entry — you'll attach it to the agent in Step 3.
Step 2 — Trigger vectorization
ElevenLabs needs to vectorize the knowledge base before the agent can query it. This happens server-side when you specify a model. The default is e5_mistral_7b_instruct, which is good for general text.
curl -X POST https://api.elevenlabs.io/v1/convai/knowledge-base/{id}/vectorize \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "e5_mistral_7b_instruct"
}'
Vectorization is async. Poll for status or just wait a minute before testing queries.
Step 3 — Attach to the agent and enable RAG
Update your agent with a PATCH request that enables RAG and attaches the knowledge base entries:
curl -X PATCH https://api.elevenlabs.io/v1/convai/agents/{agent_id} \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"rag": {
"enabled": true,
"knowledge_base": ["kb-entry-id-1", "kb-entry-id-2"]
}
},
"conversation_config": {
"agent": {
"prompt": {
"system_prompt": "You are a helpful assistant. When answering questions, retrieve relevant context from the knowledge base and attribute your answers to the source title. If the answer is not in the knowledge base, say so."
}
}
}
}'
Step 4 — Auto-sync with a GitHub Action
For static sites on GitHub Pages, you want the knowledge base to update every time the site rebuilds. The trigger is page_build, not push. A push trigger fires before GitHub Pages finishes deploying, which causes a ReadabilityError because the URL isn't live yet.
Save this workflow to .github/workflows/sync-knowledge-base.yml in your site's repo:
name: Sync Knowledge Base
on:
page_build:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Re-create knowledge base entries
env:
ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }}
run: |
# Delete old entries (optional — or just update in place)
# This script re-creates and re-attaches knowledge base documents
python3 scripts/sync_kb.py
- name: Vectorize
env:
ELEVENLABS_API_KEY: ${{ secrets.ELEVENLABS_API_KEY }}
run: |
# Poll until vectorization is complete
python3 scripts/vectorize_kb.py
The page_build event fires after GitHub Pages finishes, so the URLs in your knowledge base entries are guaranteed live. Add your ELEVENLABS_API_KEY to the repo's GitHub Secrets.
on: push and your knowledge base entries reference URLs on GitHub Pages, the ElevenLabs crawler may hit a 404 because Pages hasn't finished deploying. The fix is on: page_build. This is documented poorly and cost me an hour.
Step 5 — Verify end-to-end
- Open your ElevenLabs agent in the dashboard. The knowledge base section should show your attached entries with green checkmarks (vectorized).
- Start a conversation with the agent. Ask a question whose answer is in your docs.
- Verify the agent names the source document (e.g., "According to the Product Docs...").
- Ask a question not in the knowledge base. The agent should say it doesn't know, rather than hallucinating.
- Push a change to your site. Wait for the
page_buildaction to run. Ask the same question again — the answer should reflect the updated content.
When not to use this
RAG is the wrong pattern when:
- The agent needs broad world knowledge. If most questions are "What's the weather in Paris?" not "What's your refund policy?", RAG adds latency for no gain.
- Source material changes hourly. Re-vectorizing on every change is expensive. For rapidly changing content, consider a dynamic lookup (API, database) instead of a static knowledge base.
What's next
- Multi-source attribution. If you attach multiple knowledge bases, the agent can cite them by name. This requires careful prompt engineering — test that it distinguishes between "Pricing FAQ" and "Developer Docs."
- Chunking strategy. For long documents, ElevenLabs splits into chunks automatically. If answers span multiple chunks, you may need to tune chunk size or add cross-references.
- Client-side tools. Combine RAG with client tools so the agent can not only answer from docs but also trigger UI changes. See the client tool recipe.
Seth Shoultes builds at garagedoorscience.com and writes about it at sethshoultes.com/blog.