[Blog](https://cohesivity.ai/blog)

Architecture

Published Jul 21, 2026·Updated Aug 30, 2026

![](https://cohesivity.ai/authors/arag.webp)![](https://cohesivity.ai/authors/shouryamaan.webp)[Arag](https://www.linkedin.com/in/aragagrawal/) and [Shouryamaan](https://www.linkedin.com/in/shouryamaanjain/)

# Multi-Tenant AI Agent Infrastructure: Isolation, Limits, and Shared State

[Read as Markdown](https://cohesivity.ai/blog/multi-tenant-infrastructure-for-ai-agents.md)

Tenant

Identity

Tenant state

Isolation

Multi-tenant agent infrastructure must derive tenant scope from authenticated context and preserve it through tools, databases, queues, caches, artifacts, credentials, and logs. A `tenant_id` in a prompt or model-generated argument is not isolation.

Agents increase the number and variety of backend actions, so a missed boundary can cross tenants without a human navigating through a constrained interface. The control must hold when the model is confused, retrieved content is hostile, or two resources share the same friendly name.

## Bind identity before accepting resource input

Resolve the tenant from the session or application credential. Pass that identity through the [agent control plane](https://cohesivity.ai/blog/how-to-design-an-agent-control-plane), then authorize the requested action against a server-side resource record.

```mermaid
flowchart LR
    Request[Agent tool call] --> Session[Authenticated session]
    Session --> Scope[Tenant and delegated scope]
    Scope --> Policy{Authorize resource and action}
    Policy -->|allow| Tool[Execute scoped tool]
    Policy -->|deny| Audit[Record denial]
    Tool --> DB[(Tenant-scoped data)]
    Tool --> Queue[(Tenant-scoped work)]
    Tool --> Artifacts[(Tenant-scoped artifacts)]

```

Do not let a tool argument override the authenticated tenant. A resource ID should be looked up under the current tenant, even if it is globally unique, because that keeps the authorization rule explicit.

## Choose a database isolation model deliberately

| Model               | Boundary                                               | Operational consequence                                                                 |
| ------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| Shared tables       | Tenant column plus row-level policy and scoped queries | Simple migrations, but every access path depends on correct policy and connection role  |
| Schema per tenant   | Separate namespace inside one database                 | Stronger naming boundary, with per-schema migration and connection setup                |
| Database per tenant | Separate database and credentials                      | Strongest storage boundary, with more provisioning, pooling, backup, and migration work |

Row-level security can be strong when the application role cannot bypass it and tenant context is set server-side. It is not inherently weaker than an application `WHERE` clause; its guarantee depends on the policy, role, and every alternate connection path.

Use a higher-isolation model for regulatory requirements, unusually large tenants, customer-managed encryption, or independent restore needs. Do not choose database-per-tenant only because the caller is an agent.

The [database patterns guide](https://cohesivity.ai/blog/database-design-patterns-for-ai-agent-applications) shows composite tenant keys and operation constraints.

## Carry scope through every shared subsystem

Database isolation is one boundary among several:

- Prefix cache keys with a non-user-controlled tenant identifier and include it in invalidation.
- Put tenant scope in queue messages from authenticated server context, then reauthorize when a worker consumes them.
- Namespace object keys and vector collections, while checking ownership before issuing a signed URL or search.
- Keep browser and sandbox sessions tenant-owned, with separate filesystems and credentials.
- Scope tool sessions and OAuth grants to the represented tenant and user.
- Partition rate and spend limits by tenant, agent, and high-impact action.

Test the same resource name in two tenants. Friendly names such as `production`, `orders`, or `main` are common collision points when a model selects a resource from context.

## Keep credentials and logs tenant-aware

Store provider credentials under a tenant-owned secret reference. Tool workers should receive only the reference they are authorized to resolve. A shared provider account still needs per-tenant accounting and revocation.

Logs and traces require tenant fields for investigation, but access to observability must be tenant-scoped too. Redact prompts, tool arguments, and results before export. An internal dashboard that can search every tenant may be appropriate for a small trusted operations team, but it remains a privileged surface.

NIST’s [zero trust architecture](https://csrc.nist.gov/publications/detail/sp/800-207/final) frames access as a per-request decision based on identity and resource rather than network location. That maps cleanly to background workers and internal tool calls, which should not gain broad access merely because they run inside the platform.

## Contain loops without confusing quotas for permissions

Set per-tenant limits on concurrent runs, tool calls, model spend, storage, and repeated failures. Add narrower limits to destructive or expensive tools. A loop should pause the tenant’s affected workload and leave an operation record a human can inspect.

Limits contain volume. They do not make an unauthorized call acceptable. Run authorization before charging quota, and return stable error classes so the agent does not retry a policy denial.

## Design deletion across the whole tenant graph

A tenant deletion path should inventory databases, cached values, queued work, artifacts, memories, indexes, browser sessions, sandboxes, credentials, logs, backups, and active operations. Decide what is deleted immediately, expires later, or is retained for legal and security reasons.

Stop new work and revoke credentials before deleting data. Make deletion resumable and idempotent because a partial cleanup is likely. Record completion for each resource without retaining the deleted content itself.

## Test isolation with adversarially similar data

Create two test tenants with overlapping names and near-identical IDs. Attempt access through every tool, worker, cache, queue, and artifact path. Include a retrieved document that instructs the model to switch tenant IDs. The server should deny the action regardless of what the model emits.

The prompt below turns that into a repository-specific test plan. It begins by locating where tenant scope originates, because isolation cannot be proven from a database diagram alone.

or send it to[Claude Code](https://claude.ai/new?q=Inspect+this+repository%27s+AI+agent+path+from+authentication+through+tools+and+storage.+Do+not+edit+code+or+touch+production.+Design+an+isolated+test+with+two+tenants+that+use+identical+resource+names+and+similar+record+IDs.+Check+database+queries%2C+tool+sessions%2C+queues%2C+caches%2C+object+keys%2C+vector+namespaces%2C+browser+sessions%2C+credentials%2C+logs%2C+quotas%2C+and+deletion.+For+each+boundary%2C+state+whether+tenant+scope+comes+from+authenticated+context+or+model-supplied+input.+Report+any+path+where+changing+an+argument+could+cross+tenants%2C+then+propose+the+smallest+server-side+fix. "Send to Claude")[Cursor](https://cursor.com/link/prompt?text=Inspect+this+repository%27s+AI+agent+path+from+authentication+through+tools+and+storage.+Do+not+edit+code+or+touch+production.+Design+an+isolated+test+with+two+tenants+that+use+identical+resource+names+and+similar+record+IDs.+Check+database+queries%2C+tool+sessions%2C+queues%2C+caches%2C+object+keys%2C+vector+namespaces%2C+browser+sessions%2C+credentials%2C+logs%2C+quotas%2C+and+deletion.+For+each+boundary%2C+state+whether+tenant+scope+comes+from+authenticated+context+or+model-supplied+input.+Report+any+path+where+changing+an+argument+could+cross+tenants%2C+then+propose+the+smallest+server-side+fix. "Send to Cursor")[Codex](https://chatgpt.com/codex?prompt=Inspect+this+repository%27s+AI+agent+path+from+authentication+through+tools+and+storage.+Do+not+edit+code+or+touch+production.+Design+an+isolated+test+with+two+tenants+that+use+identical+resource+names+and+similar+record+IDs.+Check+database+queries%2C+tool+sessions%2C+queues%2C+caches%2C+object+keys%2C+vector+namespaces%2C+browser+sessions%2C+credentials%2C+logs%2C+quotas%2C+and+deletion.+For+each+boundary%2C+state+whether+tenant+scope+comes+from+authenticated+context+or+model-supplied+input.+Report+any+path+where+changing+an+argument+could+cross+tenants%2C+then+propose+the+smallest+server-side+fix. "Send to Codex")[opencode](https://opencode.ai/?q=Inspect+this+repository%27s+AI+agent+path+from+authentication+through+tools+and+storage.+Do+not+edit+code+or+touch+production.+Design+an+isolated+test+with+two+tenants+that+use+identical+resource+names+and+similar+record+IDs.+Check+database+queries%2C+tool+sessions%2C+queues%2C+caches%2C+object+keys%2C+vector+namespaces%2C+browser+sessions%2C+credentials%2C+logs%2C+quotas%2C+and+deletion.+For+each+boundary%2C+state+whether+tenant+scope+comes+from+authenticated+context+or+model-supplied+input.+Report+any+path+where+changing+an+argument+could+cross+tenants%2C+then+propose+the+smallest+server-side+fix. "Send to OpenCode")
