Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
Platform as a Service (PaaS)

secure code execution sandbox for AI agents: hosted options with isolation + network controls

Modal8 min read

AI agents that can execute arbitrary code are both powerful and dangerous. As soon as you let an agent run Python, shell commands, or call external tools, you take on real risk: data exfiltration, cryptomining, lateral movement inside your VPC, or just runaway bills from a while-true loop that fan-outs to a thousand GPUs.

You want two things at the same time:

  • Strong isolation so agents can’t escape their box
  • Tight network controls so they can’t talk to anything you didn’t explicitly allow

This post walks through the hosted options for a secure code execution sandbox for AI agents, with a bias toward real constraints (network egress, GPU access, multi-tenant safety) rather than marketing fluff. I’ll also show what this looks like concretely on Modal using Sandboxes and Python-defined policies.

Quick Answer: A secure code execution sandbox for AI agents needs container-level isolation (ideally gVisor or similar), default-deny network egress, and programmable policies for what each agent is allowed to do. Hosted options like Modal Sandboxes give you gVisor-based isolation, Python-defined compute/runtime, and fine-grained network controls so you can safely run untrusted agent code on elastic CPU/GPU resources.

Why This Matters

LLM agents are getting delegated more authority: refactoring codebases, touching production databases, calling internal APIs, even running shell scripts. Without proper sandboxing, “let the agent run code” is equivalent to “give an internet stranger a terminal on your infra.”

For most teams, the bottleneck isn’t model quality—it’s operational risk and blast radius. If you can’t trust your sandbox, you throttle back agent autonomy, bolt on human approvals everywhere, or stay stuck in demo-land. A good secure execution environment lets you:

  • Safely experiment with more capable tools (code execution, package install, browser automations)
  • Confidently expose agents to user-provided prompts and tools without worrying about prompt injection turning into RCE
  • Keep your cloud and data governance teams comfortable with aggressive agent workloads

Key Benefits:

  • Reduced blast radius: Compromise is contained to a short-lived sandbox with no trust into the rest of your infrastructure.
  • Stronger governance: Network, identity, and data access are defined in code and can be reviewed, audited, and versioned.
  • Faster iteration: You can say “yes” to more powerful agent behaviors because the guardrails are enforced by the platform, not ad hoc scripts.

Core Concepts & Key Points

ConceptDefinitionWhy it's important
Secure sandboxA short-lived, isolated environment (usually a container/VM) where untrusted code can run with strict limits on CPU, memory, filesystem, and network.This is your blast-radius boundary: if the agent is compromised, damage stays inside the sandbox.
Isolation runtime (e.g., gVisor)A hardened container runtime that intercepts syscalls and shields the host kernel from guest workloads.Adds defense-in-depth on top of regular containers, critical for running untrusted or user-generated code.
Network controlsFine-grained rules for what the sandbox can talk to (egress allow/deny lists, per-endpoint auth).Prevents agents from exfiltrating data, scanning internal networks, or calling production APIs they shouldn’t know about.

How It Works (Step-by-Step)

At a high level, a secure code execution sandbox for AI agents looks like this:

  1. The agent decides to run code (e.g., a “run_python” tool).
  2. Your orchestrator spins up a sandbox with strict policies.
  3. The agent’s code executes inside the sandbox and returns results over a narrow, audited channel.

Let’s break that down in a concrete, hosted setup using Modal as the sandbox layer.

1. Define the sandbox environment in code

On Modal, you define your execution environment in pure Python. That includes OS deps, Python packages, hardware, and isolation runtime (Modal containers run under gVisor for sandboxing).

import modal

app = modal.App("agent-sandbox")

# Base image for untrusted agent code
sandbox_image = (
    modal.Image.debian_slim()
    .pip_install(
        "python-dotenv",
        "requests",
        "numpy",
        # keep this list minimal; add tools explicitly
    )
)

# Function that runs arbitrary Python code in a sandbox
@app.function(
    image=sandbox_image,
    timeout=60,            # hard cap: 60s
    cpu=1.0,
    memory=2048,
    concurrency_limit=10,  # avoid noisy-neighbor problems
)
def run_user_code(code: str, input_data: dict) -> dict:
    # Do NOT eval directly in real life – parse and restrict
    local_vars = {"input_data": input_data}
    exec(code, {}, local_vars)
    return {k: v for k, v in local_vars.items() if k not in ("__builtins__",)}

