Skip to main content

Sandbox Modes

AgentVisor™ supports multiple sandbox modes. Docker and gVisor are both production-grade; gVisor adds syscall-level interception for slightly stronger defense-in-depth and is the default for built images. Docker runs on any platform that supports Docker.

What "sandbox" means in AgentVisor

A sandbox is a security isolation boundary — a hardened execution environment where agent code runs fully isolated from the host with no direct access to the network, filesystem, processes, or credentials. This is a production-grade boundary, not a test environment.

The sandbox is the substrate for confinement, not a substitute for it. Isolation is what makes mediation non-bypassable; together with credential brokering, policy decisions on every outbound effect, and a host-side record, it yields a confined agent.

Overview​

ModePlatformIsolation LevelHardeningNotes
gvisorLinuxContainer + Syscall interceptionFullStrongest isolation; default for built images
dockerLinuxContainerFullCross-platform; production-grade
dockermacOS/WindowsContainerFull†Same posture as Docker/Linux; outbound restriction via in-guest nftables
noneAnyNoneNoneNo isolation; agent development and debugging only

†Docker on macOS/Windows uses network_filtering (in-guest nftables) instead of --network=none because TCP transport to host.docker.internal is required. The agent's effective outbound network restriction is equivalent.

gVisor Mode
Linux Only
​

Syscall-level isolation — strongest security available, recommended for Linux production deployments.

Default for Built Images

gVisor is the default sandbox mode when deploying containers built with agentvisor build. It is recommended for Linux production deployments where slightly stronger isolation is preferred.

agentvisor serve ./my-agent --sandbox=gvisor

# Interactive terminal session with gVisor isolation
agentvisor exec ./my-agent --sandbox=gvisor
Local gVisor Installation

Container images built with agentvisor build already include gVisor — you get gVisor sandbox isolation on any platform through the normal build and deploy flow.

Installing gVisor's runsc locally is only needed if you want to run agentvisor serve --sandbox=gvisor directly on a Linux workstation:

curl -fsSL https://gvisor.dev/archive.key | sudo apt-key add -
sudo add-apt-repository "deb https://storage.googleapis.com/gvisor/releases release main"
sudo apt-get update && sudo apt-get install runsc
Platformagentvisor build (gVisor)Local --sandbox=gvisor
macOS (Intel/Apple Silicon)YesNo
Windows (with Docker Desktop)YesNo
Linux (x86_64/arm64)YesYes

How It Works​

  1. Host runtime creates OCI bundle
  2. runsc (gVisor runtime) spawns sandbox
  3. Sentry (userspace kernel) intercepts all syscalls
  4. Network disabled, only Unix socket available

Isolation Features​

gVisor provides a userspace kernel (Sentry) that intercepts every syscall before it reaches the host kernel. AgentVisor layers additional hardening on top:

From gVisor:

  • Syscall interception: Every syscall goes through Sentry
  • No direct kernel access: Kernel vulnerabilities don't expose host

Added by AgentVisor:

  • Network isolation: network=none configuration — no network interface in the sandbox
  • Resource limits: cgroups v2 enforcement of memory_limit, cpu_limit and pids_limit, governed by the resource_limits hardening group. Always on in docker mode. In gvisor mode it needs the host runtime to run as root with a writable cgroup v2 mount (typically a privileged container); otherwise set the limits on the container or pod running the host runtime
  • Privilege separation: OpenSSH-style privsep with UID 2000 main process
  • Per-agent UID isolation: Unique UIDs (2001+) prevent cross-tenant memory reads
  • Environment curation: Allowlist for system env vars, blocklist for user-supplied vars

Advantages​

  • Strongest isolation available
  • Kernel vulnerabilities don't affect host
  • Comprehensive syscall filtering
  • Defense in depth

Privilege Modes​

gVisor can run in two modes: rootless (default) or privileged.

Rootless Mode (Default)​

gVisor creates a user namespace internally via CLONE_NEWUSER combined with --network=none. Container images built with agentvisor build have uidmap and subuid/subgid pre-configured for this.

Kernel Prerequisites

Rootless mode requires unprivileged user namespaces enabled on the host kernel:

  • Linux 5.15+ supports this by default on most distributions
  • Some distributions (Debian, Ubuntu 23.10+) require: sysctl -w kernel.unprivileged_userns_clone=1
  • Verify with: cat /proc/sys/user/max_user_namespaces (should be > 0)

