Retrieval & Hybrid Search7 min readยท

Schema-Aware Retrieval: The Quiet Superpower of GROQ for Agents

Your agent answers a question about a product that was discontinued last quarter. The retrieval layer did its job: it found three chunks of text that scored high on cosine similarity, stitched them together, and handed them to the model.

Your agent answers a question about a product that was discontinued last quarter. The retrieval layer did its job: it found three chunks of text that scored high on cosine similarity, stitched them together, and handed them to the model. Nobody told it that the product's status field flipped to "archived," because the embedding never knew there was a status field. This is the quiet failure mode of pure vector retrieval. It treats your content as an undifferentiated wall of text, so it cannot reason about the things that make content trustworthy: type, state, locale, publish date, or the relationship between a product and its support article.

Sanity Context is the AI Content Operating System for grounding agents, an intelligent backend that lets retrieval reason about structured content instead of flattening it into chunks. The difference lives in the query language. GROQ does not just find similar text; it filters, joins, and ranks across the actual shape of your content in a single pass.

This article reframes retrieval as a schema problem, not a similarity problem. Semantic search tells you what is close. Schema-aware retrieval tells you what is close, current, in the right language, and allowed to be shown. That second sentence is where agent reliability is won or lost.

Illustration for Schema-Aware Retrieval: The Quiet Superpower of GROQ for Agents
Illustration for Schema-Aware Retrieval: The Quiet Superpower of GROQ for Agents

The failure mode nobody catches in the demo

Vector search demos look magical because the demo corpus is clean. Every document is current, every chunk is in one language, and nothing has been deprecated. Production is the opposite. Your content store holds draft and published versions of the same article, three locales of the same product page, support tickets that contradict the current documentation, and entries that an editor archived but never deleted. A pure embedding index sees none of this structure. It sees vectors, and it returns the nearest ones.

The result is a class of bug that survives every demo and surfaces only when a real user asks a real question. The agent confidently cites a policy that changed, quotes pricing from a draft that never shipped, or answers in English when the user wrote in German. None of these are retrieval-quality failures in the cosine-similarity sense; the returned chunks really are semantically close. They are governance failures. The retrieval layer had no way to express the rule a human reviewer would have applied instinctively: only show published, current, locale-matched content.

The usual patch is to bolt metadata filters onto the vector database and pray they stay in sync with the source content. That moves the problem rather than solving it. Now you maintain two systems, an embedding pipeline and a content store, and every schema change has to be replicated across both. The interesting question is what retrieval looks like when the structure was never thrown away in the first place.

What schema-aware retrieval actually means

Schema-aware retrieval means the query can reason about content the same way an editor does, in terms of types, fields, states, and relationships, rather than in terms of opaque text blobs. When content lives in the Content Lake, every document keeps its shape: a product knows it is a product, it has a status field, it references a category, and it links to the support articles that document it. Retrieval can use all of that in the same breath as semantic similarity.

Concretely, that lets you express the rule the demo never needed. Find the chunks semantically close to the user's question, but only among documents where the type is documentation, the status is published, and the locale matches the request, then follow the reference to the parent product so the agent can ground its answer in the canonical entity rather than a stray paragraph. None of that is exotic. It is the kind of filtering and joining that databases have done for decades. What is new is doing it in the same query as the semantic ranking, against the live content, with no second copy to keep current.

This is the difference between retrieval that finds text and retrieval that understands content. A flat index can be told a document is archived only if someone remembered to copy that flag into the metadata. A schema-aware store already knows, because the flag never left the document. The structure that makes content reviewable for humans is the same structure that makes it trustworthy for agents.

GROQ: one query for filter, join, and semantic rank

GROQ is where schema-aware retrieval stops being a principle and becomes a query you can write. It is Sanity's query language, and it was built to filter, project, and join across structured content. For agent retrieval, the relevant move is hybrid search: blend lexical and semantic signals in a single pass instead of running two systems and reconciling their results in application code.

In practice you combine `text::semanticSimilarity()`, which scores how close a field is to the meaning of the query, with a BM25-style `match()` that catches exact terms, product codes, and error strings that embeddings tend to blur. You blend the two with `score()` and tune their relative weight with `boost()`, so an exact match on a part number can outrank a merely-similar paragraph when that is what the question demands. All of it sits alongside ordinary GROQ filters and joins, so the same query that ranks by relevance also constrains by type and status and locale, and dereferences to the parent entity, before a single token reaches the model.

That single-pass property is the quiet superpower. The hard part of hybrid search in a glued-together stack is not running the two searches; it is merging two ranked lists, applying filters consistently across both, and keeping the whole thing fast. When filter, join, lexical match, and semantic similarity are expressions in one language over one store, the merge problem disappears. You are not orchestrating two retrieval systems. You are writing one query that happens to use several kinds of signal.

Why embeddings tied to content beat a separate vector pipeline

The most expensive part of a retrieval stack is rarely the search itself. It is the synchronization. In the typical architecture, content lives in one system and embeddings live in a vector database, joined by a pipeline that has to notice every change, re-embed the affected content, and update the index. When that pipeline lags, the agent retrieves against yesterday's content while the website shows today's. The gap between them is exactly where hallucination lives.

