LlamaIndex's job is building indexes over your documents and giving an agent a retriever tool to query them. Checking whether the caller invoking that agent is authorized to see the documents the retriever returns is a separate concern, and it has to happen before the query reaches the index, in the layer your application builds around LlamaIndex.

This matters more for LlamaIndex than for a general-purpose orchestration framework, because LlamaIndex's core value proposition is the data layer: connecting agents to your actual documents, databases, and knowledge bases. That makes data access control the central governance question for any LlamaIndex deployment, not a secondary concern.

What LlamaIndex provides

LlamaIndex is organized around a data pipeline: ingest documents, split them into chunks, generate embeddings, store them in a vector index, and expose a retriever that returns the most relevant chunks for a given query. Agents are built on top of that pipeline — a function-calling agent or a ReAct-style agent that reasons step by step, decides to call a retrieval tool, and incorporates the result into its response.

The framework gives you fine control over the data side of this: how documents are parsed and chunked, which embedding model is used, how retrieval is scored and re-ranked, and how multiple indexes or data sources can be combined into a single query engine. This is genuinely useful engineering — retrieval quality determines answer quality, and LlamaIndex's abstractions make it easier to iterate on that quality without rewriting the retrieval logic from scratch.

None of that data-pipeline work answers a different question: who is allowed to ask this agent about what. LlamaIndex's retriever executes the query against whatever index it is pointed at. Whether the caller belongs to a specific tenant, department, or clearance level is something your application code has to resolve and build into the query as an explicit filter.

Where the data access gap sits

1. Index-level access is all-or-nothing by default

If you build a single index over documents from multiple teams, customers, or sensitivity levels, an agent's retriever can return chunks from any part of that index unless the query explicitly filters by metadata your ingestion pipeline attached — a tenant ID, a department tag, a classification level. It is straightforward to forget this filter on a specific retrieval path, especially once an application has several agents built against the same underlying index for different purposes. The result is the same pattern covered in vector store poisoning and RAG pipeline security: the retrieval layer trusts the index's contents and the query's scope without an independent authorization check.

2. Retrieval results carry no provenance the caller can act on

A retrieved chunk tells the agent what the text says, not who is allowed to see it or where it came from in terms of a caller's authorization. If a document was ingested with sensitive content and later needs to be restricted to a subset of users, that restriction has to be enforced at query time against metadata — LlamaIndex will retrieve and hand the chunk to the model whenever the metadata filter is not applied, because similarity search runs against whatever content the index holds — deciding that a specific caller is not allowed to see a specific chunk is an authorization step made outside that search.

3. Agent tools beyond retrieval have the same in-process authorization gap

Once an agent is built on LlamaIndex's function-calling or ReAct pattern, it can hold tools beyond retrieval — calling an API, writing to a database, triggering a workflow. Those tools execute the same way any orchestration framework's tools do: in-process, with whatever credentials they were given, with no external check on whether this specific caller's request should be allowed to trigger this specific action. This is the general orchestration-versus-authorization split described in least privilege for AI agents — a good retriever is a data-quality feature, and it sits alongside that authorization layer rather than replacing it.

4. Multi-tenant deployments amplify the blast radius

A LlamaIndex-powered support or knowledge-base agent serving multiple customers is the highest-stakes version of this gap: a single misconfigured or missing filter means one customer's agent session can retrieve another customer's data. This is not a hypothetical edge case — it is the direct consequence of building convenience on top of a shared index without an authorization layer that runs before the retrieval call, every time, regardless of which application code path invoked it.

What good looks like

Data access controls for a LlamaIndex deployment need to answer these questions before any query reaches the index:

  1. Who is the caller, and what tenant, department, or clearance does that identity carry? This has to be resolved before retrieval, not inferred from the prompt.
  2. What subset of the index is that caller authorized to query? Enforce this as a mandatory filter applied to every retrieval call, not as an optional parameter application code can omit.
  3. What tools, beyond retrieval, does the agent hold, and are they scoped to this caller's authorization? Treat each tool the same way you would treat a database credential — narrow, revocable, attributable to a specific caller or session.
  4. Is every retrieval and tool call logged with the caller identity and the filter that was applied? Without this, you cannot demonstrate after the fact that access controls were actually enforced, which is the same audit gap covered in building an AI agent inventory applied to the data layer specifically.
Layer LlamaIndex responsibility External responsibility
Ingestion Chunking, embedding, metadata attachment Tagging documents with authorization metadata
Retrieval Similarity search and re-ranking Enforcing mandatory access filters on every query
Agent tools Executing the tool call Authorizing the caller for that specific tool and target
Audit Retrieval result logging in application code Attributing every query to a caller identity, retained centrally

Treat LlamaIndex as what it is: a strong data and retrieval layer, not an access control system. The authorization decision — who can query what — belongs outside the index, enforced on every call, independent of which application or agent is making the request. For the broader identity model this depends on, see identity and access for AI and PII detection and redaction in AI pipelines for the complementary control on what retrieved content is allowed to reach the model or the caller.

Common questions

Does re-ranking or a similarity threshold reduce the need for an access filter?

No. Re-ranking changes which of the retrieved candidates surface first; a similarity threshold changes how many candidates are returned. Neither one evaluates whether the caller is authorized to see any given candidate — both operate purely on relevance to the query. A highly relevant but unauthorized document will still rank well and still clear a relevance threshold; only an explicit authorization filter, applied against the caller's identity, removes it from consideration.

If each tenant has its own index, is the access problem solved?

Separate indexes per tenant remove one failure mode — a query against tenant A's index structurally cannot return tenant B's documents, because they were never in the same index. It does not solve the access problem within a tenant's own index, where documents may still carry different sensitivity levels or be scoped to specific roles or departments. Index-per-tenant is a good isolation boundary at the tenant level; it is not a substitute for document-level filtering within that boundary.

Where should the access filter be applied — in the retriever's query, or after results come back?

Apply it as part of the query sent to the index, not as a post-processing step that discards unauthorized results after retrieval. Filtering after the fact still means the vector search itself considered unauthorized documents when selecting the top matches, which can silently reduce answer quality by "wasting" result slots on documents that get discarded, and depends on every code path remembering to run the post-filter correctly. A query-time filter, enforced as a required parameter rather than an optional one, is both more reliable and more efficient. Where the underlying vector store supports it, express the filter as a mandatory clause the query builder cannot construct without, rather than a convention every call site has to remember to apply correctly on its own — a required parameter fails loudly when omitted, while a forgotten convention fails silently by returning results nobody meant to expose to a caller who was never supposed to see them.