# AML Agent Sandbox images

Choose, pin, use, and extend AML's full and single-Agent container images.
Canonical: https://agent-markup-language.com/docs/sandbox-images/
Documentation index: https://agent-markup-language.com/docs/
Complete documentation: https://agent-markup-language.com/docs/llms.txt

AML publishes ready-to-use container images for running Agents and AML workflows with [Docker](https://agent-markup-language.com/docs/providers/sandboxes/docker/), [Daytona](https://agent-markup-language.com/docs/providers/sandboxes/daytona/), and [Modal](https://agent-markup-language.com/docs/providers/sandboxes/modal/). The default `full` image contains every built-in Agent. Smaller stable variants contain one Agent while preserving the same AML and system runtime.

- [Stable images on Docker Hub](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags) — Browse versioned releases and moving full or Agent-specific tags.

- [Bleeding edge on GHCR](https://github.com/orgs/we-are-singular/packages/container/package/aml-agent-sandbox) — Inspect the mutable, full dev image built from main.

- [Image changelog](https://agent-markup-language.com/docs/reference/changelog/sandbox/) — Review changes released independently from the AML SDK and CLI.

## What every variant contains

Every image variant is built from the same [`images/sandbox/Dockerfile`](https://github.com/we-are-singular/aml/blob/main/images/sandbox/Dockerfile) and includes:

- the `aml` CLI and `@aml-jsx/sdk`, installed outside `/workspace` so clean mounted workflows can import the SDK;
- Node.js 26 and npm;
- Python 3, pip, and `venv`;
- Git, OpenSSH, curl, CA certificates, jq, ripgrep, patch, Bash, and common shell/archive utilities;
- a Debian Bookworm/glibc runtime and the non-root `aml` user with writable home, `/tmp`, and `/workspace`.

The images deliberately exclude credentials, Agent login state, project dependencies, browsers, cloud CLIs, Docker-in-Docker, compilers, and broad language toolchains. Add project-specific software in a derived image instead of reinstalling it whenever a Sandbox starts.

## Choose a variant

Single-Agent variants are clean builds. They select their Agent dependencies before `npm install`; they do not inherit `full` and delete other Agents in a later layer. This makes the published image smaller both on disk and over the network.

| Variant      | Use it when                                                                                                | Agent packages and commands                                      | Stable tags                             | Docker Hub                                                                                   |
| ------------ | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------- |
| **Full**     | The application may choose different Agents at runtime, or you want the most convenient development image. | Every Agent listed below.                                        | `X.Y.Z`, `X.Y.Z-full`, `latest`, `full` | [Full tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=full)         |
| **Codex**    | Every workflow uses [`codexAgent()`](https://agent-markup-language.com/docs/providers/agents/codex/).                                       | `codex-acp` `1.4.0` and `codex` `0.147.0`.                       | `X.Y.Z-codex`, `codex`                  | [Codex tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=codex)       |
| **Copilot**  | Every workflow uses [`copilotAgent()`](https://agent-markup-language.com/docs/providers/agents/copilot/).                                   | `copilot` `1.0.80`.                                              | `X.Y.Z-copilot`, `copilot`              | [Copilot tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=copilot)   |
| **GLM**      | Every workflow uses [`glmAgent()`](https://agent-markup-language.com/docs/providers/agents/glm/).                                           | `glm-acp-agent` `1.5.0`.                                         | `X.Y.Z-glm`, `glm`                      | [GLM tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=glm)           |
| **OpenCode** | Every workflow uses [`opencodeAgent()`](https://agent-markup-language.com/docs/providers/agents/opencode/).                                 | `opencode` `1.18.18`.                                            | `X.Y.Z-opencode`, `opencode`            | [OpenCode tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=opencode) |
| **Pi**       | Every workflow uses [`piAgent()`](https://agent-markup-language.com/docs/providers/agents/pi/).                                             | `pi` `0.84.2`, `pi-acp` `0.0.33`, and `pi-mcp-adapter` `2.26.0`. | `X.Y.Z-pi`, `pi`                        | [Pi tags](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags?name=pi)             |

The versions above describe the current repository build. The [image package manifest](https://github.com/we-are-singular/aml/blob/main/images/sandbox/package.json) is the source of truth when a dependency changes.

Choose `full` when the Agent is selected dynamically. Choose a single-Agent variant when the application always uses one Agent and image size matters.

**Caution — The image does not select the Agent**

`opencodeAgent()` selects OpenCode; the image only supplies its executable and runtime. Pairing `codexAgent()` with an
OpenCode-only image fails because `codex-acp` and `codex` are deliberately absent.

## Understand the stable tags

[Docker Hub](https://hub.docker.com/r/wearesingular/aml-agent-sandbox) is the canonical stable registry.

- `X.Y.Z` and `X.Y.Z-full` identify the same full release.
- `X.Y.Z-<agent>` identifies the matching single-Agent release.
- `latest` and `full` move to the newest validated full release.
- `codex`, `copilot`, `glm`, `opencode`, and `pi` move to the newest validated release in that Agent lane.

AML's release process treats versioned tags as immutable. It builds and publishes every versioned variant first, runs the matching real Agent smoke against each pushed digest, signs the digests, and only then advances the moving tags. Stable releases also include SBOM and provenance attestations.

Use a versioned tag while evaluating a release, and pin its digest when the exact registry artifact must never change:

```ts title="Pin a stable digest"
import { dockerSandbox } from "@aml-jsx/sdk"

const sandbox = dockerSandbox({
  image: "wearesingular/aml-agent-sandbox@sha256:IMAGE_DIGEST",
})
```

## Bleeding-edge dev image

`ghcr.io/we-are-singular/aml-agent-sandbox:dev` is the public bleeding-edge image built from relevant changes on `main`.

```sh title="Pull the bleeding-edge image"
docker pull ghcr.io/we-are-singular/aml-agent-sandbox:dev
```

The `dev` image intentionally remains full and non-versioned. It is not reduced to a single-Agent dependency set: Codex, Copilot, GLM, OpenCode, and Pi are all present. Normal image cleanup still applies, but there are no `dev-codex`, `dev-opencode`, or other GHCR variant lanes.

The [development image workflow](https://github.com/we-are-singular/aml/blob/main/.github/workflows/agent-sandbox-dev.yml) explicitly builds `IMAGE_VARIANT=full`, runs its deterministic image check and dependency audit, and replaces the mutable `dev` tag. AML's repository smoke matrix uses this channel so changes can be exercised before a stable Docker Hub release.

**Caution — Do not treat dev as a production pin**

`dev` can change after any relevant merge to `main`, has no semantic version, and is not a stable mirror of Docker
Hub. Use it for unreleased integration testing. Use a Docker Hub version or digest for reproducible deployments.

## Pull and inspect an image

Pull the full stable image when you want every Agent:

```sh
docker pull wearesingular/aml-agent-sandbox:latest
```

Pull a versioned single-Agent image when the Agent is fixed:

```sh
docker pull wearesingular/aml-agent-sandbox:X.Y.Z-opencode
docker run --rm wearesingular/aml-agent-sandbox:X.Y.Z-opencode opencode --version
```

Replace `X.Y.Z` with a tag listed on [Docker Hub](https://hub.docker.com/r/wearesingular/aml-agent-sandbox/tags). You can also inspect the shared runtime directly:

```sh
docker run --rm wearesingular/aml-agent-sandbox:X.Y.Z-opencode sh -lc '
  node --version
  npm --version
  python --version
  pip --version
  jq --version
'
```

## Configure the image in AML

Docker, Daytona, and Modal use the full `wearesingular/aml-agent-sandbox:latest` image when their factory receives no image or Daytona snapshot override:

```ts title="Use the default full image"
import { dockerSandbox } from "@aml-jsx/sdk"

const sandbox = dockerSandbox()
```

To use a single-Agent image, configure the matching Agent and Sandbox providers together:

```ts title="Use the OpenCode variant"
import { AmlRuntime, dockerSandbox, opencodeAgent } from "@aml-jsx/sdk"

const runtime = new AmlRuntime({
  agentProvider: opencodeAgent({
    env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
  }),
  sandboxProvider: dockerSandbox({
    image: "wearesingular/aml-agent-sandbox:X.Y.Z-opencode",
  }),
})
```

The same image reference belongs on `daytonaSandbox({ image })` or `modalSandbox({ image })` when those platforms can pull it. Image identity belongs to the provider factory, not an `<Sandbox image="…" />` prop.

## Extend a variant

Start from the smallest variant that contains the selected Agent, then add only the project tools the workflow needs. This example adds the SQLite CLI to OpenCode:

```dockerfile title="Dockerfile"
FROM wearesingular/aml-agent-sandbox:X.Y.Z-opencode

USER root
RUN apt-get update \
    && apt-get install -y --no-install-recommends sqlite3 \
    && rm -rf /var/lib/apt/lists/*

USER aml
WORKDIR /workspace
```

Build the derived image and pass it to AML:

```sh
docker build --tag example/aml-opencode:1 .
```

```ts
import { dockerSandbox } from "@aml-jsx/sdk"

const sandbox = dockerSandbox({
  image: "example/aml-opencode:1",
})
```

Pin the `FROM` reference before publishing the derived image. Build tools are not part of the shared runtime; add them only when a dependency requires compilation, and use a separate build stage when they do not belong in the final image. Keep model, repository, and registry credentials out of image layers.

## Image and Sandbox responsibilities

**The image supplies software**

Operating-system files, Agent executables, interpreters, package managers, and command-line tools.

**The provider supplies execution**

Container or remote-environment creation, Workspace attachment, process transport, cancellation, and cleanup.

**The application supplies policy**

Credentials, network access, resource limits, project dependencies, image pinning, and deployment hardening.

An image is not a complete isolation policy. Validate the selected Agent, credentials, network policy, Workspace behavior, provider limits, and container hardening together before production use.

Continue with [Run AML in a Sandbox image](https://agent-markup-language.com/docs/cookbook/sandbox-image/) for a runnable Docker walkthrough, [alternative and custom images](https://agent-markup-language.com/docs/providers/sandboxes/images/) for third-party recipes and verification guidance, and [production security](https://agent-markup-language.com/docs/production/security/) for the deployment boundary.