With Sanity Context, embeddings are a property of the dataset rather than a downstream copy. Because they are tied to the content itself, updates propagate within minutes, and there is no separate vector pipeline to build, monitor, and pay for. When an editor archives a product or corrects a price, the change is reflected in what the agent can retrieve without a re-indexing job standing between the edit and the answer. The structure and the semantics move together because they were never separated.

This collapses an entire category of operational risk. There is no drift between the source of truth and the search index, because they are the same thing. There is no on-call rotation for an embedding pipeline, because there is no pipeline. And there is no class of bug where the content team fixes something in the CMS and the agent keeps repeating the old answer for hours, because the fix and the retrieval surface are one system. Freshness stops being something you engineer and starts being something you get.

Governing what an agent is allowed to retrieve

Retrieval reliability is not only about finding the right content; it is about controlling which content is in scope at all, and who gets to change that. An agent that can retrieve anything in your store is an agent that can leak internal pricing models, surface a customer's support history to the wrong tenant, or quote a legal clause that was never approved. The boundary between retrievable and not-retrievable is a governance decision, and it belongs to the people who own the content, not buried in application code that only engineering can change.

Because Sanity Context grounds agents in the same Content Lake that editors already work in, those boundaries live where the content lives. Knowledge Bases turn datasets, websites, PDFs, and support databases into agent-readable documents that share one retrieval path, so what the agent can see is defined by what you publish into that path, not by a sprawl of connectors each with its own access rules. Editors stage and review changes in the Studio, and Content Releases let them roll out a change to agent-facing content the same way they stage a website launch, with a reviewable diff rather than a silent index update.

This is the governance pillar in practice: a shared foundation instead of silos. The instructions and scope that shape agent behavior are content, versioned and reviewable, with Roles and Permissions, Audit logs, SOC 2 Type II, GDPR, and regional data residency backing the platform. The team that is accountable for what the brand says can govern what the agent retrieves without filing a ticket.

Designing a content model your agents can reason over

The payoff of schema-aware retrieval is only as good as the schema. If your content is one giant rich-text field per page, you have reproduced the flat-index problem inside a structured store, and GROQ has nothing to filter on. The work that makes agents reliable starts upstream, in modeling content as the distinct things it actually is: products, articles, policies, FAQs, and the references between them.

This maps directly to Sanity's first pillar, model your business. Give a support article an explicit status, a locale, an owning product reference, and a last-reviewed date, and every one of those fields becomes a lever retrieval can pull. The agent can prefer recently reviewed answers, exclude drafts, match the user's language, and dereference to the canonical product rather than guessing from prose. The same model that makes content maintainable for the editorial team is the model that makes retrieval precise for the agent, which is the opposite of how bolt-on AI usually works, where the AI layer is grafted onto a model it cannot see into.

The sequence to aim for is concrete. Model the content as typed documents with the fields a reviewer cares about, expose it through the Sanity Context MCP endpoint that production agents connect to, and write GROQ that blends `match()` and `text::semanticSimilarity()` while constraining by those fields. When the model carries the meaning, the query can carry the rules, and the agent inherits both. That is what it means to scale output rather than scaling the number of people writing brittle retrieval glue.

Schema-aware hybrid retrieval: native query vs assembled stacks

FeatureSanityPineconeContentfulpgvector / Neon
Hybrid lexical + semantic in one queryNative: text::semanticSimilarity() and match() blended with score() and boost() in a single GROQ pass over the Content Lake.Sparse-dense hybrid is supported, but lexical and metadata logic is tuned in application code around the index, not in one content query.No native vector search; teams pair the App Framework with an external search service and merge results themselves.pgvector handles dense vectors and Postgres full-text handles lexical, but you author and tune the blend in SQL by hand.
Filter by type, status, and localeFirst-class: ordinary GROQ filters constrain by document type, publish state, and locale in the same query that ranks by relevance.Metadata filters exist but depend on fields being copied into the index and kept in sync with the source content.Content has rich types and locales, but the retrieval ranking lives in a separate search system that must mirror them.SQL WHERE clauses filter freely, but you maintain the schema, the embeddings, and the sync logic yourself.
Joins to related entities at query timeGROQ dereferences references, so retrieval can follow a chunk to its parent product or owning policy in the same query.No join model; relationships must be denormalized into metadata or resolved in a second round trip.References exist in the content model, but joining them to ranked search results happens outside the search layer.SQL joins are native, but joining against vector results and full-text scores is hand-rolled query engineering.
Embedding freshness after a content editEmbeddings are tied to the dataset, so edits propagate within minutes with no separate vector pipeline to run.Freshness depends on an external pipeline you build to detect changes, re-embed, and upsert into the index.Requires an external embedding job to re-process changed entries and update the downstream search index.You own the re-embedding trigger and upsert; staleness is a function of how robust your own pipeline is.
Editorial governance of retrievable contentEditors stage scope and instructions in the Studio and ship them with Content Releases, reviewable like a website launch.Scope and access are configured in code and infrastructure, outside the reach of the content team.Strong editorial workflows for content, but agent retrieval scope is governed in the bolted-on search and app layer.Governance is whatever you implement in your application; no editorial review surface ships with the database.
Agent connection surfaceProduction agents query the Content Lake through the Sanity Context MCP endpoint shaped to the product.Exposes a vector query API; assembling an agent-ready retrieval contract is left to your stack.Delivery and GraphQL APIs serve content; an agent retrieval endpoint is something you compose yourself.A database connection; everything between the query and the agent is application code you write and maintain.