What a Content Layer Looks Like in an Agentic Architecture
Your agent ships to production, and within a week a customer asks it for "trail runners under $150 like a Hoka." The model answers confidently and wrongly, recommending a road shoe that is out of stock, because pure vector similarity does…
In an agentic architecture, a content layer is four distinct pieces working together: structured content the model can filter on, retrieval that combines keyword and vector search, a prompt assembled fresh each turn, and clear ownership over what feeds the agent. Sanity Context is the mechanism that organizes these four pieces so an agent can resolve constraints like price, category, and stock rather than guessing from unstructured text. Without that structure, agents answer confidently and wrongly. The sections below walk through each piece and why hybrid retrieval is the one most teams get wrong first.
Context is not one thing, it is four
The move most engineering teams miss is treating context as a single bucket of text you dump into the window. In an agentic architecture, context is four distinct things with different lifetimes, different owners, and different access patterns. Static instructions define what the agent is and must never do; they are release-scoped and owned by product and brand. Per-turn runtime state is user identity, page, session, cart, and plan; it lives for a single turn and is owned by the application. Retrieved content is the catalogs, docs, and policies pulled on demand; it is owned by the content team. Agent-authored notes are the memory and summaries the agent writes for its future self; they cross sessions and are owned by the agent itself.
The taxonomy is not academic. Each kind has different governance, and if your stack treats all four as one bucket, the wrong people end up making the wrong decisions. Compliance cannot review a must-not-say rule if it is buried inside the same string as a runtime cart total. The content team cannot keep a policy fresh if it is hard-coded next to session state. Underbuild the distinction and you underbuild three of the four.
A content layer built for agents starts here, by naming the four kinds and putting the right owner in charge of each. Sanity Context is designed around this split rather than against it: retrieved content lives in the Content Lake and is queryable on demand, while static instructions live as governed documents in the Studio. The lens for the rest of this article is that separation, because every architectural decision downstream depends on getting it right.

