Skip to main content
Sandboxes run untrusted or short-lived code in an isolated microVM and capture its output, useful for agent tool-calls, REPLs, and one-off jobs. The engine’s iii-sandbox router serves the sandbox::* functions and forwards each call to a sandbox adapter. The sandbox-libkrun worker is the adapter that runs the VMs, and Compose installs it from the registry when a project needs it: when the compose file sets engine.sandbox for its own namespace, when it declares a worker that runs in a VM (a bundle worker, or a path:// worker with runtime.base_image), or when you run iii call compose::add worker=iii-sandbox. To change which images the adapter allows, set its configuration under containers.sandbox-libkrun.config_override:
worker-compose.yaml
image_allowlist and custom_images set the images a sandbox can boot. An engine that no Compose file manages has no adapter bound, so its sandbox::* calls fail with S303 until you set a top-level sandbox: section in its engine config. Upgrading to the sandbox worker covers that case and the move from the 0.25 setup.
This page is a quick tour of the sandbox functions. For the adapter’s own documentation, see the sandbox-libkrun docs.
Sandboxes work through the worker’s sandbox::* functions, called the same way as any other function (see Call a function). Images are catalog names such as python or node, not arbitrary OCI references. You drive sandboxes by calling the worker’s sandbox::* functions, the same way you call any function (see Call a function). Images are catalog names such as python or node, not arbitrary OCI references. The examples below capture the new sandbox’s id with jq and stop the sandbox when done so nothing keeps running.

One-shot run

sandbox::run boots a VM, runs a snippet, captures its output, and stops the VM in a single call, so there is nothing to clean up.
lang accepts node, python, shell, or an interpreter path. Pass keep_sandbox=true to leave the VM running afterwards, and stop it yourself with sandbox::stop.

Lifecycle

For multi-step work, create a sandbox, operate on it with its id, then stop it. Every function takes a sandbox_id plus its own fields. A cmd that contains whitespace, with args and argv empty, is split into the binary and its arguments.
For multi-step work, create a sandbox, operate on it with its id, then stop it. Most functions take flat key=value arguments; only nested payloads need --json.