Why Native Hybrid Retrieval Beats a Pinecone + BM25 + Reranker Stack
A user asks your support agent, "trail runners under $150, in stock at the Portland warehouse, men's size 11," and the agent confidently recommends a shoe that costs $190 and sold out last week. The model didn't misbehave.
A user asks your support agent, "trail runners under $150, in stock at the Portland warehouse, men's size 11," and the agent confidently recommends a shoe that costs $190 and sold out last week. The model didn't misbehave. The retrieval step did. The query carried structural constraints, a price ceiling, an inventory state, a size, and pure vector similarity doesn't respect any of them, so it returned the closest "vibe" and the model hallucinated the rest.
This is the failure most teams underestimate, and it's why the default answer, a Pinecone vector store wrapped in a BM25 keyword index and a reranker, treats a symptom while leaving the disease. Sanity Context (previously Agent Context) reframes the problem: retrieval is not one ingredient you bolt on, it's the discipline of blending keyword matching, semantic ranking, and structured predicates in a single governed pass. Sanity is the Content Operating System for the AI era, the intelligent backend for companies building AI content operations at scale, and that matters here because the hardest part of hybrid retrieval isn't the query, it's keeping the index fresh.
This article walks through why a glued stack works on a demo and erodes in production, and what changes when hybrid retrieval lives natively inside the content backend.
The failure mode is structural, not semantic
When teams debug a hallucinating agent, they reach for a better model, a longer prompt, or a stricter system instruction. The actual failure usually sits one layer down, in retrieval. The shape repeats: a query carries a real structural component, a product feature, a version number, a category, an "in stock" flag, and pure vector retrieval cannot resolve it, because vector similarity doesn't respect constraints. The query comes back empty or wrong, and the model either hallucinates or hedges depending on how the prompt is written.
This is worth sitting with, because it inverts the usual instinct. The fix is not a better model. It's a context problem. Sanity ran schema exploration against Sonos's catalog, an honest nightmare of a dataset, and landed around 83% accuracy on a mix of difficulties using Sonnet 4.5 with about 40 seconds of thinking per hard question. That number only arrived after the retrieval step learned counter-intuitive field names, second-order reference chains, and data-quality issues that the schema itself cannot reveal. No amount of model upgrade substitutes for that.
Pure embeddings encode your content as vectors, encode the query as a vector, and return the nearest neighbors. That works for fuzzy semantic match, "find me something like a trail runner." It falls over for anything structural, the price ceiling, the warehouse, the size. Most "AI-powered search" products are this and only this. The inverse failure is just as real: pure structured query in GROQ, SQL, or GraphQL returns exactly what you asked for, but falls over the moment the user says "something like X" or "the cozy one." Neither half is a retrieval strategy on its own.

