Agent Multi-Tenant Isolation Specification
An agent multi-tenant isolation specification defines tenant context propagation, per-tenant memory namespacing, tool allowlist scoping, secret separation, per-tenant rate limits, and audit-trail requirements that contain the blast radius of prompt injection or compromise to a single tenant.
TL;DR
In a multi-tenant SaaS agent, the model, the memory store, the tool layer, and the secret store are usually shared across tenants. Without explicit isolation, one tenant's prompt injection becomes another tenant's incident: shared memory turns into a propagation channel, reused tokens leak data across boundaries, and a single noisy tenant exhausts the shared rate limit. This spec defines the seven controls that contain blast radius to a single tenant: tenant context, memory namespacing, tool allowlist scoping, secret separation, per-tenant rate limits, prompt-injection containment, and per-tenant audit trail.
Definition
Multi-tenant isolation for an agent is the property that any side effect of a turn — a memory write, a tool call, an output, a state change, a token consumption — is bounded to the tenant the turn belongs to. The spec is the contract every layer of the agent must implement to maintain that property under both honest and adversarial inputs (Scalekit, 2026).
Isolation is not the same as authentication. Authentication answers who is calling; isolation answers what they can touch. A correctly authenticated tenant can still trigger a cross-tenant breach if the agent's memory is shared, the tool credentials are pooled, or the audit log lacks tenant tags.
Why this matters
Agent platforms aggregate tenant data and tenant capabilities in ways traditional SaaS does not:
- Long-term memory is a propagation surface. When memory embeddings are shared across tenants, an attacker's stored prompt becomes a policy virus that the next tenant's agent reads as trusted context (Nexumo, 2026).
- Tool credentials are concentrated. A pooled OAuth token used by the agent on behalf of all tenants is a single credential whose theft breaches every tenant. Channel-owned tokens isolated per tenant remove this concentration (Scalekit, 2026).
- Prompt injection has high blast radius. With broad IAM permissions, a successful injection can pivot from one tenant's data into shared infrastructure (Reddit r/aiagents, 2026).
- Cost and rate budgets cross over. A noisy tenant burning the shared LLM rate limit degrades every other tenant's service.
Provider documentation now treats tenant isolation as a first-class concern (AWS Bedrock multi-tenant guidance, Databricks Unity Catalog isolation), but the agent layer is where the contract is enforced.
The seven controls
Every turn must satisfy all seven. The spec is non-negotiable; partial implementation is treated as no implementation.
| Control | Purpose | Failure mode if missing |
|---|---|---|
| Tenant context propagation | Bind every call to a tenant_id | Cross-tenant data return |
| Memory namespacing | Partition vector + state stores | Policy-virus propagation |
| Tool allowlist scoping | Limit which tools each tenant can invoke | Privilege escalation via tool |
| Secret separation | Per-tenant credentials | Single-token cross-tenant breach |
| Per-tenant rate limits | Bound token + call budget | Noisy-neighbor degradation |
| Prompt-injection containment | Sanitize, partition, refuse | Cross-tenant policy injection |
| Per-tenant audit trail | Tag every event with tenant_id | Untraceable incidents |
Tenant context propagation
A single canonical tenant_id must be derived at request entry from the authenticated principal and propagated through every downstream call. Three rules:
- Single source. Derive tenant_id from the auth token, not from request parameters. Inferred or message-payload-derived tenant IDs are the most common privilege-escalation root cause in agent systems (Scalekit, 2026).
- Explicit propagation. Pass tenant_id as a typed argument to every internal function and downstream call — retrieval, memory read/write, tool invocation, logging. Implicit context (request-local globals) breaks under async, retries, and multi-agent handoffs.
- Validation at boundaries. Each downstream service re-validates tenant_id against the authenticated principal. Trusted-input assumptions across service boundaries are the second most common failure pattern.
Memory namespacing
Vector indexes, KV memory, and conversational memory are namespaced per tenant by physical separation, not just by filter:
- Separate index, collection, or partition per tenant where the store supports it.
- Where physical separation is not feasible, an enforced metadata filter on every query plus a row-level access policy at the store. Filter-only enforcement at the application layer is bypassable.
- Cross-tenant memory promotion (e.g., learning from one tenant to improve another) is forbidden by default. If permitted, it requires an explicit privacy review and an opt-in flag per source tenant.
Violating this control creates the canonical multi-tenant time bomb: an attacker stores a prompt-shaped string in memory, the next tenant retrieves it as context, and the model treats it as a trusted instruction (Nexumo, 2026).
Tool allowlist scoping
Each tool is registered with an allowlist of tenants permitted to invoke it, plus a per-tenant configuration scope:
- The agent's tool selection step filters by allowlist before exposing tools to the model. Tools the tenant cannot invoke must not appear in the model's tool list — not because the model is trusted to refuse, but because exposed tools become injection targets.
- Tool parameters are sourced from the per-tenant config, not inferred across tenant boundaries (Scalekit, 2026). Resource IDs, paths, and account references must come from the tenant's config entry; never from message text or model-generated values that could pass a different tenant's resource.
- Outbound network destinations from tools are restricted per tenant. A code-execution tool for tenant A cannot egress to tenant B's webhook URL.
Secret separation
Secrets and credentials are stored per tenant, never pooled:
- Each tenant has its own encrypted credential store entry per integration. No shared OAuth token across tenants.
- The agent fetches credentials just-in-time per tool call, scoped to the current tenant_id. Long-lived in-memory credential caches are forbidden — they are the most common source of stale-tenant-mapping bugs.
- Secretless architectures (short-lived assumed roles, OIDC token exchange) reduce blast radius further by eliminating the long-lived stored credential (Akeyless, 2026).
Per-tenant rate limits
Three budgets are enforced per tenant, not globally:
- Tokens per minute. Caps total LLM token consumption.
- Tool calls per minute. Caps tool fan-out and downstream API pressure.
- Cost per day. Caps spend; integrates with the graceful-degradation spec to fall back to a cheaper model when approaching cap.
A single global rate limit is unsafe — one tenant under load can exhaust the shared budget and degrade every other tenant. Per-tenant budgets are the only durable defense against noisy-neighbor outages.
Prompt-injection containment
The spec assumes prompt injection will succeed eventually and is concerned with the blast radius when it does. Three containment layers:
- Input sanitization. Strip or escape control sequences in tool outputs before they enter the model context. Tag every external string with provenance metadata so downstream policies can tell user-typed text from tool-returned text from memory-retrieved text.
- Capability minimization. The agent operates with least-privilege IAM — no broad s3: or database: grants. Capability is granted per-tool, per-tenant, per-action (Reddit r/aiagents, 2026).
- Output policy. The agent's response cannot include data not authorized for the current tenant; an output filter cross-checks the response against the tenant's data scope before returning.
The Databricks pillar model (limit input, limit reasoning, limit state-change/external communication) is a usable baseline (Databricks, 2025).
Per-tenant audit trail
Every event — turn start, model call, tool call, memory read, memory write, refusal, error — is logged with tenant_id, user_id, turn_id, and policy_decisions. Two requirements:
- Immutable. Logs are write-once for at least the compliance retention window.
- Queryable per tenant. Operators can answer "what did this tenant's agent do in the last hour" without scanning shared logs.
Without per-tenant audit, post-incident investigation is impossible and regulatory questions (GDPR right-of-access, SOC 2 evidence) become forensics projects.
Common pitfalls
- Filter-based memory isolation only. Application-layer filters are bypassable; require physical or store-level enforcement.
- Shared OAuth token across tenants. A theft or leak of one credential breaches every tenant.
- Tenant ID inferred from message payload. Lets an attacker spoof tenant context by writing a different ID in the body.
- Global rate limits. Noisy neighbors degrade everyone; per-tenant budgets are required.
- Tools exposed to all tenants by default. Allowlist must be explicit; default-allow is a privilege-escalation backdoor.
- No provenance tagging on retrieved text. Memory-retrieved injection is indistinguishable from user input and bypasses input-only sanitization.
- Audit logs without tenant_id field. Untraceable incidents and broken compliance posture.
FAQ
Q: Is per-tenant isolation the same as silo deployment?
No. Silo deployment dedicates infrastructure per tenant; isolation is a contract that holds in pooled deployments too. Most production agent platforms run pooled with isolation enforced at the application and storage layers (AWS Bedrock multi-tenant, 2024).
Q: Can the model itself be shared across tenants?
Yes, the model is stateless per call. The state — memory, tools, secrets, history — is what must be partitioned. Sharing the model is fine; sharing memory is the danger.
Q: How does this spec interact with prompt injection defenses?
This spec is the blast-radius layer; prompt-injection detection and prompt-firewalls are the prevention layer. Both are required — detection prevents some injections, isolation contains the ones that succeed.
Q: What about cross-tenant analytics or model improvement?
Forbidden by default. Permitted only with an explicit privacy review, opt-in per source tenant, and aggregation that prevents per-record reconstruction. Cross-tenant memory promotion in particular is the canonical multi-tenant time bomb (Nexumo, 2026).
Q: How do I test this spec?
A red-team test suite per release: attempt to retrieve another tenant's memory via prompt injection, attempt to invoke a tool the tenant is not allowlisted for, attempt to reuse a captured token across tenants, and attempt to exhaust the global rate limit from one tenant. All must fail.
Q: Does this apply to single-tenant deployments?
Most controls still help (capability minimization, secret rotation, audit). Memory namespacing and per-tenant rate limits are unnecessary in true single-tenant deployments but trivial to add and reduce migration cost if the platform later goes multi-tenant.
Related Articles
Agent Circuit Breaker Specification
Specification for circuit breakers protecting AI agent calls to LLM providers and tools, including state transitions, threshold tuning, fallback strategies, and observability hooks.
Agent Graceful Degradation Specification
Specification for graceful degradation when AI agent dependencies fail: model fallback chains, tool-skip policies, cached-response serving, and user-facing failure messaging.
Agent Retry Strategy Specification
Retry-strategy specification for AI agents covering retry classes, exponential backoff with jitter, idempotency keys, Retry-After honoring, and per-tenant retry budgets.