Retrieval & Hybrid Search7 min readยท

How to Handle Multilingual Embeddings for Global Content

A German customer asks your support agent about "wasserdichte Laufschuhe unter 150 Euro," and the retrieval layer returns a confident answer built from English product docs it never actually matched.

A German customer asks your support agent about "wasserdichte Laufschuhe unter 150 Euro," and the retrieval layer returns a confident answer built from English product docs it never actually matched. The embeddings looked close enough in vector space, so the agent hedged, mistranslated a return policy, or invented a size chart. Multiply that failure across twelve locales and you have a global content operation that hallucinates in proportion to how far a query drifts from English.

This is where most teams discover that "we have multilingual embeddings" is not a retrieval strategy. Sanity Context (previously Agent Context) treats the problem the way it actually behaves: as a hybrid retrieval question, not a pure-vector one. Sanity is the Content Operating System for the AI era, the intelligent backend for companies building AI content operations at scale, and retrieval is the layer where those operations succeed or fail first.

This guide reframes multilingual embeddings away from "pick the right model and ship" toward the harder truth: language is only one signal. Keyword matching, structured predicates that must hold per locale, and freshness across every translated field decide whether your agent answers correctly in Japanese as reliably as it does in English.

Why pure embeddings break down across languages

The seductive pitch for multilingual search is simple. Encode your content as vectors, encode the incoming query as a vector, and return the nearest neighbors. It works for fuzzy semantic match, the "find me something like a trail runner" class of question, and cross-lingual embedding models genuinely can place a French query near an English document in the same vector space. That is a real capability, and for open-ended discovery it is often good enough.

The trouble is that most production questions are not open-ended. They carry structure. "Trail runners under 150 euros, in stock at the Portland warehouse, men's size 11" is a query where a price ceiling, an inventory state, and a size all have to hold, and none of those constraints live in the semantic vibe of the sentence. Pure embeddings fall over here, and they fall over in a language-specific way: the closer a locale's phrasing drifts from the training distribution, the noisier the nearest-neighbor ranking gets, so the structural miss compounds with a semantic miss. Most "AI-powered search" products are this and only this, which is exactly the failure that multilingual global content amplifies.

The consequence is the empty-or-wrong result. A query with a real structural component that vector similarity cannot resolve comes back empty or subtly incorrect, and the model does what models do with thin retrieval: it hallucinates or hedges. In a monolingual catalog you might catch that in review. Across a dozen locales, each with its own reviewers and its own edge cases, the failure hides. The fix is not a better embedding model. It is refusing to treat retrieval as a single-signal problem.

The three signals every multilingual retrieval needs

Reliable retrieval blends three distinct signals, and the reason to name all three is that each one covers a different class of failure. Keyword search, the classic BM25 approach, catches literal matches: a product SKU, a model name, a legal term of art that must appear verbatim regardless of language. Embeddings handle semantic ranking, the meaning-level similarity that lets a paraphrased or cross-lingual query find the right document. Structured predicates enforce the filters that simply have to hold, the price ceiling and the in-stock flag and the locale field itself.

The evidence that no single layer is enough is unusually clean. Anthropic's contextual retrieval research measured the layers directly: contextual embeddings cut top-20 retrieval failures by 35 percent, adding contextual BM25 took that improvement to 49 percent, and adding a reranking pass on top brought it to 67 percent. You can read the paper closely or you can just notice the shape of the numbers. Each layer contributed, and the semantic layer alone left the largest gap on the table.

Multilingual content raises the stakes on the keyword and predicate layers specifically. CJK languages tokenize differently, compound-heavy languages like German and Finnish defeat naive stemming, and a locale field is a structured predicate that a vector search will happily ignore. If your architecture leans on embeddings to carry all three jobs, you have quietly delegated your correctness to whichever language your embedding model was best trained on. Hybrid retrieval is the discipline that keeps a Japanese query as reliable as an English one, because the keyword and predicate signals do not degrade with linguistic distance the way a lone vector score does.