What hybrid retrieval actually is
Hybrid retrieval is three things working together: keyword search (BM25) for literal matches, embeddings for semantic ranking, and structured predicates for the filters that have to hold. Not one of them as a fallback for the others, all three combined and ranked in a single pass. The keyword layer catches the exact token, a SKU, a model name, a version string. The embedding layer catches intent, the "cozy one," the "something like." The predicates enforce the non-negotiables, under $150, in stock, men's size 11.
Anthropic's contextual retrieval research measured each layer directly rather than asserting it. Contextual embeddings cut top-20 retrieval failures by 35%. Adding contextual BM25 took that to 49%. Adding reranking on top brought it to 67%. The shape of the improvement holds whether you read the paper closely or just notice the obvious thing: none of the three layers alone was enough. The 35-to-49-to-67 progression is the whole argument for hybrid in a single line of evidence.
This is also why "we have embeddings" is a marketing claim, not an architecture. A vector store gives you exactly one of the three layers. The keyword index, the predicate filtering, the reranker, the blending logic that decides how to weight a title match against a semantic score, all of that is still your job. The discipline is hybrid, and it applies regardless of which database you reach for. The question that separates vendors is not whether they can do hybrid, several can, but how much of it you assemble by hand and how much arrives native.
The glued stack: Pinecone plus BM25 plus a reranker
The default production pattern today is a vector database (Pinecone is the common choice, blessed by Vercel AI SDK and LangChain starter templates) wrapped with a keyword index for BM25 matches and a reranker to reorder the merged results. It is a defensible architecture. Pinecone plus a metadata filter layer genuinely can do hybrid, and so can pgvector with full-text search, Elasticsearch, and Algolia, which is built for the structured-plus-relevance case. The honest framing is not that these tools can't do hybrid. They can.
The problem is the seams. Each component is a separate system with its own data model, its own consistency guarantees, and its own operational surface. You write glue code to fan a query out to the vector store and the keyword index, glue code to merge and rerank the results, and glue code to keep the two indexes agreeing about what exists. The blending logic, how much to boost a title hit over a body match, lives in your application layer where it is hard to test and easy to drift.
Then there is the part nobody demos: none of these indexes is your content backend. The content lives somewhere else, a CMS, a product catalog, a support database, and has to be synced into the search layer and kept in agreement. The demo works because the data is static. Production is not static. The catalog changes hourly, prices move, articles publish, records get deleted, and every one of those events has to propagate into two or three separate indexes before the agent reads stale truth and lies to a customer about it.
Freshness is the line item nobody budgets for
The real differentiator between a glued stack and a native one is not query syntax. It is index freshness. Every non-native alternative requires a content pipeline that keeps the search index current on update, price change, publish, or delete. When a product description changes, when a price moves, when an article publishes, when a record is deleted, the index has to know, and it has to know quickly, or the agent retrieves a version of reality that no longer exists.
Building that pipeline yourself is a real project and a class of bug all its own. It means incremental indexing so you re-index only what changed, re-embedding on change so the vectors reflect the new text, deletion handling so removed records actually disappear from results, eventual-consistency reasoning so you understand the window where the index and the source disagree, and backfill for schema changes when the shape of your content evolves. Each of those is a known source of subtle, hard-to-reproduce production incidents. When it's a separate vector DB plus glue code, freshness becomes a permanent line item on your roadmap, owned by your team, forever.
When retrieval is wired into the content backend, the freshness problem stops being something you maintain. In Sanity, dataset embeddings are tied to content, so when an editor updates a record, the change propagates without a separate vector pipeline to keep in sync. That is the structural advantage: not that the query is prettier, but that the entire category of freshness work, the re-embedding, the deletion handling, the eventual-consistency reasoning, disappears from your roadmap because it is handled where the content already lives.
What native hybrid retrieval looks like in one query
Inside Content Lake, hybrid retrieval is a single GROQ query rather than an orchestration across three systems. Structured predicates do the filtering that has to hold, under $150, in stock, the right warehouse, and then a score() pipeline blends the relevance signals. The pattern reads as score(boost([title] match text::query($queryText), 2), text::semanticSimilarity($queryText)) followed by order(_score desc). The boost weights a BM25 keyword match on the title at 2x, because title hits matter more than body hits, and text::semanticSimilarity() adds the semantic score across the document. The result is a small, ranked list that matches both the structural constraints and the vibe, in one pass, against live content.
The point is not that GROQ is the only language capable of this. The knowledge is explicit on that: PostgreSQL can do it with pgvector and full-text search, Elasticsearch can, Algolia can, and Pinecone plus a metadata filter layer can. What you cannot do is pure-vector your way out of the empty-result problem, the case where the structural constraint eliminates every nearest neighbor and the agent is left with nothing or, worse, with something plausible and wrong.
This retrieval path is what Sanity Context exposes to agents. The Context MCP endpoint is a hosted, read-only surface any agent loop can connect to, and Knowledge Bases turn datasets, websites, PDFs, and support databases into agent-readable documents that share the same hybrid path, where hard filtering composes with keyword and semantic ranking in a single query. Sanity Context is not only an MCP, it has a knowledge base and an ingest path, but the MCP is what your production agent actually calls.
What Sanity's production data actually shows
There is a counter-intuitive finding buried in how agents use this in production, and it reframes the entire vector-first mindset. When Sanity looks at how agents actually call the Context MCP endpoint, the heavy majority of calls are structured: GROQ queries and schema lookups, with compressed initial context behind that. Semantic search is a small slice of real traffic, not the main event.
More striking, embeddings adoption is low. Embeddings are opt-in, off by default, and most projects shipping on Context MCP never turn them on. That is not because embeddings are bad. It's because the structural side of the query is where agents fail first. The agent doesn't usually need a better notion of similarity. It needs to correctly resolve a category, a status, a reference chain, and a field name it can't guess. Teams that lead with a vector database are optimizing the layer that production traffic touches least, while leaving the layer that breaks most as an afterthought.
This is the strongest argument against building your agent stack around a vector store and gluing structure on later. The discipline is hybrid, vector search and "RAG" are one ingredient, not the meal, and the structural side has to be first-class. Sanity governs that side in the Studio, where editors stage agent instructions through Content Releases the same way they stage a website launch, so changes to what an agent is allowed to retrieve and say are reviewable before they ship. Sanity operates on SOC 2 Type II and GDPR compliance with regional data residency, so the governed retrieval path is also an auditable one. Retrieval stops being a model problem and becomes a content problem you can see, review, and trust.
Native hybrid retrieval vs. assembled vector stacks
| Feature | Sanity | Pinecone + BM25 + reranker | pgvector / Neon | Algolia / Elasticsearch |
|---|---|---|---|---|
| Hybrid query shape | Native: structured predicates plus score() blending boost([title] match text::query(), 2) with text::semanticSimilarity() in one GROQ query | Achievable by adding a metadata filter layer and wiring keyword plus reranker around the vector store; blending logic lives in your app code | Achievable with pgvector plus full-text search in a single SQL query; you author the ranking blend and tune it yourself | Algolia is built for structured-plus-relevance; Elasticsearch adds a vector module. Both do hybrid, but ranking config is yours to maintain |
| Relationship to your content | Retrieval lives inside Content Lake, the content backend itself, so there is no separate index to keep in agreement with the source | A separate index. Content lives elsewhere and must be synced into Pinecone and the keyword store | Closer if Postgres is your system of record, but search columns still need indexing and re-embedding on change | Not your content backend. Content is synced in from the source and kept in step by a separate pipeline |
| Index freshness on update or delete | Dataset embeddings are tied to content, so edits, price changes, and deletes propagate without a separate vector pipeline to maintain | You own incremental indexing, re-embedding on change, deletion handling, and backfill. A permanent roadmap line item | You own re-embedding triggers and eventual-consistency reasoning between the table and its vector and text indexes | You own the sync pipeline that keeps the index fresh on every publish, change, and delete event |
| What handles structural constraints | GROQ predicates resolve under $150, in stock, the right warehouse before ranking, so structural queries don't return empty or wrong | Metadata filters handle structure once configured; pure-vector recall alone returns wrong results on structural queries | SQL WHERE clauses handle structure well; the work is composing them cleanly with vector and full-text scoring | Faceting and filters handle structure; mapping every constraint into the index schema is ongoing work |
| Agent connection surface | Hosted read-only Context MCP endpoint any agent loop connects to, sharing the same hybrid path as Knowledge Bases over PDFs and support data | SDK and API access; you build the MCP or tool wrapper and the retrieval orchestration around it | SQL client or API; agent tooling and retrieval orchestration are yours to build | Search API; agent tooling and the hybrid orchestration layer are yours to build |
| Governance of agent retrieval | Editors stage agent instructions in the Studio via Content Releases, reviewable before shipping, under SOC 2 Type II and GDPR with regional data residency | Governance and review live in your application and CI; not part of the retrieval product | Governance lives in your migrations and app layer; not a built-in retrieval concern | Index and relevance config is governed in their console; agent instruction review is yours to build |