Appearance
Vector Search
Vector search enables semantic search across your data sources using Cloudflare Vectorize.
Overview
Features:
- Semantic similarity matching
- Fast nearest-neighbor search
- Automatic embedding generation
- Cross-source search
How It Works
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Query │────▶│ Generate │────▶│ Search │
│ Input │ │ Embedding │ │ Vectorize │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Return │◀────│ Retrieve │◀────│ Find Top │
│ Results │ │ Content │ │ Matches │
└──────────────┘ └──────────────┘ └──────────────┘Searching
Via Dashboard
- Navigate to Context
- Enter search query
- View ranked results
Via API
bash
curl "https://your-domain.com/api/agents/{id}/sources/search?query=how+to+reset+password"Response:
json
{
"results": [
{
"id": "chunk-123",
"source_id": "source-456",
"content": "To reset your password, go to Settings...",
"score": 0.92,
"metadata": {
"source_name": "User Guide",
"page": 15
}
},
{
"id": "chunk-124",
"content": "Password reset emails are sent within 5 minutes...",
"score": 0.85
}
]
}Search Parameters
Basic Search
json
{
"query": "how to integrate API",
"limit": 10
}Filtered Search
json
{
"query": "installation guide",
"filter": {
"source_id": "source-123",
"metadata.category": "technical"
},
"limit": 5
}Threshold Search
json
{
"query": "error handling",
"min_score": 0.7,
"limit": 20
}Embeddings
Model
Using Cloudflare Workers AI:
- Model:
@cf/baai/bge-base-en-v1.5 - Dimensions: 768
- Metric: Cosine similarity
Generation
Embeddings are generated automatically:
typescript
const embedding = await env.AI.run(
'@cf/baai/bge-base-en-v1.5',
{ text: content }
)Vectorize Configuration
Index Settings
toml
[[vectorize]]
binding = "VECTORIZE"
index_name = "agents-dashboard-embeddings"Index properties:
- Dimensions: 768
- Metric: cosine
- Max vectors: Based on plan
Fused retrieval
Every knowledge lookup — the search_knowledge tool, auto-RAG in chat, the OAC storefront agent — goes through one function, searchKnowledgeFused() in agent/knowledge.ts. It runs up to three channels in parallel and merges them with reciprocal rank fusion (score += 1 / (60 + rank) per channel):
| Channel | Source | Notes |
|---|---|---|
| Vector | Vectorize, @cf/baai/bge-base-en-v1.5 | one query per allowed scope filter (see below), top 3 × topK |
| Keyword | kb_chunks_fts — FTS5 (porter + unicode61) over chunk text, BM25-ordered | query terms ≥ 3 chars, stop-words removed, up to 10 terms OR-ed |
| AI Search (optional) | a Cloudflare AI Search instance indexing the agents' R2 bucket | only when settings.knowledge.aiSearchInstance is set; folder-filtered to the agent's and its business's prefixes |
When more than one candidate survives, the fused list is reranked with @cf/baai/bge-reranker-base before the top topK (1–20, default 5) is returned. Each hit reports which channels found it.
The vector index alone misses exact tokens (SKU codes, names, error strings); the keyword index alone misses paraphrase. Fusing both, then reranking, is what makes "the invoice number on the Lim order" resolve.
Tenancy and scope
Knowledge has three scopes, from hard boundary inward: business (the platform tenant that owns the agent — see tenants), agent, and contact. Each data_sources row carries business_id, visibility (business | agent | contact, default agent) and contact_id (migration 077); at ingest the same values are stamped into every chunk's Vectorize metadata and FTS row.
A search only ever asks for two things:
- this agent's own chunks (
agent_id = me), and - chunks another agent of the same business has marked
visibility = business.
There is no option to read across tenants — the old filterByAgent=false default was removed. Change a source's visibility from the Knowledge page (per-source select) or with PATCH /sources/{id} { visibility }; the change re-stamps every chunk, so a reindex follows automatically. Business sharing needs the agent to belong to a tenant; chunks ingested before the tenancy migration carry no business_id and must be re-ingested to be shareable.
Integration
With Chat
Automatic RAG in conversations:
typescript
// Agent automatically searches relevant context
const context = await searchSources(query)
const response = await generateWithContext(query, context)With Workflows
json
{
"type": "search-sources",
"data": {
"query": "{{input.question}}",
"limit": 3
},
"output": "search_results"
}With Tools
Enable as an agent tool:
json
{
"name": "search_knowledge",
"description": "Search the knowledge base",
"parameters": {
"query": {
"type": "string",
"description": "Search query"
}
}
}Performance
Optimization Tips
- Limit results: Request only needed results
- Use filters: Narrow search scope
- Cache common queries: Store frequent searches
- Batch queries: Combine related searches
Metrics
Monitor search performance:
- Query latency
- Result relevance
- Cache hit rate
Best Practices
1. Quality Content
Better content = better results:
- Clear, well-written text
- Proper structure
- Consistent terminology
2. Appropriate Chunk Size
Balance context and precision:
json
{
"chunking": {
"max_size": 500,
"overlap": 50
}
}3. Metadata Filtering
Use metadata for precision:
json
{
"filter": {
"metadata.product": "pro",
"metadata.version": "2.0"
}
}4. Score Thresholds
Filter low-quality matches:
json
{
"min_score": 0.75
}5. Regular Updates
Keep embeddings current:
- Refresh on content changes
- Re-index periodically
Troubleshooting
Poor Results
- Check source content quality
- Verify chunking settings
- Adjust score thresholds
- Review search queries
Slow Searches
- Reduce result limit
- Add filters
- Check index health
- Consider caching
Missing Content
- Verify source is indexed
- Check processing status
- Ensure content is chunked
- Validate embeddings exist
API Reference
See Sources API for complete endpoint documentation.
