Sandboxing AI Agents: Isolated Runtimes, Permissions and What Agents Can Reach in Your Content
A coding agent is asked to fix a typo on a pricing page. It runs a script, the script patches the published document, and a wrong price is live before anyone looks at it. The sandbox did everything it was built to do.
A coding agent is asked to fix a typo on a pricing page. It runs a script, the script patches the published document, and a wrong price is live before anyone looks at it. The sandbox did everything it was built to do. The code never touched the host, network egress was locked down, and the token was injected so the agent never saw it. The content still changed.
Sandboxing an AI agent means isolating where its code runs. Controlling what it can reach in your content is a separate job, and the sandbox can't do it. In Sanity Context, that job sits at the content layer. Role-scoped tokens decide which datasets and document types the agent can see. Agent Actions write to drafts or Content Release versions by default, so a person still decides what gets published.
This guide treats agent safety as three stacked layers: the runtime, the tool allow-list, and content permissions. It shows which agents need which layers, so you stop expecting the sandbox to answer a question it was never designed for. It also covers how to let agents create and update content while publishing stays under control.
What does an AI agent sandbox actually isolate?
An AI agent sandbox isolates four things: where the agent's code runs, which files it can see, which hosts it can call, and which credentials it can touch. A sandbox is a disposable, isolated runtime. It lets an agent run untrusted code without that code reaching the host or the rest of your network. Coding agents need one because they do more than talk. They write shell commands, install packages, run tests, and call APIs, often for many steps without a person approving each one.
Execution isolation usually comes from a lightweight virtual machine or a user-space kernel. E2B runs each agent session in its own Firecracker microVM. Vercel Sandbox also uses Firecracker microVMs, each with a private filesystem. The AWS reference architecture for agent sandboxes on EKS uses gVisor, which intercepts system calls before they reach the host kernel. In every case, a script that deletes files or spawns runaway processes damages only its own guest.
Network isolation is the second layer. A good sandbox starts by blocking all outbound traffic and then allows specific destinations. E2B applies egress policies to each sandbox. The AWS design adds Cilium FQDN filters, so a pod can reach an approved API by hostname and nothing else. This is what stops a prompt-injected agent from sending your repository to an attacker's server.
Credential isolation is the layer teams skip most often. If an API key sits in an environment variable inside the guest, any code the agent runs can print it. E2B's enterprise offering keeps credentials outside the guest. Vercel Sandbox's firewall can inject secrets into outbound HTTP requests so the code never sees the raw value.
Taken together, a sandbox answers one question well: if this agent runs something it shouldn't, how far can the damage spread? With a well-configured runtime, the answer is no further than the microVM. That guarantee is real and necessary for agents that run code. But it's a guarantee about infrastructure. It says nothing about which data the agent is allowed to change.