Key points:

  • The environment is explicit and pinned: you choose the base image and packages.
  • Resource limits (cpu, memory, timeout) are enforced by the platform.
  • Containers run inside a gVisor-based runtime for extra isolation versus raw Docker.

2. Add network controls and secrets discipline

For AI agents, the default should be “no network” unless explicitly allowed. In hosted environments, that means:

  • No cloud metadata access
  • No access to your private VPC by default
  • Explicit configuration for any allowed egress

On Modal, you layer this in via:

  • Secrets: only mount what the agent needs (and usually none for untrusted code).
  • Networking: keep the sandbox away from private endpoints; use auth-protected APIs.

Example: the agent is allowed to call just one internal service via a narrow HTTP proxy you control:

INTERNAL_API_URL = "https://agent-gateway.internal.example.com"  # fronted by auth

@app.function(
    image=sandbox_image,
    timeout=30,
    cpu=0.5,
    memory=1024,
)
def run_restricted_http(code: str, request_payload: dict) -> dict:
    import requests

    # This function itself enforces the only egress path
    resp = requests.post(
        INTERNAL_API_URL + "/agent/run",
        json={"code": code, "payload": request_payload},
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()

The agent never sees your broader network surface—just the one gateway URL you chose to expose.

3. Wire the sandbox into your AI agent stack

From the agent’s perspective, the sandbox is just another tool. You take the LLM output, validate it, and ship it to the sandbox via .remote() or .spawn().

from modal import FunctionCall

def agent_tool_run_code(code: str, input_data: dict) -> dict:
    # Kick off sandbox execution
    call: FunctionCall = run_user_code.spawn(code, input_data)
    # Optionally do other work here while it runs
    result = call.get()  # blocks until the sandbox returns or times out
    return result

Operationally:

  • spawn() gives you a scalable job queue for agent code executions.
  • Modal autoscaling brings up containers on demand; when idle, it scales to zero.
  • Logs and execution traces show up in the Modal apps page, so you can debug crazy agent behavior.

Common Mistakes to Avoid

  • Running agent code in the same container as your orchestrator:
    This is the fastest way to accidentally grant filesystem and network access to everything your orchestrator sees (tokens, configs, SSH keys). Always put untrusted code in a separate sandbox with separate credentials and resource limits.

  • Allowing broad network egress “just for now”:
    Letting the sandbox talk to the whole internet or your entire VPC is tempting during prototyping. That’s how you wake up to surprise bills or security incidents. Start from a default-deny posture and selectively add the minimum URLs or services the agent actually needs.

Real-World Example

Say you’re building a coding agent that refactors user repositories. You want it to:

  • Clone a Git repo snapshot
  • Run static analysis / tests
  • Suggest patches or even apply them via a PR

Constraints from your security team:

  • The agent must never see production secrets.
  • The agent must not talk to internal databases.
  • If compromised, the worst-case is it wastes some CPU and accesses only the repo snapshot.

On Modal, you’d:

  1. Store the repo snapshot in a Volume or object store; the sandbox gets read-only access.
  2. Define a sandbox function that can run pytest and ruff but has no network and no secrets.
  3. Expose a single @modal.fastapi_endpoint that your orchestrator hits to trigger a sandbox run for a specific commit.

The result: the agent gets a “fake” local dev environment—full tooling, the repo, test runner—but no path to your VPC, no production tokens, and no persistent state beyond what you explicitly commit to storage.

Pro Tip: Treat sandbox specs like an API surface. Version them, pin dependencies tightly, and avoid “one mega-sandbox” that does everything. Instead, define multiple narrow sandboxes: one for code analysis, one for browser automation, one for batch data transforms. Narrow tools are easier to reason about and lock down.

Summary

A secure code execution sandbox for AI agents is not just “run Docker somewhere.” To be safe in production, you need:

  • Strong isolation (gVisor-style sandboxing, resource limits, short-lived containers)
  • Default-deny network with explicit, narrow egress paths
  • Code-defined infrastructure so you can review and evolve policies like any other part of your stack

Hosted platforms like Modal give you this as a Python API: you define Images, Functions, hardware, and policies in code, then let the platform handle fast autoscaling, gVisor isolation, and observability. That’s what lets you safely give agents powerful tools without handing them the keys to your entire cloud.

Next Step

Get Started