How to Use Embeddings to Power Semantic Search Inside Your CMS
Your marketing team searches the CMS for "how to reduce cart abandonment" and gets nothing, because the only article on the topic is titled "Recovering lost checkouts." Keyword search matched zero words, so it returned zero results, even…
Your marketing team searches the CMS for "how to reduce cart abandonment" and gets nothing, because the only article on the topic is titled "Recovering lost checkouts." Keyword search matched zero words, so it returned zero results, even though the perfect answer was sitting three folders away. Multiply that failure across every editor, every support agent, and every LLM your team is trying to ground in your own content, and you have a retrieval problem that quietly caps how useful your content is.
Semantic search fixes this by matching on meaning rather than exact words, and it does so using embeddings: numeric representations of text that place "cart abandonment" and "lost checkouts" close together in vector space. The hard part is not the math. It is keeping those embeddings fresh, governed, and tied to the content they describe, so search stays accurate as editors publish and revise. Sanity is the AI-native Content Operating System, an intelligent backend where embeddings live next to the content they index rather than in a bolted-on vector store you have to sync by hand.
This guide walks through how embeddings power semantic search, where naive setups break down at enterprise scale, and how to keep retrieval trustworthy for both humans and the LLM workflows reading from the same source.
What embeddings actually do, and why keyword search runs out of road
An embedding is a vector, a list of numbers, that captures the meaning of a piece of text so that similar meanings land near each other in a high-dimensional space. Ask for documents near the vector for "reduce cart abandonment" and you get back "recovering lost checkouts," "win-back email sequences," and "exit-intent offers," none of which share a keyword with the query. That is the whole promise of semantic search: retrieval by intent instead of by literal string match.
Keyword search, by contrast, is brittle in exactly the ways enterprise content is messy. Synonyms, acronyms, regional spellings, and product rebrands all break exact matching. A support agent searching "can't log in" misses the article titled "authentication troubleshooting." A localization team searching in one language misses assets tagged in another. As a content library grows past a few hundred documents, the gap between what people mean and what they type becomes the dominant cause of failed searches, and every failed search is either a duplicate document someone creates or a question that goes unanswered.
This maps directly to the first pillar of a modern content platform: model your business. Embeddings are only as good as the structured content underneath them. When your CMS stores richly modeled documents rather than flat HTML blobs, you can embed the fields that carry meaning, the body, the summary, the tags, and skip the boilerplate. Sanity's structured content model gives semantic search clean, field-level material to work with instead of scraping rendered pages after the fact.

