Hybrid search
hybrid_searchCombine keyword and semantic search into one fused ranking for queries that are not clearly identifiers or paraphrases. Use when unsure which single search mode fits.
Instructions
Keyword and semantic search fused into one ranking, for a query that is not clearly an identifier or a paraphrase.
Exact identifiers, code symbols, titles or known phrases: keyword_search.
Conceptual or paraphrased questions: semantic_search. Unsure which:
hybrid_search.
Both arms run for the same query and filters in one database snapshot:
the keyword_search ranking and the semantic_search ranking, each taken
to its top 50. They are fused by reciprocal rank fusion over note paths
with equal votes: a note's score is the sum, over the arms that found it,
of 1/(k + rank) (k is the server's HYBRID_RRF_K, shown as rrf_k).
A note outside both top-50 lists is not considered; the header's
arm_depth: keyword n/50, semantic c/50 chunks says when an arm was full.
Fusion helps when the query's kind is unclear, and a single arm can rank
better than it on its own kind of query (an exact identifier, or a pure
paraphrase); use that arm's tool then.
One line per result: a JSON object of the note-controlled fields
{"title","path","tags","preview_kind","preview"} (every value a JSON
string, so note text cannot forge a field), then the server fields:
score, semantic_rank (with similarity) or -, keyword_rank (with
match and matched_in) or -, and explain (the 1/(k+rank) terms
that make the score). preview_kind is snippet (a keyword highlight in
«»), head, chunk (semantic), stale_notice or none, from the arm
that ranked the note better. stale: true and embedding_truncated: true
mean what they mean in semantic_search, and so do the semantic arm's
§ "<heading path>" (#N) / § (top of note) field (read the section
with read_note(path, section="#N")) and the index_transition: line
under the header. A long response drops whole rows
from the end and says how many; a first row that does not fit is cut and
labelled. Call read_note on a path for the full note.
The header always says arms:. arms: both is a fused answer. arms: keyword-only (semantic unavailable: provider_error | provider_input_rejected)
means the embedding provider failed or refused the query: the page is the
keyword arm alone, in keyword order, and semantic_search will fail the
same way until the provider recovers.
rerank=true asks the deployment's reranker to reorder the candidates
this call already fetched; it can add up to the configured timeout. Its
rows are one-line quoted objects followed by server fields (with
rerank_score after them when reranked). The header says
reranked: true or reranked: false (<reason>), and an unreranked page
keeps the unreranked order; reranked: false (not_configured) means
this deployment has no reranker.
Every page's header also says confidence: ok or confidence: low:
low means no note matched all the keyword terms and the closest
semantic candidate is under this deployment's similarity threshold (a
line then suggests keyword_search or get_neighborhood), and ok is
also what a deployment that set no threshold says, so it is not a
quality claim.
Args: query: What you are looking for — words, a phrase or a question. limit: Maximum number of results (default 10, at most 50). folder: Optional folder prefix (e.g. "Projects/"). tags: Optional list of tag names; only notes carrying ALL listed tags match. frontmatter: Optional dict of frontmatter key/value pairs; strict type matching — string "0" does not match integer 0 (e.g. {"status": "active"}). rerank: Reorder the first 50 fused candidates with the deployment's reranker (default false).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| limit | No | ||
| query | Yes | ||
| folder | No | ||
| rerank | No | ||
| frontmatter | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |