Hybrid Search
Every query in TeamLoop passes through a multi-stage hybrid search pipeline that combines the strengths of semantic understanding and exact keyword matching. The result is retrieval that catches both conceptual relationships and precise terminology, then refines the top candidates with a cross-encoder reranker for maximum precision.
The Search Pipeline
Section titled “The Search Pipeline”When you run a query, TeamLoop executes the following stages:
- Vector search — finds semantically similar entities using embedding cosine similarity
- BM25 full-text search — finds entities containing matching keywords
- Reciprocal Rank Fusion — merges the two result sets into a unified ranking
- Cross-encoder reranking — rescores the top candidates for precision refinement
- Score normalization — normalizes final scores to a 0-1 range
Both search pipelines run in parallel, so hybrid retrieval adds minimal latency compared to vector-only search.
Vector Semantic Search
Section titled “Vector Semantic Search”Vector search embeds your query using the same model that embedded your entities, then retrieves the top 50 candidates by cosine similarity from pgvector.
This means a query for “auth token refactor” will match entities about “JWT migration” or “session management overhaul” even when they share no keywords — the embedding model understands semantic equivalence.
Embedding models by deployment:
| Deployment | Model | Dimensions |
|---|---|---|
| SaaS | Voyage AI (voyage-3) | 1024 |
| AWS Marketplace | Amazon Titan V2 (default) | 1024 |
The embedding model is locked per-organization after the first embedding is created. Both models use 1024 dimensions for schema compatibility. Titan embeddings are generated with bounded parallelism (up to 5 concurrent requests per batch) for high throughput.
BM25 Full-Text Search
Section titled “BM25 Full-Text Search”Full-text search uses PostgreSQL’s built-in tsvector indexing with ts_rank_cd scoring. It tokenizes your query and matches against pre-indexed entity text, ranking results by term frequency and document coverage.
This catches cases where exact terms matter — searching for “PROJ-1234” or “CockroachDB” will surface entities containing those literal strings, even if the embedding model doesn’t place them close in vector space.
Full-text search retrieves up to 50 candidates, ranked by BM25 relevance.
Reciprocal Rank Fusion (RRF)
Section titled “Reciprocal Rank Fusion (RRF)”After both pipelines return their candidates, TeamLoop merges them using Reciprocal Rank Fusion with k=60. For each entity, the RRF score is:
score = sum(1 / (k + rank)) across all lists where the entity appearsAn entity that appears in both vector and text results receives contributions from both, boosting it above entities that only appear in one. The constant k=60 prevents top-ranked results from dominating — a well-established default from information retrieval research.
After fusion, results are sorted by descending RRF score. The top 20 candidates are forwarded to the reranking stage.
Cross-Encoder Reranking
Section titled “Cross-Encoder Reranking”The reranker is a cross-encoder model that scores each (query, document) pair independently. Unlike the embedding model (which encodes query and document separately), the cross-encoder sees both together and can make fine-grained relevance judgments.
TeamLoop sends the top 20 RRF candidates to the reranker and keeps the top 5 results.
Reranking models by deployment:
| Deployment | Provider | Model |
|---|---|---|
| SaaS | Voyage AI | rerank-2 |
| AWS Marketplace | Cohere via Bedrock | rerank-v3.5 |
Timeout and Graceful Fallback
Section titled “Timeout and Graceful Fallback”Reranking runs with a 300ms timeout. If the reranker is unavailable, returns an error, or exceeds the timeout, TeamLoop logs a warning and returns results in their original RRF-fused order. This means reranking improves precision when available but never blocks a query from returning results.
Atomic Facts in Search
Section titled “Atomic Facts in Search”When entities have been decomposed into atomic facts (via teamloop_save_facts), those facts participate in search alongside regular entities. Both vector and text search index facts as first-class entities.
This means a query for “who approved the database migration?” may surface a specific fact like “Sarah approved the PostgreSQL migration on January 15” rather than the entire parent document. Fact results link back to their parent entity via PART_OF relationships, so you can always navigate to the full context.
See Fact Extraction for details on how facts are created.
Graceful Degradation
Section titled “Graceful Degradation”The pipeline is designed to return useful results even when components fail:
| Scenario | Behavior | Method |
|---|---|---|
| Both pipelines succeed | Full hybrid fusion + reranking | hybrid |
| Embeddings unavailable | Text search only (BM25 ranking) | text_only |
| Text search fails | Vector search only (cosine similarity) | vector_only |
| Reranker fails or times out | Results returned in RRF order | hybrid (reranked: false) |
| Both pipelines fail | Error returned to caller | — |
The method field in search metadata tells you which path was taken, so you can understand the quality of your results.
Configuration Defaults
Section titled “Configuration Defaults”| Parameter | Default | Description |
|---|---|---|
| Vector candidates | 50 | Max results from vector search |
| Text candidates | 50 | Max results from full-text search |
| RRF k | 60 | Fusion constant (higher = more equal weighting) |
| Rerank candidates | 20 | How many RRF results go to the reranker |
| Rerank top-k | 5 | How many results survive reranking |
| Rerank enabled | true | Whether reranking runs at all |
| Rerank timeout | 300ms | Max time to wait for the reranker |
These defaults work well for most workloads. Per-query overrides are available through the search API for advanced use cases.
Score Normalization
Section titled “Score Normalization”Final scores are normalized to a 0-1 range by dividing all scores by the maximum score in the result set. The top result always has a score of 1.0, and subsequent results express their relevance relative to it.
This makes scores comparable across different queries and result set sizes, regardless of whether the results were reranked or returned in RRF order.
Next Steps
Section titled “Next Steps”- Query Playground — Temporal query modes that build on hybrid search
- Fact Extraction — Decompose entities into searchable atomic facts
- Agent Memory — Natural language remember/recall powered by hybrid search