Skip to content

AI Sandboxes

A sandbox is a short-lived VM that an AI agent (or a person) creates, runs commands in, and throws away. Use it to let an agent test code on a real kernel with systemd, libvirt or a real network, without giving it access to your other VMs.

Each sandbox:

  • goes on the network and hosts an admin chooses, never wherever the caller asks;
  • is deleted automatically when its time runs out;
  • runs commands through the QEMU guest agent, so there's no SSH, no guest password and no route needed from the console to the sandbox network;
  • is reachable with a sandbox API key, which can use sandboxes and nothing else.

Sandboxes are off until an admin turns them on.

Plain unit tests don't need a sandbox

A CI runner is cheaper for tests that run in a container. Use a sandbox when the test needs a whole VM: installing packages, services, kernel modules, nested virtualization, or a real network.

1. Build the sandbox template

The template needs the QEMU guest agent with command execution allowed. Rocky and RHEL turn that off by default. On any compute node, as root:

dnf install -y guestfs-tools        # once, for virt-customize
./deployment/sandbox/build-sandbox-template.sh

This downloads the Rocky 9 cloud image and writes /var/lib/libvirt/images/sandbox-rocky9_tmplt.qcow2. The image has the guest agent, git, Python 3, Podman and build tools. No password or SSH key is baked in. Then publish it to the sandbox hosts from Content Library.

2. Pick an isolated network

Code under test is untrusted, and so is code an agent wrote. Give sandboxes a port group whose only way out is what tests need: your Git server and package mirrors. It shouldn't reach the hosts' management addresses, the console, or the database. An OVN logical switch with no router, or a VLAN behind a firewall, both work.

3. Turn sandboxes on

Settings → AI Sandboxes (Super Admin):

Setting What it does
Allow sandboxes Off by default. Can't be turned on until a network and placement are set.
Network The isolated port group from step 2.
Placement The cluster whose hosts run sandboxes. Use lab hosts, not production.
Default template Used when a caller doesn't name one, e.g. sandbox-rocky9_tmplt.qcow2.
Default life Minutes a new sandbox lives (default 60).
Max per extend The most one create or extend can set (default 240).
Hard limit Hours from creation after which a sandbox is deleted however often it was extended (default 24).
Per user, max vCPU / RAM / disk Size caps. Per-user quotas and tenant limits apply on top.
Command limit Longest time one command may run (default 3600 s).

Turning sandboxes off stops new ones being created. Existing ones still expire on time.

4. Give an agent a key

Under Settings → My API Keys, generate a key with scope Sandbox and an expiry. That key can call /api/sandboxes and nothing else. It can't list your VMs, open a console, or change these settings.

Connect it to the MCP server the same way as any other key. The agent then has sandbox_create, sandbox_exec, sandbox_exec_result, sandbox_list, sandbox_extend and sandbox_destroy. The console's AI chat panel offers the same tools while sandboxes are on.

Using the API directly

H="X-API-Key: $KEY"
# create (returns the name, e.g. sbx-alice-3f9a1c)
curl -sk -H "$H" -H 'Content-Type: application/json' \
  -d '{"vcpus":2,"memory_mb":4096,"ttl_minutes":90}' https://console/api/sandboxes

# run a command; waits up to wait_s (max 60) for it to finish
curl -sk -H "$H" -H 'Content-Type: application/json' \
  -d '{"command":"git clone https://git.lab/app.git /src && cd /src && make test","timeout_s":900}' \
  https://console/api/sandboxes/sbx-alice-3f9a1c/exec

# still running? poll it
curl -sk -H "$H" "https://console/api/sandboxes/sbx-alice-3f9a1c/exec/42?wait_s=60"

# done
curl -sk -H "$H" -X DELETE https://console/api/sandboxes/sbx-alice-3f9a1c

A command runs as root under /bin/sh -c. The result has the exit code and the last 64 KB of stdout and stderr. Exit code 124 means the command hit timeout_s and was stopped. Put secrets such as a Git deploy token in env: commands are recorded with their results, env values never are.

The first command after creating a sandbox may answer "the guest agent isn't answering yet". The VM is still booting; wait a minute and retry.

What's recorded

  • Creating, extending and destroying a sandbox, and every settings change, go to the audit log.
  • Every command, with who ran it, when, its exit code and output tail, is kept with the sandbox and for 30 days after it's deleted.
  • Expired sandboxes are deleted by the console within a minute of expiring, and the deletion is audited as system.