search
Hybrid semantic + full-text search with optional cross-source fusion
Hybrid search combining semantic similarity with full-text keyword matching using Reciprocal Rank Fusion (RRF). Optionally search across entity memories and past conversations with weighted fusion.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes | - | Natural language search query (1-10000 chars) |
limit | number | No | 5 | Maximum results to return (1-50) |
fullTextWeight | number | No | 1.0 | Weight for keyword matching (0-2) |
semanticWeight | number | No | 1.0 | Weight for semantic similarity (0-2) |
tags | string[] | No | - | Filter to documents with ALL specified tags |
sourceType | enum | No | - | Filter by source: note, file, or url |
contentType | enum | No | - | Filter by content type: email, youtube, calendar, contact, webpage, document |
minScore | number | No | - | Minimum relevance score threshold (0-1) |
includeMemories | boolean | No | false | Also search entity memories (requires ENABLE_MEMORY) |
includeConversations | boolean | No | false | Also search past conversations (requires ENABLE_CONVERSATIONS) |
memoryWeight | number | No | 1.0 | Weight for memory results when includeMemories=true (0-2) |
conversationWeight | number | No | 0.5 | Weight for conversation results when includeConversations=true (0-2) |
Example Request
Document-Only Search (Default)
Cross-Source Search
Response
Document-Only Response
Cross-Source Response
When includeMemories or includeConversations is true, results are fused by score:
Output Schema
This tool MUST return structuredContent alongside the text response. The structuredContent object MUST use canonical verbose keys regardless of the COMPACT_RESPONSES setting.
| Field | Type | Description |
|---|---|---|
query | string | The search query |
totalResults | integer | Number of results returned |
results | array | Array of result objects |
results[].type | enum | document, memory, or conversation |
results[].score | number | Relevance score |
results[].documentId | string | Document UUID (document results) |
results[].documentTitle | string | Document title (document results) |
results[].sourceType | string | Source type (document results) |
results[].tags | string[] | Document tags (document results) |
results[].chunkId | string | Chunk UUID (document results) |
results[].content | string | Content snippet (truncated to 500 chars) |
results[].entityName | string | Entity name (memory results) |
results[].entityType | string | Entity type (memory results) |
results[].sessionId | string | Session ID (conversation results) |
results[].sessionKey | string? | Session key (conversation results) |
results[].title | string? | Session title (conversation results) |
results[].summary | string? | Session summary (conversation results) |
counts | object | Source counts (cross-source only) |
counts.documents | integer | Number of document results |
counts.memories | integer | Number of memory results |
counts.conversations | integer | Number of conversation results |
How It Works
Reciprocal Rank Fusion (RRF)
textrawl runs two parallel searches:
- Full-Text Search: PostgreSQL tsvector matching for exact keywords
- Semantic Search: pgvector cosine similarity for meaning
Results are combined using RRF:
Where k = 60 (standard RRF constant).
Weight Tuning
| Use Case | fullTextWeight | semanticWeight |
|---|---|---|
| Exact phrases | 1.5-2.0 | 0.5-1.0 |
| Conceptual search | 0.5-1.0 | 1.5-2.0 |
| Balanced (default) | 1.0 | 1.0 |
| Keyword-only | 2.0 | 0 |
| Semantic-only | 0 | 2.0 |
Tip: Start with default weights and adjust based on results. Higher semantic weight helps with paraphrased queries.
Filtering
By Tags
Filter to documents containing ALL specified tags:
Only returns documents tagged with both work AND project-x.
By Source Type
| sourceType | Description |
|---|---|
note | Created via add_note tool |
file | Uploaded via CLI or Web UI |
url | Web content (future feature) |
By Content Type
| contentType | Description |
|---|---|
email | Email messages |
youtube | YouTube watch history |
calendar | Calendar events |
contact | Contacts |
webpage | Saved web pages |
document | General documents |
By Score Threshold
Filter out low-relevance results:
Caution: Scores are relative. A 0.7 threshold may filter out relevant results for broad queries.
Error Responses
| Error | Cause | Fix |
|---|---|---|
| Database not configured | Missing Supabase credentials | Set SUPABASE_URL and SUPABASE_SERVICE_KEY |
| Embedding provider not configured | Missing API key | Set OPENAI_API_KEY or configure Ollama |
| Search failed | Database or embedding error | Check connectivity and logs |
Best Practices
- Start broad, then narrow: Begin without filters, add them if too many results
- Use semantic weight for questions: Increase
semanticWeightfor natural language queries - Use full-text weight for keywords: Increase
fullTextWeightfor specific terms - Combine with get_document: Search returns chunks, use
get_documentfor full context - Use cross-source sparingly: Enable
includeMemories/includeConversationsonly when you need context from those sources - Check score distribution: If all scores are low, try rephrasing the query