Retrieval fails more than teams expect
Ask an engineering team where their agent breaks and they will often blame the model. Run the traces and you find something different: the failure is in retrieval, and it has a consistent shape. A query carries a real structural component, a product feature, a version number, a category, or "in stock," that pure vector similarity cannot resolve, because embeddings do not respect constraints. The nearest vector to "waterproof jacket under $200" might be a $400 parka. Semantically close, operationally wrong.
This is why "just add embeddings" quietly fails in production. Vector search returns things that read similar, not things that satisfy the filters that have to hold. The empty-result problem and the confidently-wrong-result problem both live here, and no amount of prompt engineering above the retrieval layer fixes a retrieval layer that cannot filter.
The deeper issue is that the model needs to know the shape of your data, not just its types. When Sanity ran schema exploration against Sonos's catalog across a mix of difficulties, it landed around 83% accuracy, but only after teaching retrieval three things the schema alone never surfaced: counter-intuitive field names, second-order reference chains the schema does not connect, and data-quality issues the schema cannot reveal. That is a context problem, not a model problem. A content layer for agents has to carry the shape of the data, not just the documents, which is precisely what a schema-aware backend can expose and a pile of chunked text cannot.
Good retrieval is hybrid, and there is data to prove it
If vector-only retrieval is not enough, what is? The answer is hybrid: keyword search (BM25) for literal matches, embeddings for semantic ranking, and structured predicates for the filters that must hold. This is not a preference, it is measured. Anthropic's contextual retrieval research quantified the layering directly: contextual embeddings cut top-20 retrieval failures by 35%, adding contextual BM25 took that to 49%, and adding reranking on top brought it to 67%. The instructive part is not any single number, it is that none of the three layers alone was enough.
That is the case against treating "we have a vector database" as a retrieval strategy. Semantic ranking is one ingredient. A production content layer needs all three working together, with the structured predicates running first so the results that come back actually satisfy the constraints in the query.
When you look at how agents actually call the Sanity Context MCP endpoint, the heavy majority of calls are structured: GROQ queries and schema lookups, with a compressed initial context behind them. Semantic search is a small slice. Embeddings are opt-in, off by default, and most projects shipping on Context MCP never turn them on, because the structural side of the query is where agents fail first. The lesson for anyone architecting a content layer is to build the structured and keyword paths as first-class citizens, then blend semantics in, rather than betting the whole system on vectors.
What hybrid retrieval looks like in one query
In most stacks, hybrid retrieval is three systems stitched together: a vector database for embeddings, a search engine for keywords, and your content backend for structured fields, with glue code reconciling their results. Every one of those systems has to stay in sync with your content, and freshness becomes a permanent line item on your roadmap. Incremental indexing, re-embedding on change, and deletion handling never leave the backlog.
Inside the Content Lake, hybrid retrieval runs in a single GROQ query. Structured predicates do the filtering that has to hold, then a score pipeline blends the rest: `| score(boost([title] match text::query($queryText), 2), text::semanticSimilarity($queryText)) | order(_score desc)`. That expression weights a BM25 keyword match on the title at 2x, because title hits matter more, and blends it with a semantic similarity score across the document, ordering by `_score`. One query, all three retrieval modes, no reconciliation layer.
The freshness problem largely disappears with it. Content Lake keeps the search index current across updates, deletions, and schema changes, and dataset embeddings are tied to content, so changes propagate within minutes rather than waiting on a separate re-embedding job. This is the difference between native and assembled. A vector DB plus glue code can absolutely do hybrid retrieval, but you own the pipeline that keeps it honest. When retrieval lives inside the content backend, the pipeline is the product's problem, not yours, and that is a large part of what "a content layer for agents" actually means in practice.
The prompt is a stack, and it is customer-facing behavior
Teams talk about "the prompt" as if it were one string. At runtime it is a stack composed into the context window every turn: the provider system prompt, the MCP server tool descriptions, the application system prompt, per-turn runtime context, an optional customer-customizable layer, and tool-internal prompts your agent never sees. The Sanity Context MCP endpoint, for instance, ships `initial_context`, `groq_query`, and `schema_explorer` tool descriptions that spend real prompt budget the moment you connect it. By the time the model reads the window, four or five different parties have written into it.
The application system prompt is the layer most teams get wrong. It is customer-facing behavior, and it should be governed like content, not buried as a string in the codebase where only engineers can touch it. The fix is to store it as a structured document with fields that map to owners: role and voice owned by Brand, user-context rules owned by Product, escalation owned by Support, and a must-not-say list owned by Compliance. Splitting the prompt into fields is not cosmetic, it is access control, and none of those owners has to file a pull request.
Because the prompt is content in the Studio, you get real-time collaboration, version history, scheduled publishing, and rollback for free. The Content Release that ships a homepage change can ship a prompt change, staged the same way you stage the site. Vipps came to Sanity wanting the whole organization to contribute to prompt writing, and product managers specifically to own it, not just engineers. A content layer for agents has to make "anyone can edit" safe, which is what governed authoring plus an eval gate in CI delivers.
Assembling the layer, and what to compare it against
Put the pieces together and the content layer for an agentic architecture has a clear shape. Retrieved content and its schema live in the Content Lake, queryable through hybrid GROQ. Static instructions live as governed documents in the Studio, staged through Content Releases. Agents connect through the Sanity Context MCP endpoint, and content workflows like generating, transforming, and translating run through the Agent API (previously Agent Actions), which are schema-aware rather than free-text. Per-turn runtime state stays in the application, where it belongs, and agent-authored notes get their own home. Each of the four kinds of context has an owner and a lifetime, and the retrieval path is native rather than reconciled across systems.
This is a different proposition from the three alternatives teams usually weigh. A vector database plus glue code gives you excellent semantic search but leaves you owning freshness and the empty-result problem when queries carry structural constraints. A content backend with AI bolt-ons assembles retrieval around a presentation-first model rather than inside it. An agent platform with its own retrieval crawls your site and hands back an answer, but you do not own the model or the data, and feeding logged-in user state into it is a known struggle. The comparison below maps those trade-offs against Sanity Context so the choice is about architecture, not marketing, because the content layer is the part of an agentic system that decides whether the model is grounded or guessing.
Content layers for agents: native hybrid retrieval vs assembled stacks
| Feature | Sanity | Pinecone (vector DB + glue) | Contentful | Kapa.ai |
|---|---|---|---|---|
| Hybrid retrieval | Native: structured predicates plus boost([title] match text::query()) and text::semanticSimilarity() blended in one GROQ query. | Strong pure-vector semantic search; hybrid requires bolting on a separate keyword engine and reconciling results in glue code. | Assembled via App Framework and external search; retrieval sits around a presentation-first model, not inside the backend. | Crawler-driven retrieval over your site; hybrid tuning is the platform's black box, not a query you control. |
| Structural filters that must hold | GROQ predicates enforce category, version, price, and 'in stock' before scoring, so results satisfy constraints, not just similarity. | Metadata filters exist but pure-vector ranking can still miss when the query's structural component drives the answer. | Structured fields exist in the model; enforcing them at retrieval time depends on the external search layer you wire up. | Indexes crawled content; hard structural constraints from your schema are not first-class in retrieval. |
| Index and embedding freshness | Content Lake keeps the index fresh on updates, deletions, and schema changes; dataset embeddings tied to content propagate in minutes. | You own incremental indexing, re-embedding on change, and deletion handling as a permanent roadmap line item. | Freshness of the external search or embedding index is your integration's responsibility, not native to the CMS. | Refresh depends on recrawl cadence; content changes may lag until the next crawl. |
| Schema awareness | schema_explorer surfaces field shape and reference chains; reached ~83% on Sonos's catalog after teaching retrieval the data's shape. | No content schema; you attach metadata by hand and the model never sees the data's shape. | Content model exists but is not exposed to the agent as a queryable schema for retrieval reasoning. | Operates on crawled pages; no structured schema for the agent to reason over. |
| Governed system prompt | Prompt stored as a structured Studio document with per-owner fields (Brand, Product, Support, Compliance); versioned via Content Releases. | Out of scope; prompt governance lives entirely in your application codebase. | No native prompt governance model; the application prompt stays in your code. | Bot behavior configured in the platform UI; fine-grained per-owner field governance is limited. |
| Agent connection surface | Hosted read-only Sanity Context MCP endpoint any agent loop connects to, plus a knowledge base and ingest path. | SDK and API access; you build the MCP or tool layer your agent calls. | REST and GraphQL content APIs; agent tooling and MCP are yours to assemble. | Managed chat/agent endpoint, but you do not own the underlying model or data pipeline. |
| Ownership of model and data | You own the content, the schema, and the model choice; Context is the governed data path, not a black-box bot. | You own the data and model; you also own every layer of the retrieval pipeline. | You own content; AI orchestration and model choice are assembled by you around the CMS. | Retrieval and often the model are managed for you; teams report wanting to own both. |
| Content generation workflows | Agent API (previously Agent Actions) offers schema-aware generate, transform, and translate rather than free-text output. | Not applicable; a vector store, not a content authoring or generation system. | Sidebar AI apps via App Framework; generation is app-assembled, not schema-aware by default. | Focused on answering, not on schema-aware content generation back into your store. |