These prerequisites only matter when running runsc directly on a host; container images from agentvisor build handle the rest.

# CLI — rootless is the default
agentvisor serve ./my-agent --sandbox=gvisor

# Docker — both flags required: seccomp and AppArmor can each block CLONE_NEWUSER
docker run --security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
-p 8090:8090 \
my-agent:v1

Privileged Mode​

Opt-in mode that requires Docker --privileged. Provides full gVisor capabilities with maximum defense-in-depth, including DirectFS for fastest I/O.

# CLI — opt in with --rootless=false
agentvisor serve ./my-agent --sandbox=gvisor --rootless=false

# Docker — must run as root with --privileged
docker run --user root --privileged -p 8090:8090 -e AGENTVISOR_GUEST_ROOTLESS=false my-agent:v1

Mode trade-offs:

AspectRootless (default)Privileged
Docker flags--security-opt seccomp=unconfined --security-opt apparmor=unconfined--user root --privileged
Filesystem9P filesystem (slower)DirectFS (fastest)
Defense in depthReduced (per gVisor docs)Full
Privilege requiredNone (zero-capability)Root-equivalent
Kernel prerequisitesUnprivileged userns + uidmapNone
Automatic Privilege Dropping

In rootless mode (default), the process never starts as root — no privilege is required or dropped. In privileged mode, the host runtime starts as root only to initialize the gVisor sandbox, then permanently drops privileges to uid/gid 1000 (unprivileged agentvisor user) via irreversible setuid()/setgid() syscalls. All subsequent operations run as the unprivileged user.

When to use privileged mode
  • When maximum I/O performance (DirectFS) is required
  • On hosts without unprivileged user namespace support
  • When your environment already allows --privileged and you want full defense-in-depth
Rootless limitations
  • Performance: Uses 9P filesystem instead of DirectFS
  • Symlinks: Container root path must not contain symlinks
  • Isolation: Some defense-in-depth guarantees are reduced per gVisor documentation

When to Use​

  • Production deployments
  • Multi-tenant environments
  • Running untrusted code
  • Regulated industries

Docker Mode​

Docker container isolation — a production-grade isolation boundary that runs the guest in a Docker container.

Default for the CLI

Docker is the default sandbox mode for agentvisor run, agentvisor serve, and agentvisor exec because it works on any platform (Linux, macOS, Windows) without extra host setup.

agentvisor serve ./my-agent

How It Works​

  1. Host runtime starts on the host machine
  2. Guest container started via Docker API
  3. Host and guest communicate over a hostlink session, carried by UDS on Linux or TCP+mTLS on macOS/Windows (see Hostlink Transport below)
  4. Agent runs inside the container

The hostlink session (see Architecture) is the multiplexed gRPC connection between the host runtime and the guest sandbox. By default (guest.docker_transport: auto), the wire-level transport depends on host OS:

  • Linux: Unix domain socket bind-mounted into the container. OS-level isolation; no TLS needed.
  • macOS / Windows: TCP + mTLS via host.docker.internal. UDS bind-mounts don't cross the Docker Desktop VM boundary, so AgentVisor falls back to TCP — and mTLS keeps the channel authenticated and encrypted across that boundary. The mTLS credentials are short-lived and scoped to the sandbox lifetime.

Remote or Sibling Docker Daemon​

A Linux host isn't always a guarantee that the Docker daemon shares a filesystem with the host runtime — a remote Docker daemon, or a sibling daemon reached over DOCKER_HOST (for example, a Docker-in-Docker CI topology), can't see a UDS bind-mount created outside its own container, even though the host reports Linux. Two config keys make the transport and advertised host address explicit instead of relying on OS auto-detection:

  • guest.docker_transport (AGENTVISOR_GUEST_DOCKER_TRANSPORT): auto (default, GOOS-based as above), uds (force UDS), or tcp (force TCP + mTLS even on Linux).
  • guest.host_link_advertise_host (AGENTVISOR_GUEST_HOST_LINK_ADVERTISE_HOST): the address the guest dials back to reach the host when TCP transport is selected. Empty (default) keeps host.docker.internal; set this when the daemon reaches the host runtime under a different name.

