Secure Retrieval for Enterprise Agents: OAuth, Role-Based Access, and Content Scoping
A support agent answers a billing question by quoting a pricing tier that was deprecated two quarters ago, or worse, surfaces an internal margin note to an external customer because the retrieval layer had no concept of who was asking.
A support agent answers a billing question by quoting a pricing tier that was deprecated two quarters ago, or worse, surfaces an internal margin note to an external customer because the retrieval layer had no concept of who was asking. That is the failure mode that keeps enterprise AI platform teams up at night: not a model that reasons poorly, but a retrieval path that reasons over content it should never have seen. When an agent can read everything, it will eventually say the wrong thing to the wrong person.
Sanity Context (previously Agent Context) exists to close that gap. It is the intelligent backend for companies building AI content operations at scale, where retrieval, permissions, and governance live in the same system rather than being stitched together after the fact. The premise is simple: an agent should only ever retrieve content that the caller is entitled to, in the state that content is currently in.
This article reframes secure retrieval as three connected disciplines: authenticating the caller with OAuth, resolving what that caller is allowed to see through role-based access, and scoping content so the retrieval query itself can never over-return. Treated together, they turn "the agent leaked something" from an incident into an architectural impossibility.

The over-retrieval problem is a security problem, not a relevance problem
Most teams first meet retrieval security as a relevance bug. An agent returns a stale answer, a document that should have been archived, or a note meant for one region shown to a user in another. The instinct is to tune the ranking. But ranking is downstream of a deeper question: what was in the candidate set at all? If the retrieval index contains every document regardless of caller, then no amount of re-ranking makes the result safe. A confidential roadmap that ranks fourth is still a leak waiting for the right prompt.
Enterprise content is not flat. A single knowledge corpus mixes public marketing pages, gated partner documentation, internal support runbooks, unreleased product specs, and customer-specific contract terms. Each has a different audience. When those live in one undifferentiated vector store, the security boundary has been deleted at ingestion time, and every query afterward inherits that flaw. You cannot bolt a permission model onto an index that already forgot who owns what.
The correct mental model is that every retrieval is a query executed on behalf of an identity, against content that carries its own access metadata. The candidate set should be constructed from the intersection of the query's relevance and the caller's entitlements, in that single step. Sanity's Content Lake supports this because content is stored as structured, queryable documents with fields you define, so audience, region, lifecycle state, and ownership are first-class attributes rather than afterthoughts. Filtering on them happens inside the query, before ranking, before the model ever sees a token. Secure retrieval starts by refusing to build an unsafe candidate set in the first place.
OAuth: authenticating the caller before a single document is read
Role-based access is meaningless if you cannot trust the claim of who is asking. That is what OAuth solves. Rather than an agent holding a static API key that grants blanket read access, each request carries a token that identifies the acting user or service and the scopes it was granted. The retrieval layer validates that token and derives an identity it can enforce against. The difference matters most when an agent acts on behalf of many end users: a single agent process serving thousands of customers must never collapse them into one privileged service account that can see everyone's data.
The common anti-pattern is the "god key" architecture. A team stands up a vector database, gives the agent one credential with full read access, and pushes all permission logic into prompt instructions or a post-filter written in application code. Both are brittle. Prompt-level rules are advisory, not enforced, and a jailbreak or an unusual phrasing can route around them. Application post-filters run after the sensitive content has already left the store and entered the process, so a bug in that filter is a disclosure, not a near miss.
With Sanity Context, production agents connect through the Sanity Context MCP endpoint, which is the authenticated seam between the agent and the Content Lake. Identity travels with the request, so the system can resolve entitlements at query construction rather than trusting the model to police itself. The token defines the ceiling of what any retrieval can return, and no clever prompt can raise that ceiling. Authentication is the foundation; everything downstream assumes it is solid.
Role-based access: from identity to a concrete entitlement set
Once the caller is authenticated, the system must translate that identity into a concrete answer: which documents may this request touch? This is where role-based access does its work. Roles group users by function (support agent, partner, internal engineer, external customer) and map each role to the content classifications it is permitted to read. A partner-tier role sees partner documentation and public content but never internal runbooks. An external customer sees only their own contract terms plus general product help.
The naive approach models this in the application: fetch the user's role, hard-code a list of allowed collections, and hope every new content type gets added to every relevant list. That coupling rots fast. Every new document category becomes a migration across every role definition, and the gaps that open during that drift are exactly where leaks happen. The more content types you add, the more the human-maintained permission matrix lags behind reality.
Sanity models permissions at the platform layer through Roles & Permissions, so entitlements are defined against the same content model the editors already work in. When a new document type is introduced, it inherits the access rules of its classification rather than requiring a fresh permission audit. Because the content is structured, a role can be expressed as a filter over document attributes (audience equals partner, region equals EU, lifecycle equals published) instead of a brittle list of collection IDs. Governance and retrieval share one foundation, which is the difference between a permission model that describes your content and one that merely tries to keep up with it.
Content scoping: enforcing entitlements inside the query itself
Authentication tells you who is asking. Roles tell you what they may see. Content scoping is where those two facts get compiled into the retrieval query so the store physically cannot return anything outside the entitlement set. This is the step that separates enforcement from suggestion. In a scoped architecture, the filter is not a courtesy applied to results; it is a precondition on which documents are even considered.
Consider a support agent handling an EU customer on a legacy plan. The retrieval should search only content that is published, tagged for the EU region, relevant to the legacy plan, and within the caller's role. In Sanity, that is expressed directly in GROQ. A hybrid retrieval query blends semantic and keyword relevance using text::semanticSimilarity() and a BM25 match(), combined through score() and boost(), while the same query carries hard filters on audience, region, and lifecycle state. Relevance and entitlement resolve in one pass, so a document outside the scope never enters the ranked set no matter how semantically similar it is to the question.
This is the architectural payoff of keeping retrieval inside the Content Lake rather than in a detached vector store. Because dataset embeddings are tied to the content itself, when a document is unpublished, reclassified, or its region changes, the retrieval behavior updates within minutes without a separate re-indexing pipeline to babysit. There is no window where the embedding index still reflects last week's access rules. Scoping is not a wrapper around the model; it is a property of the query, enforced by the same system that stores and governs the content.
Governing agent instructions the way you govern the website
Secure retrieval is not only about which documents come back. It is also about the instructions that shape how an agent behaves: its system prompts, its allowed tools, the classifications it is cleared to reason over. In most stacks these instructions live in code or environment variables, edited by whoever has deploy access, with no review trail and no way to test a change in isolation before it hits every user. That is a governance blind spot precisely where the highest-leverage behavior lives.
The consequence is familiar. Someone tweaks a prompt to fix one edge case, and a subtle change in tone or scope ships to production unreviewed, sometimes loosening a boundary that a security team had deliberately set. Because the change was invisible to the people accountable for it, the drift is discovered only after an agent says something it should not have. Config-in-code treats agent behavior as an implementation detail rather than as governed content.
Sanity puts this material where editors and reviewers already operate. In Studio, agent instructions and content classifications are edited as structured documents, and with Content Releases a change to an agent's behavior can be staged, reviewed, and scheduled the same way a website launch is. Audit logs record who changed what and when, which is the evidence a compliance team needs after the fact. Agent Actions provide schema-aware APIs for the generate, transform, and translate workflows an agent runs, so those operations are bounded by the same content model rather than free-form calls. Governing instructions and governing content in one place is what makes the whole system reviewable instead of merely functional.
Compliance, residency, and the evidence auditors ask for
For a regulated enterprise, secure retrieval has to produce evidence, not just behavior. It is not enough that an agent avoided leaking a document; the organization has to demonstrate, months later, that access was constrained, that data stayed in the right jurisdiction, and that changes to policy were reviewed. This is where the retrieval architecture meets the audit binder, and where an assembled stack of separate services tends to fall apart, because the evidence is scattered across a vector database, an auth provider, an application, and a pile of deploy logs.
A consolidated backend narrows that surface. When identity, entitlements, content lifecycle, and instruction changes all pass through the same system, the audit trail is coherent rather than reconstructed. Sanity is SOC 2 Type II compliant and GDPR-aligned, offers regional hosting and data residency for teams that must keep content in a specific jurisdiction, and publishes its sub-processor list so security reviewers can complete their own due diligence. Region can also be a scoping attribute in the retrieval query itself, so residency is enforced at read time, not just at storage.
The practical difference is how a review goes. Instead of correlating logs across four vendors to prove that an EU customer's agent only ever retrieved EU-resident, published, entitled content, the story lives in one place: the token that authenticated the caller, the role that set the ceiling, the GROQ filter that scoped the query, the Audit logs that record every instruction change. Sanity Context treats compliance evidence as a natural byproduct of the architecture rather than a separate reporting project bolted on at the end.
Secure retrieval for enterprise agents: how the approaches enforce access
| Feature | Sanity | Pinecone | Contentful | pgvector / Neon |
|---|---|---|---|---|
| Caller authentication | Identity travels with each request through the authenticated Sanity Context MCP endpoint, so entitlements resolve per caller, not per shared key. | API-key or scoped access at the index level; per-end-user identity and entitlement resolution is built in your application layer. | OAuth and Roles & Permissions exist for content APIs, but agent retrieval against an external search index is authenticated separately by you. | Postgres roles and row security are available, but wiring OAuth-derived identity into vector queries is application code you write and maintain. |
| Role to entitlement mapping | Roles & Permissions are defined against the same content model editors use, so new document types inherit classification rules instead of a fresh audit. | No native content roles; permission logic lives outside the vector store and must be kept in sync with your document classifications by hand. | Mature role model for the CMS, though mapping those roles onto a bolted-on search or vector layer is a separate integration to maintain. | Row-level security can express entitlements, but it is schema and policy you design, test, and evolve as content categories change. |
| Enforcement point | Scope is compiled into the GROQ query as hard filters on audience, region, and lifecycle, so out-of-scope documents never enter the candidate set. | Metadata filters are supported and can pre-filter candidates, but correct scoping depends on the filter your app attaches to every query. | Enforcement typically happens as a post-filter in application code after results leave the search service, widening the trusted surface. | Filtering in SQL is possible pre-ranking, but blending it with vector search and entitlements is a hand-built query pattern. |
| Hybrid relevance plus scope in one pass | text::semanticSimilarity() and match() blend via score() and boost() while entitlement filters apply in the same query, one pass. | Strong vector search with metadata filters; combining BM25 keyword relevance and access rules is orchestrated across services. | Relevance comes from an external search product; scope and hybrid ranking are assembled across the CMS and that search tool. | Hybrid search needs extensions and glue; you compose vector distance, keyword match, and access filters into one query yourself. |
| Embedding freshness after access changes | Dataset embeddings are tied to content, so unpublishing or reclassifying propagates to retrieval within minutes with no separate re-index job. | Embeddings live apart from source content; access or lifecycle changes require your pipeline to re-embed and re-upsert. | Content lives in the CMS but embeddings sit in the external index, so a sync pipeline governs how fast changes reach retrieval. | You own the ETL; a reclassified or archived row is only reflected once your embedding refresh job runs. |
| Governing agent instructions | Instructions edit as structured documents in Studio; Content Releases stage and review changes, and Audit logs record who changed what. | No instruction governance layer; system prompts live in your app or config with whatever review your own tooling provides. | Content workflows and roles exist, but agent instructions are usually held outside the CMS in application config. | Instruction management is entirely your responsibility, typically as code or config with your own review process. |
| Compliance evidence trail | SOC 2 Type II, GDPR alignment, regional hosting and data residency, and a published sub-processor list, with the trail in one system. | Holds its own compliance attestations, but the end-to-end retrieval evidence spans your auth provider, app, and this store. | Enterprise compliance for the CMS is strong; a full agent-retrieval audit still spans the CMS plus the external search stack. | Neon and Postgres carry their own posture, but assembling a coherent retrieval audit across services is on your team. |