Per-User Agent Isolation in Self-Hosted Multi-Tenant Deployments
Hardware-isolated VMs per tenant are the only structurally sound defense.

Self-hosted multi-tenant agent deployments face a threat model that standard SaaS isolation never anticipated: the platform executes code it did not write and cannot review. That code, generated at runtime from user prompts, can attempt to escape to neighboring tenants. If you want to close every escape path at once, you need per-user hardware-level VM isolation, enforced structurally rather than by policies the application must remember to apply.
Why standard multi-tenant scoping fails when agents execute arbitrary code
Traditional multi-tenant SaaS isolates tenants at the application layer. The code was written internally, reviewed, tested, deployed through a pipeline. Trust in the code is the unstated foundation beneath every tenant_id filter and every scoped credential.
AI agents invert that model. The threat model shifts from preventing unauthorized data access to preventing arbitrary code running in the platform's environment from escaping to neighboring tenants. Three attack surfaces open simultaneously: compute, covering CPU and process space. Storage, covering filesystem and memory stores. And in-process memory, covering agent context and credentials. But it cannot close the compute surface structurally when processes share a host kernel. No predicate exists that prevents a kernel exploit. This is the gap the rest of the argument addresses.
What "isolation" actually requires at each of the three layers
Closing all three attack surfaces simultaneously is the correct definition of isolation for agent workloads. Closing two out of three is not a partial win. It is a gap an attacker or a misbehaving agent can exploit. The three surfaces demand different mechanisms, and conflating them is where most deployments fail.
Compute isolation requires that each tenant's code run in an execution boundary that a kernel exploit, a container escape, or resource exhaustion cannot cross to reach a neighbor's workload. Container escape CVEs recur. runc produced CVE-2019-5736 and CVE-2024-21626, both high-severity. Each disclosure opens a window for tenant-boundary crossing: a kernel exploit inside one container walks through to the host and every neighbor sharing it.
Storage isolation means every file operation, vector retrieval, and knowledge graph query must be structurally scoped to the tenant, not filtered by a predicate the application must remember to pass. The distinction is simple: a filter the application must supply on every call is a soft partition that leaks the moment a predicate is omitted. A storage-layer boundary that structurally refuses cross-tenant queries is a hard boundary.
Memory isolation closes the third surface. Identity must be propagated all the way to the data layer, enforced by validated JWT tokens at the back end, not inferred by the agent from its context window. The context window is precisely the surface injection attacks target.
Where containers break down under adversarial agent workloads
The structural flaw in container-based isolation for agent workloads is that containers share the host kernel. Containers isolate at the process level: a tenant's agent gets a separate process tree, isolated network and filesystem views, CPU and memory limits. But all of it sits on the same kernel every other container on the node shares.
That boundary keeps failing under adversarial pressure. CVE-2019-5736 and CVE-2024-21626 in runc are high-severity examples, each one opening a path from inside a container to the host. CNCF's analysis of the November 2025 runc breakouts warned that such flaws "are most critical" in multi-tenant environments where users define their own containers or run unvetted images. The platform never reviewed it. It is structurally untrusted, and trusting the container boundary to contain it is a design assumption that CVE history has repeatedly disproved.
The recurrence of container escape CVEs underscores why serious multi-tenant agent deployments cannot rely on a shared-kernel boundary. VM-per-tenant isolation closes the compute surface structurally because each tenant's agent runs on its own isolated kernel with no shared escape path to the host or neighboring workloads. Tighter RBAC, more granular API keys, stricter tenant_id filters on storage queries all live above the kernel, and a kernel exploit bypasses them entirely. Container isolation remains appropriate for workloads where the platform controls the code: pre-defined functions, reviewed background jobs. It is not appropriate for arbitrary agent-generated code executing in a multi-tenant context.
How micro-VM isolation closes the compute surface that containers cannot
A dedicated guest kernel enforced by hardware virtualization moves the trust boundary below the kernel. Firecracker is the open-source virtual machine monitor that operationalizes this. It uses KVM for hardware virtualization and provides the same isolation guarantees as a full VM. Firecracker boots a microVM in 125 milliseconds or less and adds less than 5 MiB of memory overhead per VM. The attack surface is the hypervisor's VMM, written in Rust with a deliberately narrow device model, not the full host kernel.
This is not a theoretical recommendation. AgentCore Runtime launches lightweight microVMs on a per-session basis, each with its own isolated filesystem, with optional managed session storage that persists across stop/resume cycles. Agents can read and write session-scoped files and preserve state across multi-step interactions, reducing the risk of cross-session data leakage, all without the cost or latency of spinning up a full virtual machine per tenant.
The isolation guarantee is structural, not policy-dependent. There is no predicate to forget, no permission check to misconfigure. Self-hosted deployments get the same isolation guarantee without managed-cloud lock-in.
Closing the storage surface: hard boundaries versus soft partitions in agent memory
The decision that determines whether a multi-tenant agent deployment leaks storage data is not the schema design. It is whether the tenant boundary is enforced by the storage layer or by a filter the application must remember to pass on every query. A single omitted predicate in a recall query, a background reindexing job running with elevated credentials, or an approximate nearest-neighbor search without a strict filter can return another tenant's data.
A concrete miss illustrates the failure mode. The fix was a real boundary, not a stricter filter. Cognee's production guide identifies the recurring failure points: shared embeddings indexes where the similarity query omits the tenant filter, shared knowledge graphs where entity resolution merges nodes from different tenants under the same canonical name, background jobs that iterate over all records and write results back without reapplying the tenant predicate.
Hard boundaries make cross-tenant queries structurally impossible. There is nothing to forget because no cross-boundary query path exists. The silo pattern, dedicated memory stores per tenant, reduces cross-tenant access risk at higher operational cost, and it is the right default when a storage leak is a breach rather than a bug.
Three scopes typically compose in production. The pattern for crossing them without weakening boundaries is a fan-out at the application layer: recall from each bank the caller is entitled to, merge and rerank results before they reach the model. Never punch a hole through a boundary.
Closing the memory surface: identity propagation and credential scoping
VM isolation closes the compute surface and hard storage boundaries close the storage surface. Neither prevents a tenant's agent from acting on a falsely propagated identity inside its own execution environment. The memory surface requires explicit identity enforcement at every layer of the stack. The agent must not be permitted to infer or assert its own identity from context, because context is vulnerable to prompt injection and impersonation.
AgentCore's tenant context model illustrates the mechanism. Row-level security at the database layer then enforces that even a correctly running agent can only read rows its validated identity is entitled to. Application-layer checks above the database are a soft partition subject to the same omission risk as metadata filters.
Credentials and secrets must never pass through the agent's context window. Each micro-VM carries its own persistent filesystem and memory store scoped to that session. State does not survive across sessions to different tenants, and waking a hibernated agent restores only that agent's own snapshot.
Three isolation tiers and when each applies in a self-hosted deployment
Not all workloads in a self-hosted multi-tenant deployment carry the same risk profile. The right isolation tier closes all three surfaces for the workloads that require it, without applying micro-VM overhead to workloads where containers are appropriate. Tier one is micro-VM per session for arbitrary agent code. Maritime implements the same tier on bare metal: each agent lives in its own Firecracker micro-VM with a persistent disk and a real kernel, and the snapshot-restore scheduler means a hibernated agent pays only for storage, not idle compute, making the per-user micro-VM model economically viable at scale.
Tier two is container isolation for platform-controlled code. The untrusted-code execution model of AI agents shifts the threat surface from data access to process escape. Application-layer tenant_id filters and scoped API keys, while necessary for storage and memory isolation, cannot alone protect against a misbehaving or malicious agent that executes arbitrary code. Only structural isolation at the compute layer, the independent VM per tenant that Maritime runs on bare metal, can eliminate the blast radius entirely.
Tier three is per-deployment physical isolation for regulated tenants. A full stack per tenant, often in that tenant's own network segment, is required when data residency, air-gapped operation, or contractual single-tenancy is mandated. It carries the highest operational cost but structurally eliminates shared infrastructure as an attack surface. Tier assignment is a security property, not a performance hint.
Snapshot-restore scheduling and the economics of running micro-VMs at scale
The historical objection to VM-per-user isolation is that spinning up a dedicated VM for every user is prohibitively expensive. When a session transitions to standby, the compute bill drops to zero. The only remaining cost is snapshot storage, which is orders of magnitude cheaper than active compute.
AI agents spend a large portion of their execution time waiting. At low utilization, managed services absorb the fixed overhead. At higher utilization, self-hosting amortizes the control-plane cost across more active sessions, and the isolation quality is equal or better.
Implementing VM-per-user isolation in a self-hosted deployment: the practical sequence
Implementation proceeds in four layers that must be addressed in order: compute provisioning, storage scoping, identity propagation, and observability. Skipping any layer leaves one of the three attack surfaces partially open. Provision a Firecracker micro-VM per user session on bare metal with KVM enabled. A session requiring micro-VM isolation must not fall back to container execution under capacity pressure.
Storage comes second, and it requires hard boundaries rather than soft partitions. For file storage, scope every tool call to the tenant's root directory at the MCP tool layer. Background jobs, whether reindexing, summarization, or graph enrichment, must reapply tenant predicates explicitly. Running them with elevated credentials over all records and writing back without scoping is the most common source of storage leakage in production systems.
Identity propagation comes third. Pass tenant metadata, including identifier, tier, and entitlements, via HTTP headers set by the platform before the request reaches the agent. Observability completes the sequence. Log every file access, memory retrieval, and tool call with the tenant ID. Emit per-tenant resource consumption metrics to support cost attribution and noisy-neighbor detection. AgentCore's tenant observability model, covering per-tenant cost attribution, noisy-neighbor detection, and observability with audit trails handled separately via CloudTrail and policy controls, is the production template for this layer in a self-hosted deployment.
What the complete picture looks like and where self-hosted teams most often fall short
Full isolation in a self-hosted multi-tenant agent deployment means all three surfaces are closed simultaneously by structural mechanisms, not by policies the application must remember to enforce. Any deployment that closes two out of three has a gap, and in agent workloads, gaps get found. The most common incomplete pattern is hard storage boundaries and careful identity propagation with containers for compute. Storage and memory surfaces close, but the compute surface stays open to kernel exploits and resource exhaustion attacks. This is the exact pattern that container escape CVEs like CVE-2024-21626, a runc file descriptor leak enabling host filesystem access, directly exploit.
The second common gap is micro-VM compute isolation with soft storage partitions. Metadata filters and namespace predicates stand in for storage-layer boundaries, so the storage surface is only as strong as the discipline of every query writer and every background job author. The third gap is VM and storage isolation with identity inferred or carried by the agent rather than injected and validated at the infrastructure layer. The memory surface stays open to prompt injection that causes the agent to act on a falsely claimed identity.
The self-hosted advantage is that operators who own the infrastructure can close all three surfaces with a coherent architecture. The managed-service trade-off is that the provider closes some surfaces on the operator's behalf but may not expose the controls needed to close all three for specialized workloads. The standard to hold a self-hosted deployment to: compute boundary enforced by hardware virtualization, storage boundaries enforced by the storage engine rather than application predicates, identity enforced by validated claims at the infrastructure layer rather than inferred by the agent, and observability across all three surfaces so gaps can be detected before they are exploited.