The freshness problem: why bolt-on vector databases drift
The most common semantic search architecture is also the most fragile: content lives in the CMS, and a separate vector database, Pinecone or a pgvector table, holds the embeddings. A pipeline listens for content changes, re-embeds the affected documents, and upserts the new vectors. On a whiteboard this looks clean. In production it drifts.
Every moving part is a place for staleness to creep in. An editor publishes a correction, but the webhook that triggers re-embedding fails silently, so search keeps surfacing the old claim. A bulk import lands 4,000 documents and the embedding job times out halfway through, leaving the index half-populated with no obvious signal that anything is wrong. A schema change adds a new field nobody remembered to include in the embedding text. The vector store and the content are two sources of truth, and keeping two sources of truth in sync is a standing operational tax that grows with every document and every team touching the content.
This is the pillar of automate everything, and it is where owning both layers pays off. Sanity's Embeddings Index API and dataset embeddings tie the vectors to the content in the Content Lake, so when a document changes the embedding is the platform's responsibility, not a pipeline you babysit. Freshness stops being a cron job you hope succeeded and becomes a property of the system. There is no separate store to reconcile, because the embeddings and the content are governed by the same platform.
Two sources of truth is the real cost
Chunking and structure: why Portable Text beats scraping rendered pages
Embedding models have a context limit, so long documents get split into chunks before they are embedded. How you chunk determines retrieval quality. Split mid-sentence or mid-concept and you get vectors that represent fragments of ideas, which return confident but subtly wrong matches. Chunk along the natural structure of the document, by section, by heading, by list, and each vector represents a coherent unit of meaning.
This is exactly where content stored as rendered HTML lets you down. If your only representation of an article is the published web page, your chunker has to reverse-engineer structure from markup, guessing where one idea ends and the next begins. Rebranded components, inconsistent heading levels, and injected marketing widgets all corrupt the input before the embedding model ever sees it.
Structured rich text avoids the guesswork. Sanity stores rich content as Portable Text, where headings, blocks, annotations, and marks are preserved as data rather than flattened into a string. That structure survives chunking: you can embed at the block or section level, keep the metadata about what each chunk is, and reassemble context accurately at retrieval time. For LLM workflows this matters twice over, because the same structure that makes chunking clean also lets a model cite the exact block it drew an answer from. Semantic search and LLM grounding read from the same structured source, so improving one improves the other rather than forcing you to maintain two parallel pipelines.
Blending semantic and keyword search in a single query
Pure semantic search has a failure mode of its own: it is fuzzy where you sometimes need precision. Search for a specific SKU, a part number, or an exact error code, and vector similarity can float in near-miss neighbors that share a topic but not the exact identifier. The mature answer is hybrid retrieval, combining semantic similarity with traditional keyword and filter matching, so you get meaning-aware recall without losing exact-match precision.
In most architectures, hybrid search means orchestrating two systems: query the vector database for semantic neighbors, query the CMS or a separate search index for keyword matches, then merge and re-rank the two result sets in application code. That merge logic is fiddly, it is where relevance bugs hide, and it is another component to own.
Sanity collapses this into the query layer. Because embeddings live alongside content in the Content Lake, a single GROQ query can blend semantic similarity with exact filters, references, and field conditions. You can ask for documents semantically near a phrase, then constrain to a locale, a content type, a publish status, and a date range in the same expression, no result-set merging in application code. This is the model-your-business and power-anything pillars working together: the structure you defined becomes the filter surface, and one query serves the website, the internal search box, and the LLM retrieval step alike. One place to reason about relevance instead of three.
Governance: keeping semantic search from surfacing the wrong content
Semantic search is powerful precisely because it is good at finding things, which is also its governance risk. A draft with a not-yet-approved pricing claim, an internal runbook, or a deprecated policy is still just text, and an embedding index will happily surface it to whoever, or whatever, is searching. When an LLM is one of the consumers, the stakes rise: the model does not know that the confident-sounding paragraph it retrieved was an unpublished draft.
Enterprise semantic search therefore needs the same controls as publishing: who can see what, what state a document is in, and an auditable record of changes. This is where a search layer welded onto a raw vector store struggles, because the vector store has no concept of editorial state or permission; it just holds vectors and returns the nearest ones.
Because Sanity's embeddings are part of the platform rather than a detached index, retrieval inherits the governance already in place. Content Releases let you stage and review changes before they are live and searchable. Roles & Permissions constrain who can query what. Audit logs record the history. For compliance-sensitive teams, Sanity is SOC 2 Type II compliant, supports GDPR obligations, offers regional data residency, and publishes its sub-processor list, so the content feeding semantic search and LLM workflows sits inside a governed system rather than an ungoverned copy. Semantic search stops being a side door around your editorial controls and becomes an extension of them.
Retrieval that inherits your editorial controls
Wiring semantic search into AI workflows and the editor
Semantic search is rarely the finish line. It is the retrieval step that feeds something else: an LLM answering a support question, an editor finding related content while drafting, an agent grounding a generated summary in approved source material. The value of owning embeddings inside the CMS compounds when these workflows read from the same fresh, governed index.
Inside the Studio, AI Assist can use retrieved context to do concrete editorial work: summarize the three most similar existing articles before an editor writes a fourth, fact-check a claim against the knowledge base, or suggest internal links to semantically related pages. Agent Actions extend this to schema-aware pipelines, where an LLM can generate, transform, or validate content grounded in what semantic search returns, with the structure of your content model intact. Functions let you run automation on publish, re-enriching or re-tagging content so the embedding index and the workflows reading from it stay current without manual intervention.
For retrieval-augmented generation specifically, Sanity Context exposes this governed content to agents through a standard interface, so the same embeddings that power your internal search box also ground external agents. The deeper agent-grounding architecture is a topic in its own right; the point here is that when embeddings are native to the platform, the CMS is a first-class participant in LLM workflows rather than a data source you export from. This is the scale-output promise: the same structured, embedded, governed content serves humans and models from one foundation, so improving your content improves every consumer of it at once.
Where the embeddings live: CMS-native versus bolt-on approaches
| Feature | Sanity | Pinecone | pgvector / Neon | Contentful |
|---|---|---|---|---|
| Where embeddings live relative to content | In the Content Lake next to the content they index, via the Embeddings Index API and dataset embeddings, so no separate store to reconcile. | Standalone vector database; content stays in your CMS and vectors are upserted separately, so you own the sync between the two. | Vectors in a Postgres column; convenient if content is already in that DB, but a CMS-backed setup still means a separate copy to keep aligned. | No native embeddings store; teams pair Contentful with an external vector DB and a webhook pipeline to populate it. |
| Keeping embeddings fresh on content change | Freshness is a platform property; when a document changes, re-embedding is the platform's job, not a webhook you monitor. | You build and operate the re-embed pipeline; a failed or timed-out job leaves the index stale with no built-in signal. | Freshness depends on triggers or app code you write; silent failures leave stale vectors until someone notices bad results. | Freshness depends on the App Framework function or middleware you wrote; the sync contract is yours to maintain. |
| Hybrid semantic plus keyword and filter query | One GROQ query blends semantic similarity with exact filters, references, locale, and publish state; no merging result sets in app code. | Supports metadata filters and sparse-dense hybrid, but exact CMS-side filters require a second query and a merge step you own. | SQL can combine vector distance with WHERE clauses; capable, but relevance blending and ranking logic are hand-rolled. | Requires orchestrating Contentful search plus the external vector DB and merging both result sets in application code. |
| Structure preserved through chunking | Portable Text keeps headings, blocks, and marks as data, so chunks map to coherent units and cite the exact block. | Vector-agnostic; chunk quality depends entirely on how you split content before ingest, typically from rendered or Markdown text. | No content structure of its own; chunking quality is whatever your ingestion code produces. | Rich Text is structured, but chunking still happens in your external pipeline, outside the CMS. |
| Governance over what search can surface | Retrieval inherits Content Releases, Roles & Permissions, and Audit logs, so search and LLMs cannot bypass editorial state. | The vector store has no editorial state or permissions; access control and draft filtering must be enforced in your app layer. | Governance is whatever your database roles and app logic enforce; no editorial concept of publish state. | Content governance is strong in the CMS, but the external vector copy sits outside it unless you replicate the controls. |
| Serving humans and LLM agents from one index | AI Assist, Agent Actions, and Sanity Context read the same governed embeddings, so internal search and agent grounding share one source. | Excellent as an LLM retrieval backend, but it is one system among several; editor-facing search is a separate integration. | Works as an LLM retrieval store; editor tooling and agent access are separate builds on top. | AI features exist via Quick Start AI and the App Framework, but agent retrieval typically routes through the external vector layer. |
| Compliance posture for the content feeding search | SOC 2 Type II, GDPR support, regional data residency, and a published sub-processor list cover the governed content and its embeddings. | SOC 2 Type II and GDPR support for the vector service; the content it indexes is governed wherever that content actually lives. | Inherits your database provider's posture (Neon offers SOC 2); the CMS content itself is governed separately. | SOC 2 Type II and GDPR support for the CMS; the external vector copy's posture depends on the vendor you bolt on. |