Illustration for How to Handle Multilingual Embeddings for Global Content
Illustration for How to Handle Multilingual Embeddings for Global Content

Architecting the index: one multilingual dataset or per-locale?

Once you accept that retrieval is hybrid, the multilingual question becomes an architecture decision rather than a model-selection exercise. The first fork is whether all locales live in one dataset with a language field, or whether each locale gets its own index. A single multilingual dataset keeps cross-lingual retrieval trivial, since a query in one language can rank documents in another, and it means one schema, one pipeline, and one place to reason about freshness. The cost is that ranking quality can vary by language, and you lean harder on a locale predicate to keep results in the user's language when that is what they expect.

Per-locale indexes give you tighter control. You can tune tokenization and keyword weighting per language and avoid cross-locale bleed, but you pay for it in operational surface area: more indexes to keep fresh, more schema changes to fan out, and the loss of easy cross-lingual fallback when a locale's content is thin. There is no universally correct answer. The right call depends on whether your users cross language boundaries mid-session and how uneven your translated coverage is.

What should not be part of this decision is building the freshness machinery yourself. In Content Lake, the search index stays current automatically. When a description updates, a price changes, an article publishes, or a record is deleted, the index knows. Doing that by hand, incremental indexing, re-embedding on change, deletion handling, eventual-consistency reasoning, and backfill for schema changes, is a real project and a class of bug, and it multiplies with every locale you add. With a separate vector DB plus glue code, freshness becomes a permanent line item on the roadmap, and per-locale re-embedding is exactly the corner that gets skipped under deadline.

Blending BM25 and semantic similarity in a single query

The practical payoff of hybrid retrieval is that you can express it as one query rather than as an orchestration of separate services. In GROQ, a hybrid query filters with predicates first, then ranks with a blended score pipeline. The pattern looks like this: | score(boost([title] match text::query($queryText), 2), text::semanticSimilarity($queryText)) | order(_score desc) [0...10]. The predicates do the filtering that has to hold, your locale field, your price ceiling, your in-stock flag. The score pipeline then blends a BM25 keyword match on the title, weighted 2x because title hits matter more, with a semantic similarity score across the document.

What you get back is a small, ranked list that matches both the structural constraints and the vibe, in a single round trip against Content Lake. For a multilingual query, the locale predicate keeps results in the language the user is working in, match() catches the verbatim terms that survive translation like model numbers and brand names, and text::semanticSimilarity() covers the meaning-level match that lets a paraphrase land. Three signals, one query, no service mesh to keep in sync.

You do not strictly need GROQ to do this. PostgreSQL can, with pgvector and full-text search. Elasticsearch can. Algolia is built for the structured-plus-relevance case, and Pinecone plus a metadata filter layer can. What none of them can do is pure-vector their way out of the empty-result problem, and what all of them require, and what Content Lake handles for you, is the content pipeline that keeps the search index fresh as your translated content changes underneath the query.

What production data says about embeddings-first thinking

There is a strong prior in the market that vector search is the center of gravity for AI retrieval. When you look at how agents actually call Context MCP, the heavy majority of calls are structured: GROQ queries and schema lookups, with the compressed initial context behind that. Semantic search is a small slice of real traffic.

Embeddings adoption follows the same pattern. 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. This is the counter-intuitive part for a team about to invest heavily in choosing a multilingual embedding model: the model is rarely the thing standing between your agent and a correct answer. The shape of the data is.

Sanity's schema exploration against the Sonos catalog, an honestly nightmarish dataset, reached about 83 percent accuracy on a mix of difficulties using Sonnet 4.5 with roughly 40 seconds of reasoning per hard question, and it only got there after teaching the retrieval step things a schema alone will not reveal: counter-intuitive field names, second-order reference chains the schema does not connect, and data-quality issues the types cannot expose. None of that is a model problem. It is a context problem. For multilingual content the lesson lands twice, because uneven translation coverage and inconsistent locale metadata are precisely the data-shape problems that no embedding model can see.