When docker_transport: tcp is selected explicitly (rather than via the macOS/Windows auto-path), the hostlink listener binds all interfaces instead of loopback-only, since a remote or sibling daemon is a real network peer rather than a VM-proxied guest — mTLS remains the access control in that case. There is no automatic discovery of a working host_link_advertise_host value for a given topology; an incorrect value fails the connection rather than silently falling back to a guess.

Advantages​

  • Works on macOS, Windows, and Linux
  • Container-level isolation
  • Uses familiar Docker tooling
  • Default mode — no extra flags needed

Limitations​

  • Uses TCP instead of Unix sockets on macOS/Windows (Docker Desktop VM limitation)
  • Docker Desktop VM overhead on non-Linux platforms
  • Does not include syscall-level interception (use gVisor on Linux if that layer matters)

When to Use​

  • Development and production on any platform that supports Docker
  • Cross-platform deployments (Linux, macOS, Windows)
  • CI/CD environments
  • Production on non-Linux hosts (or Linux hosts where gVisor's runsc is not available)

Unsandboxed Mode​

No isolation — runs the agent directly in your local environment. Mediation is bypassable in this mode, so the agent is unconfined.

agentvisor serve ./my-agent --sandbox=none
Setup Required

Running with --sandbox=none requires a Python virtual environment with the AgentVisor SDK installed. See Local Development Setup for complete setup instructions.

How It Works​

  1. Host runtime starts directly (no container)
  2. Agent process spawned as a child process
  3. HTTP proxy runs in the same process
  4. Policy enforcement still applies

Advantages​

  • Fast startup
  • Easy debugging with standard tools
  • No container overhead
  • Works on any platform

Limitations​

  • No security isolation
  • Agent has full filesystem access
  • Agent could bypass proxy (if malicious)
  • Requires manual environment setup (e.g., Python venv for LangGraph agents)

When to Use​

  • Debugging agent code
  • Quick iteration with breakpoints
  • When Docker is not available

Granular Hardening​

AgentVisor's security hardening is organized into seven feature groups. Each group defaults to auto, which enables features when supported by the sandbox type.

How the security-layer counts relate

You may see AgentVisor's sandbox security described with three different numbers. Each counts the same defense-in-depth architecture at a different level of granularity: 7 feature groups here (the independently-configurable guest.hardening knobs), 12 implementation-level hardening mechanisms enumerated in Guest Sandbox Hardening (several groups above cover more than one mechanism), and 14 independent security layers in Why AgentVisor — a broader, product-level count that also includes protections outside guest.hardening's scope entirely, such as credential brokering and stdio MCP server sandboxing. None of these numbers contradicts another.

Hardening Feature Groups​

Feature GroupWhat It Controls
process_isolationPrivilege separation, UID isolation, capability dropping
env_curationEnvironment variable curation (allowlist for system env, blocklist for user vars), umask 0077
network_isolationLoopback-only networking (--network=none)
network_filteringIn-guest nftables ruleset restricting outbound traffic to loopback + hostlink only
filesystem_hardeningRead-only rootfs, seccomp profiles, tmpfs mounts
kernel_hardeningCapability bounding set, NoNewPrivileges, user namespace blocking
resource_limitsEnforcement of the sandbox-wide memory_limit, cpu_limit and pids_limit through cgroups

Configuration Values​

ValueBehavior
autoEnable if supported by sandbox type (default)
enabledForce enable — fails startup if not supported
disabledForce disable — WARNING logged

Auto-Detection Matrix​

Sandbox TypePlatformprocess_isolationenv_curationnetwork_isolationnetwork_filteringfilesystem_hardeningkernel_hardeningresource_limits
gvisorLinux✓✓✓—✓✓✓†
dockerLinux✓✓✓—✓✓✓
dockermacOS/Windows✓✓—✓✓✓✓
noneAny✗✗✗✗✗✗✗

† gvisor enforces the sandbox-wide limits only when the host runtime runs as root with a writable cgroup v2 mount (for example a privileged container), so resource_limits: auto resolves to off in the default rootless deployment. enabled fails startup there instead.

network_isolation and network_filtering are mutually exclusive: Linux modes use --network=none (OS-level); Docker on macOS/Windows uses in-guest nftables instead, achieving equivalent outbound restriction.

Configuration Example​

guest:
hardening:
process_isolation: auto # AGENTVISOR_GUEST_HARDENING_PROCESS_ISOLATION
env_curation: auto # AGENTVISOR_GUEST_HARDENING_ENV_CURATION
network_isolation: auto # AGENTVISOR_GUEST_HARDENING_NETWORK_ISOLATION
network_filtering: auto # AGENTVISOR_GUEST_HARDENING_NETWORK_FILTERING
filesystem_hardening: auto # AGENTVISOR_GUEST_HARDENING_FILESYSTEM_HARDENING
kernel_hardening: auto # AGENTVISOR_GUEST_HARDENING_KERNEL_HARDENING
resource_limits: auto # AGENTVISOR_GUEST_HARDENING_RESOURCE_LIMITS
Use auto for most deployments

The auto setting is recommended for most deployments. It enables all hardening features supported by your sandbox type without manual configuration.

Comparison​

Note: Both docker and gvisor are production-grade. The difference is that gVisor adds a userspace kernel that intercepts every syscall, while Docker relies on container isolation and seccomp filtering. none has no isolation and is for local development only.

Configuration​

Startup/shutdown timeouts are available in gvisor and docker modes.

Resource limits (memory_limit, cpu_limit, pids_limit) apply to the sandbox as a whole and are governed by the resource_limits hardening setting. In docker mode they map to Docker's --memory/--cpus/--pids-limit flags. In gvisor mode they are enforced through a cgroup that the host runtime hands to runsc, which requires the host runtime to run as root with a writable cgroup v2 mount (for example a privileged container). In the default rootless deployment that is not available: resource_limits: auto resolves to off, the startup log shows resource_limits=false, and a warning names any limit you changed. Apply memory, CPU and process limits to the container or pod that runs the host runtime instead (for example Kubernetes resource limits or docker run --memory), or set resource_limits: enabled to fail startup rather than run without them.

memory_limit is a hard cap on memory plus swap: a sandbox that exceeds it is killed, not paged out. cpu_limit is a number of CPUs (0.5 = half a CPU). In gvisor mode pids_limit counts the sandbox's host threads rather than the processes inside it, and exceeding it stops the whole sandbox, so keep it generous. Process count per agent run is separately bounded by nproc_soft_limit/nproc_hard_limit.

See the Configuration Reference for the full environment variable list.

Docker/Kubernetes Deployment​

For container deployments, the sandbox mode is configured via environment variable. Images built with agentvisor build default to gVisor, so AGENTVISOR_GUEST_SANDBOX can be omitted unless you need to override it.

Rootless Mode (Default)​

No extra capabilities required. Images built with agentvisor build work out of the box:

# docker-compose.yml (rootless — default)
services:
agentvisor:
image: my-agent:v1
security_opt:
- seccomp=unconfined # Required: default seccomp profile may block CLONE_NEWUSER
- apparmor=unconfined # Required on Ubuntu 24.04+, GKE, AKS
ports:
- "8090:8090"
# Kubernetes deployment (rootless — default)
apiVersion: v1
kind: Pod
spec:
containers:
- name: agent
image: my-agent:v1
securityContext:
seccompProfile:
type: Unconfined # Required: default seccomp profile may block CLONE_NEWUSER
appArmorProfile:
type: Unconfined # Required on Ubuntu 24.04+, GKE, AKS

Privileged Mode​

Opt-in when you need DirectFS performance or lack unprivileged user namespace support:

# docker-compose.yml (privileged)
services:
agentvisor:
image: my-agent:v1
user: root
privileged: true
environment:
- AGENTVISOR_GUEST_ROOTLESS=false
# Kubernetes deployment (privileged)
apiVersion: v1
kind: Pod
spec:
containers:
- name: agent
securityContext:
privileged: true
runAsUser: 0
env:
- name: AGENTVISOR_GUEST_ROOTLESS
value: "false"

Choosing a Mode​

ScenarioRecommended Mode
Local development (default)docker
Debugging/breakpointsnone
Production on Linux (strongest isolation)gvisor
Production on non-Linux / cross-platformdocker
Multi-tenant SaaS on Linuxgvisor
CI/CD testingdocker
Interactive sessions (exec)docker or gvisor