Choosing a ranking mode
The rule is short: if a model wrote the query, use hybrid. If a human did, usually keyword.
| Mode | Matches on | Best when |
|---|---|---|
keyword | Words, weighted by how distinctive they are (BM25). | The query contains the words the article will contain. |
semantic | Meaning, via embeddings. | The query describes a concept the article expresses differently. |
hybrid | Both, combined. | You do not know which of the two applies — which is most of the time. |
Why "who wrote it" is the deciding factor
A human searching for news types what they expect to read: "Fed rate decision", "ASML export licence". Those words are in the articles, and keyword ranking will find them precisely — including the distinction between "ASML" and "ASM International", which an embedding may blur.
A model writing a query paraphrases. Asked about interest rates it will write "central bank monetary tightening", because that is the concept. No article says that. Keyword ranking returns the handful of think-pieces that happen to use the phrase and misses the actual news, and the model concludes there is no coverage.
Hybrid covers both: the lexical half still rewards an exact match on "Fed", and the semantic half bridges the paraphrase. That is why the MCP tool defaults to it — a model is on the other end by construction.
What changes in the response
total_relation. Keyword queries return exact: the inverted index counted every match.
Semantic and hybrid return approximate, because nearest-neighbour retrieval ranks a bounded candidate
set — so total is how many candidates were considered, not how many exist.
Practically: do not render "About 4,132 results" for a hybrid query. If you need a real count, run the same filters
as a keyword query and read that total. More on totals.
What does not change
Filters. language, country, topic, time range and signal constraints are
exact matches on indexed attributes and behave identically in every mode. So the right move for a vague query is
not to add words to it — it is to add filters and let ranking work on a smaller, cleaner set.
# Worse: more words make ranking fuzzier.
q=semiconductor export controls Netherlands ASML August 2026
# Better: the concept in q, the facts as filters.
q=semiconductor export controls
&mode=hybrid
&organization=asml
&publisher_country=NL
&from=2026-08-01 Testing it on your own corpus slice
Run the same query three ways and compare the top few titles. It takes a minute and settles the question:
for mode in keyword semantic hybrid; do
echo "== $mode"
curl -s -G "https://api.unzoi.com/search" -H "x-api-key: $UNZOI_KEY" \
--data-urlencode "q=central bank monetary tightening" \
--data-urlencode "mode=$mode" \
--data-urlencode "limit=5" | jq -r '.results[].title'
done Clustering is a separate choice
/stories takes the same mode. Ranking decides what matches;
clustering decides how the matches are grouped. Hybrid ranking plus clustering is usually the right combination for
an agent: it finds the coverage despite the paraphrase, then returns one row per event.