Why can't a sandbox decide which content an agent can change?
A sandbox can't decide which content an agent may read or change because it has no model of your content. From inside a Firecracker microVM, a request to your content API is just an HTTPS call to a hostname on the allow-list. The firewall checks the destination. It doesn't check whether the request rewrites a draft or overwrites a live pricing page.
Take a common setup. A team gives an autonomous agent a sandbox that blocks all outbound traffic except one hostname for the content API. It also uses secret injection, so the agent never sees the token. Every runtime box is ticked. But the token belongs to a service account created for a demo, and it can publish to every dataset. The agent can now reach everything the service account can. A misread instruction, a prompt injection hidden in a retrieved document, or a plain bug can still publish to production. The sandbox will log it as a clean, allowed request.
Credential injection is easy to misread. Hiding the raw secret from agent code stops the secret from being stolen. It doesn't reduce what the secret can do. A narrowly scoped token that leaks is a smaller problem than a broad token that never leaks but gets used for the wrong write.
The sandbox also has no concept of editorial state. It can't tell a draft from a published document. It can't tell a content type the legal team owns from one marketing owns, or a staged release from what's live. Those distinctions live in the content backend, and only the content backend can enforce them.
So the question splits in two. Isolation answers how far damage from running code can spread. Authorization answers which documents the agent may touch, and whether its changes go live without a person. Teams that expect the first layer to handle the second end up hand-writing permission checks into every tool. Those checks fall out of date as the content model changes, and nobody notices until an agent writes somewhere it shouldn't.
A fully sandboxed agent can still publish the wrong price
What are the layers of control for AI agents that act on content?
Agents that act on content need three layers of control, stacked from the infrastructure up to the document. Each layer answers a different question, and none of them replaces the others.
First, the sandbox runtime decides where code runs. This is the microVM or gVisor layer provided by tools like E2B, Vercel Sandbox, and the AWS agent sandbox reference on EKS. It contains code execution, the file system, network egress, and credentials. It matters most for agents that write and run code.
Second, an MCP gateway or tool allow-list decides which tools the agent can call. MCP server tool descriptions count as trusted text, because they land in the prompt every turn. A sloppy or malicious server can prompt-inject an agent before the user has typed anything. The risk grows as teams combine servers. Pairing Context MCP with a Shopify MCP and a CRM MCP is a common request, and each server adds more trusted text and more tools competing for the model's attention. Docker MCP Gateway is one example of this layer. It runs MCP servers in isolated containers and enforces Cedar-based permit and forbid policies on server registration, tool listing, and tool calls. Read the source of every MCP server you install. Then allow-list only the tools the agent's job needs.
Third, content-level permissions and draft and publish controls decide which documents an allowed tool may touch and whether its changes go live. This is the only layer that knows a document's type, dataset, and editorial state. It's enforced by the role attached to the token each tool runs under. It also depends on where writes land: on a draft, in a staged release, or on published content.
A useful test is to imagine each layer failing on its own. If the sandbox fails, the gateway and content permissions still limit what a compromised agent can call and change. If the gateway lets an unexpected tool through, the token's role still limits what it can reach. If the content layer is missing, nothing else in the stack knows that a pricing page shouldn't go live without review.
When does an AI agent need a sandbox, and when is a read-only agent enough?
An AI agent needs a sandbox when it runs code or takes multi-step autonomous actions. It usually doesn't need one when it only reads content through scoped, read-only tools. What decides it is what the agent can do between human checkpoints, not how sensitive the content is.
A read-only grounding agent is the lowest-risk shape. A site assistant that answers questions from product and documentation content runs no shell, writes no files, and calls a fixed set of retrieval tools. Context MCP, the hosted read-only endpoint in Sanity Context, fits this shape. An agent connected to it has no way to write content at all. The controls that matter here are the token's read scope and a short tool list, not a microVM.
Customer-facing agents that take small actions sit in the middle. They run in harnesses built for short in-product conversations. They act under a user's identity and call tightly scoped tools that receive the user's token. Changing a booking or opening a ticket is a write, but it's a single, limited call made as the user. A coding harness bolted onto this kind of agent is a poor fit for those constraints. The control that matters most is passing the user's token through, so the agent can do only what that user could do.
Coding and autonomous agents need the full sandbox. Tools like Claude Code and Cursor run inside harnesses built for long, autonomous, sandboxed work with filesystems, bash, git, and subagents. Say an agent writes a migration script and runs it against your content API. It belongs in an isolated runtime that blocks outbound traffic by default, and it should carry a token that can only write drafts.
A sensible rollout follows the same order. Start with a read-only site assistant on a public page, three to five read-only tools, and no writes. Put the system prompt somewhere a non-engineer can edit it, and set up trace logging. Only then add write tools. Expect your security team to review how user tokens are passed to those tools before they ship.
How do you let AI agents create and update CMS content without publishing it?
To let agents create and update content safely, send every agent write to a draft or a staged release and keep publishing a human action. In Sanity, Agent Actions do this by default. Agent Actions are schema-aware APIs for content operations: Generate, Transform, Translate, Prompt, and Patch. By default they never change a published document. If you pass a published document ID, the action creates a draft first and leaves the live version alone until someone publishes it.
Writing straight to published content is possible, but you have to opt in. The call must set forcePublishedWrite: true. One edge case belongs in your runbook. Document types configured with liveEdit: true behave as if forcePublishedWrite were set, because they have no draft layer. Keep agents away from liveEdit types unless direct writes are intended.
Agent Actions can also write into a Content Release. Passing a version ID as the _id on a create operation creates a Content Release version. A batch of agent translations or product-copy updates can then be staged together and reviewed as a set. After every call, check the returned _id to confirm whether the write landed on a draft, a published document, or a release version. That check belongs in your tool's tracing.
The role on the token is the second safeguard. Sanity's Contributor role, available on Growth and Enterprise plans, has read and write access to draft content and can write but not publish documents. An agent acting with a Contributor user's token can't publish even if a prompt tells it to, because it doesn't have the permission.
This is the gap between CMSes that bolt on AI and Sanity as the Content Operating System for the AI era. The draft and release tools editors already use are the same ones that govern the agent. That keeps AI governed and part of everyday content operations, instead of running alongside them with its own rules.
Drafts by default, publishing only on request
How do role-scoped tokens limit what an AI agent can reach in Sanity?
Role-scoped tokens limit what an agent can reach in Sanity because every query and mutation runs under the role attached to the token. The Content Lake enforces that role no matter which runtime the agent runs in. By default, all permissions are set to No access, so the agent can reach only what you grant.
The built-in roles cover the common agent shapes. Viewer gives read-only access to all datasets, which suits grounding agents. Contributor gives read and write access to draft content but can't publish. For narrower scope, Enterprise custom roles can use GROQ filters to grant access to specific content types only. A support-copy agent could then edit FAQ documents and nothing in pricing or legal. Permissions are granted per dataset, and tags group datasets that share permissions.
Two details shape how you design agent roles. First, permissions are additive, so a GROQ-filtered resource can't narrow a broad grant later. If a role already reads everything, adding a filtered resource doesn't restrict it. Start restrictive and add grants one dataset at a time.
The second detail is whose token the agent carries. If you pass along the signed-in user's token, the agent reads and acts as that user. In code, the difference is a single line: sanityClient.withConfig({ token: userToken }). The agent retrieves only what that user can see and does only what that user could do. Its actions are also recorded against the user rather than the model. The agent inherits the security model you already run, with the same permissions and the same rate limits. There's no separate AI security layer to maintain.
A service-account token is the exception. It's for agents that must work across accounts, such as a support tool that looks up any customer's order. Only load that tool into a session where the agent has confirmed a support agent is in control. Demos run on service accounts because demos have no users. Production agents shouldn't.
Plan availability for agent scoping
How do you keep a person in the loop when AI agents change content?
Keeping a person in the loop means the agent can propose, check, and stage changes, while publishing stays with a human or with an explicit, reviewed rule. Sanity Context supports this with the same editorial tools that govern the website, so agent changes and human changes go through one process.
Content Releases are where changes are staged. Agent writes that land in a release version wait there until a person reviews and ships the release. Agent instructions can follow the same path. When the system prompt lives as a document in the Studio with field-level ownership, editors can tune the agent's voice and scope without a code change. A new set of instructions can be staged in a Content Release and previewed before it goes live, just like a homepage update.
Functions handle automated reactions to content changes. You write them in TypeScript or JavaScript, deploy them to the Content Lake, and trigger them on create, update, and delete events. The older publish event is deprecated and shouldn't be used. Publishing a document fires an update event on the published document instead. Two flags control which events count. includeDrafts (default false) covers drafts.** events, and includeAllVersions (default false) covers versions.** events from Content Releases and Scheduled Drafts. A Function that validates agent drafts, for example, needs includeDrafts set to true.
Workflows store the editorial process as data next to the content. The feature is in Beta, opt-in, and may change before general availability. A person submits a draft, and an agent checks it against your style guide and either moves it forward or sends it back. The stages are where a human keeps control. Because the process leaves a record in the content itself, an audit question like what was published without legal review becomes a single GROQ query.
Each layer has its own job. The sandbox contains the runtime, and the gateway limits the tools. The content layer decides what the agent can reach and who publishes.
Sanity Context vs sandbox, gateway, and service-token approaches to agent control
| Feature | Sanity | E2B | Docker MCP Gateway | Service token in code |
|---|---|---|---|---|
| What the layer controls | Which documents, datasets, and content types an agent can read or change, enforced by the role on the token that every query and mutation runs under. | Where agent code runs: one Firecracker microVM per session, so untrusted code can't reach the host or other sessions. | Which MCP servers and tools an agent can call, with Cedar permit and forbid policies on server registration, tool listing, and tool calls. | Whatever the token's role allows. One service-account token in agent code usually gives the same broad scope to every session that loads it. |
| Network and credential isolation | Not a runtime. Sanity governs access inside whatever sandbox or harness the agent uses, and the token's role limits what it can reach even if a credential leaks. | Built in: egress policies per sandbox, and the enterprise offering keeps credentials outside the guest so agent code can't read them. | Runs each MCP server in an isolated container, which limits what a compromised server can touch on the host. | None on its own. A token in an environment variable can be read by any code the agent runs unless a sandbox or secret injection protects it. |
| Content-level read scope | Default No access. Viewer is read-only; Enterprise custom roles use GROQ filters to limit access to specific content types, granted per dataset. | Not in scope. A call to an allowed content API returns whatever the injected credential permits; the sandbox doesn't inspect documents. | Tool level only. A policy can allow or forbid a read tool, but it can't control which documents that tool returns once called. | Set once by the token's role. Narrowing access per user or per content type has to be hand-written into each tool's query. |
| Draft versus publish control | Agent Actions never change a published document by default. They create a draft, and writing to published content requires an explicit forcePublishedWrite: true. | No concept of draft or published state. A write that leaves the sandbox lands wherever the content API and token send it. | Can forbid a publish tool entirely, but can't tell whether an allowed update tool is changing a draft or a live document. | Depends on how each tool is coded. If the token can publish, any bug or injected instruction can publish too. |
| Staging agent changes for review | Pass a Content Release version ID as _id and the agent writes into a release. A person reviews and ships the whole release. | Not in scope. Staging and review happen in whatever backend the sandboxed code writes to, under that backend's own rules. | Not in scope. The gateway sees tool calls, not the editorial state of the content those calls change. | Has to be built per project, usually as a custom review queue or a separate staging environment the agent writes into. |
| Read-only grounding path | Context MCP is a hosted read-only endpoint, so a grounding agent connected to it has no way to write content at all. | Possible, but a read-only agent that runs no code gains little from a microVM, because the sandbox protects execution, not reads. | Can expose only a server's read tools through an allow-list policy, which is a sound way to keep a mixed MCP setup read-only. | Read-only only if the token's role is read-only. Reusing an editor or admin token quietly gives a chat agent write access. |