---
title: "Search by meaning and by words · Agent Wranglers"
url: https://agentwranglers.se/playbook/ai-features/retrieval/hybrid-search
updated: 2026-10-20
licence: "All rights reserved"
---

# Search by meaning and by words

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Retrieval](https://agentwranglers.se/playbook/ai-features/retrieval)
- Rule: Combine a keyword search and a vector search, and merge the two result lists, for example with reciprocal rank fusion.
- How: Vector search finds text with the same meaning in other words. Keyword search, such as BM25, finds exact product names, codes and error messages that vectors often miss. Run both, take about 20 results from each, and merge them by rank. Reciprocal rank fusion scores each result as the sum of 1 divided by 60 plus its rank in each list. Optionally rerank the top results with a reranking model. Keep the merge only if it scores better in the [retrieval evals](https://agentwranglers.se/playbook/ai-features/retrieval/retrieval-evals).
- Check: The retrieval eval set includes questions with exact product codes. Hybrid search scores at least as well as vector search alone on the whole set.

Example:

```ts
const RRF_K = 60;

export function reciprocalRankFusion(...rankings: string[][]): string[] {
  const scores = new Map<string, number>();
  for (const ranking of rankings) ranking.forEach((id, rank) => scores.set(id, (scores.get(id) ?? 0) + 1 / (RRF_K + rank + 1)));
  return [...scores.entries()].sort((a, b) => b[1] - a[1]).map(([id]) => id);
}
```

```python
RRF_K = 60

def reciprocal_rank_fusion(*rankings: list[str]) -> list[str]:
    scores: dict[str, float] = {}
    for ranking in rankings:
        for rank, chunk_id in enumerate(ranking, start=1):
            scores[chunk_id] = scores.get(chunk_id, 0) + 1 / (RRF_K + rank)
    return sorted(scores, key=scores.get, reverse=True)
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers ai features playbook: https://agentwranglers.se/playbook/ai-features/retrieval/hybrid-search`.

- Previous: [Record the embedding model with every vector](https://agentwranglers.se/playbook/ai-features/retrieval/embedding-model-version)
- Next: [Measure retrieval on its own](https://agentwranglers.se/playbook/ai-features/retrieval/retrieval-evals)
- [Retrieval](https://agentwranglers.se/playbook/ai-features/retrieval)
