Back to blog
multi-tenantdata isolationRAGAI agents

Multi-tenant AI agent: isolating each customer's data

Published on 2026-10-306 min read
In short: In a multi-tenant AI agent, customer isolation has to be enforced in three places: tool calls, memory and RAG. What they share is that the customer identity comes from the server and never from the model, and every data access is filtered by that identity before the model sees anything.

Why is isolation harder with an AI agent?

Because an agent adds to ordinary software a component that decides for itself what to call, with which arguments, based on untrusted text. In a regular SaaS application, code applies a tenant_id filter to every query. In an agent, the model builds the query, and it can be influenced by a message, a document or a tool result.

OWASP documents the risk. LLM02:2025 (Sensitive Information Disclosure) recommends least privilege and limiting the model's access to external sources. LLM08:2025 (Vector and Embedding Weaknesses) describes cross-context leaks in databases shared across customers. LLM06:2025 (Excessive Agency) asks to run extensions in the user's context with the narrowest possible rights.

For the classic application side, our article on multi-tenant isolation in an HRIS covers the historical flaws. Here we focus on what the agent changes.

Where can one customer's data leak to another?

It leaks through four surfaces: tools, memory, RAG and shared context. Each has its own failure mode.

SurfaceTypical failureQuick test
Tool callsThe customer ID is an argument the model fills inAsk the agent to use another customer's ID
Long-term memoryMemory keyed by session or user only, without customerLog in with two accounts from different customers and compare
RAGA single index, filter applied after search or missingAsk a question whose answer sits in another customer's corpus
Context and cacheShared response or prompt cache, mixed logsReplay the same request from two customers

How do you isolate tool calls?

The customer must never be a tool parameter the model can choose. This is the most important rule, and the one most often broken.

A tool get_invoice(customer_id, invoice_id) exposes a direct object reference: if the model supplies customer_id, a prompt injection is enough to read another customer's invoices. The safe version is get_invoice(invoice_id). The server layer adds the customer identity from the authenticated session, passes it to the downstream service, and that service rechecks ownership.

In practice:

  • Inject identity server-side. The token or request context carries the customer. The tool schema shown to the model has no such field.
  • Apply complete mediation. OWASP asks to implement authorization in downstream systems rather than letting the LLM decide whether an action is allowed. Each service rechecks the customer on every call.
  • Use credentials in the user's context. A narrowly scoped OAuth token per customer beats a single service account that sees everything.
  • Prefer narrow tools. An "execute SQL" or "call any URL" tool bypasses every filter. Replace it with precise functions.
  • Validate returned identifiers. If a tool returns an object whose owner does not match the session's customer, reject it server-side.

Our article on function calling explains why arguments are the main attack surface.

How do you isolate the agent's memory?

With a partition key that starts with the customer, then the user, then the session. Long-term memory is a database written by the model and read back later: treat it as such.

The flaws we meet:

  1. Global memory. A fact stored for one customer ("the accounting contact is X") surfaces for another.
  2. Untrusted writes. The agent memorizes text from a third-party document. That is a persistent injection, affecting every later conversation of that customer.
  3. Shared summaries. A conversation summary generated for one customer is reused as context for another.

The measures: partition physically or logically per customer, prefix every key, stop the model from choosing the partition, tag the origin of each memory (user, tool, document), and plan complete erasure at contract end.

How do you isolate RAG between customers?

With a mandatory metadata filter applied inside the vector query itself, or with one index per customer when the risk level justifies it. Filtering results after the search is fragile: the forbidden passages have already been ranked, counted and sometimes cached.

Three architectures, from simplest to most watertight:

ArchitectureAdvantageLimit
Shared index with metadata filterCheap, simple to runOne forgotten filter exposes everyone
Namespace or collection per customerClear separation, easy deletionMore objects to manage
Dedicated database or instance per customerMaximum isolationCost and operational complexity

Whichever you choose:

  • Compute the filter from the server session, never from a field filled in by the model or the front end.
  • Keep owner metadata on every passage from ingestion on.
  • Mirror the sources' rights in the index: a document restricted to a group in the drive must be restricted in the database too.
  • Check that deleting a document removes its vectors, its text copies and its cache entries.

Write-side risks, especially poisoning, are detailed in poisoned RAG: how to test it.

How do you test the isolation of a multi-tenant agent?

With at least two test accounts belonging to two different customers and a series of boundary-crossing attacks. Create marked data in each account (a unique string per customer) so any leak is unambiguous.

The tests, in order:

  1. Direct request. From customer A, ask for customer B's data by name.
  2. Identifier substitution. Ask the agent to call a tool with customer B's ID.
  3. Document injection. Plant in A a document that orders the agent to read and return another customer's data.
  4. Persistence. Make A store an instruction, then verify it appears nowhere in B.
  5. Cache and logs. Replay identical requests and verify no response or trace crosses customers.
  6. Enumeration. Try sequential or predictable identifiers in tools and source URLs.

Count the leaks, but above all record the path: a leak through the tool, through memory and through RAG call for three different fixes. As a rule, we read only what is needed to prove access: a canary string is enough, and we download no real personal data.

What should you keep in mind when designing the architecture?

That the model is never the security boundary. It can help phrase queries, but ownership checks happen elsewhere, using the authenticated identity.

A short checklist:

  • No tenant, customer or account parameter in the tool schemas shown to the model.
  • An identity context passed to downstream services, which recheck it.
  • Memory partitioned per customer, with provenance.
  • A RAG filter applied in the query, computed server-side.
  • Logs that let you find which customer saw which passage. See logging an agent's actions.
  • Automated regression tests between two test customers.

For the overall framework, see our AI agent security page.

How does CleanIssue audit multi-tenant isolation?

We replay the six tests above on your real agent, with two test tenants, and hand back reproducible evidence. The Agent Red Team Express at €1,900 covers one agent in 5 days. If you run several agents for several customers, the Custom Red Team is quoted based on scope. The first conversation is a free 30-minute discovery call.

Does your product ship an AI agent? CleanIssue tests what a stranger can make it do with the Agent Red Team Express (5 days, €1,900), or a custom red team for several agents and MCP servers.

Know what your agent can do before an attacker does.

Tell us about your agent, its tools and your context. A free 30-minute discovery call.

Book a call