Governing multilingual agents without shipping YAML

An agent that retrieves well in twelve languages still needs to behave well in twelve languages, and behavior is content, not code. In Sanity Context, agent instructions and system prompts are authored in the Studio rather than buried in YAML, so editors and localization leads can tune an agent's voice per market and adjust the scope of what it is allowed to know without a deploy. As Nearform put it, "Storing the system prompt in a Sanity document is genuinely useful. Editors tuned the agent's voice without any code changes." For a global operation, that means the people who own tone in a given locale can own the agent's tone in that locale.

Just as important is that agent behavior can be staged the way you already stage a website. With Content Releases you get drafts, scheduling, history, permission gating, and audit trails over agent instructions, so a change to how the agent handles, say, Japanese honorifics or German formal address can be reviewed, scheduled, and rolled back like any other content change. That is the difference between governing a global agent and hoping a prompt edit did not regress eleven other markets.

Retrieval scope widens the same way. Knowledge Bases (September 2026 launch) turn Sanity datasets, support databases, websites, and PDFs into pristine, well-ordered documents with a clear table of contents, all sharing the same retrieval path. For multilingual teams whose source material is scattered across translated PDFs and locale-specific support databases, that shared path is what keeps a French policy document and its English original answerable by the same governed agent, through the hosted, read-only Sanity Context MCP endpoint any agent loop can connect to.

Multilingual hybrid retrieval: native query surface vs assembled stacks

FeatureSanityPineconepgvector (Supabase / Neon)Contentful
Hybrid retrieval in one queryNative: match() BM25 and text::semanticSimilarity() blended with score() and boost() in a single GROQ query against Content Lake.Semantic nearest-neighbor is native, but keyword and structured filters require a metadata layer plus glue code you build and maintain.Technically supported: vector similarity, full-text search, and SQL filters in one database, but you assemble and weight the blend yourself.Semantic ranking is bolted on via external search or vector services, so hybrid ranking lives outside the content store, not in one call.
Locale as a structured predicateA locale field is a first-class GROQ predicate that must hold, so results stay in the user's language before ranking ever runs.Locale must be modeled as vector metadata and filtered in a separate layer, correct but assembled per project.Locale is a normal SQL column, filterable natively, though you wire it into the ranking blend by hand.Strong localized modeling and delivery, but the locale filter and the retrieval ranking sit in different systems.
Index freshness across localesContent Lake re-indexes on change automatically when a description, price, translation, or record updates or is deleted, per locale.Re-embedding on content change and deletion handling are your pipeline; freshness is a permanent roadmap line item.Keeping vectors and full-text indexes fresh across locales on every edit is custom developer work.Content updates are native, but propagating changes into the external semantic index is glue you own.
Embedding model responsibilityEmbeddings are opt-in and off by default; production traffic is dominated by structured GROQ and schema lookups, not vectors.Multilingual quality depends entirely on the embedding model you choose and keep current.Multilingual embedding quality and re-embedding cadence are the developer's responsibility.No native embedding layer, so model choice and multilingual quality live in whatever external service you attach.
Agent instruction governanceSystem prompts are Studio documents staged with Content Releases: drafts, scheduling, history, permission gating, and audit trails.No agent-instruction governance; prompts live in application code or config outside the retrieval layer.No native prompt governance; system prompts are managed in your app, not the database.App Framework can host AI sidebar apps, but agent instructions are not versioned content in the backend.
Unifying PDFs and support docsKnowledge Bases turn datasets, support databases, websites, and PDFs into ordered documents sharing one retrieval path.Ingesting and chunking mixed sources into vectors is a pipeline you build ahead of the index.Loading PDFs and support data into tables and embeddings is bespoke ETL per source.Mixed unstructured sources are integrated through external apps rather than a single native retrieval path.