# Agent Markup Language — complete documentation This file concatenates every published AML documentation page for language models, search tools, and offline reference. For the shorter project and editorial overview, see https://agent-markup-language.com/llms.txt. For the navigable documentation website, see https://agent-markup-language.com/docs/. CLI guide: https://agent-markup-language.com/docs/cli/ Install the CLI beside the SDK with `npm install @aml-jsx/sdk && npm install --save-dev @aml-jsx/cli`. Run an exported workflow with `npx aml run ./workflow.tsx`; the file is positional and `--entry` selects a named export. Pages included: 82 --- # AML documentation Build AI agents and multi-agent applications with TypeScript and JSX. Canonical: https://agent-markup-language.com/docs/ Documentation index: https://agent-markup-language.com/docs/ Complete documentation: https://agent-markup-language.com/docs/llms.txt **Documentation shortcuts** - [FAQ](https://agent-markup-language.com/docs/faq/) - [Examples](https://agent-markup-language.com/docs/examples/) - [CLI](https://agent-markup-language.com/docs/cli/) - [Agent skill](https://agent-markup-language.com/docs/agent-skill/) - [Providers](https://agent-markup-language.com/docs/providers/) - [Cookbook](https://agent-markup-language.com/docs/cookbook/) - [Reference](https://agent-markup-language.com/docs/reference/) - [Full documentation for agents](https://agent-markup-language.com/docs/llms.txt) — Give an agent the complete AML documentation in one plain-text file. - [Project llms.txt](https://agent-markup-language.com/llms.txt) — Share the concise project overview and links to the full agent documentation. Agent Markup Language (AML) is a TypeScript framework for building AI agents and multi-agent applications. Use JSX to compose each agent's instructions, tools, input, and execution environment. AML runs that composition, passes results between agents, and manages session and resource cleanup. The built-in providers connect to existing coding agents: Codex, GitHub Copilot, GLM, OpenCode, and Pi. Those agents keep their native model loops and tools. Your application owns the workflow around them, including validation, routing, concurrency, and persistence. ## What will you build? | Start with… | Learn how to… | | -------------------------------------------------------------- | ------------------------------------------------------------------------------- | | [Your first workflow](https://agent-markup-language.com/docs/getting-started/) | Run an Agent, compose specialists, and connect a live provider. | | [An agent with an application Tool](https://agent-markup-language.com/docs/cookbook/tools/) | Grant a typed function to one agent and verify that it is called. | | [A code-review workflow](https://agent-markup-language.com/docs/cookbook/code-review-workflow/) | Gather evidence, run specialists in parallel, and validate their findings. | | [A support router](https://agent-markup-language.com/docs/cookbook/structured-routing/) | Turn a typed result into an application-authorized decision. | | [A workflow test](https://agent-markup-language.com/docs/cookbook/testing/) | Run the same composition with deterministic providers and inspect its behavior. | You can start with a single ``. Add tools, sandboxes, and workspaces when the task needs them. JSX describes the composition; ordinary TypeScript still handles conditions, loops, and application logic. React is not required. ## Install AML **Application runtime** ### Install the SDK Add the public ESM package to a Node.js 26+ TypeScript project. ```sh npm install @aml-jsx/sdk ``` Prefer an executable workflow file without application glue? Use the [experimental AML CLI](https://agent-markup-language.com/docs/cli/). [Configure TSX and run a credential-free workflow →](https://agent-markup-language.com/docs/getting-started/) **Coding agents** ### Install the AML authoring skill Give a compatible coding agent the repository-backed AML API, composition, provider, and security guidance. ```sh npx skills add \ we-are-singular/aml \ --skill aml-jsx ``` The skill guides the agent; your project still needs the SDK and its selected provider executables. [Install, verify, and use the skill →](https://agent-markup-language.com/docs/agent-skill/) Start with the [credential-free tutorial](https://agent-markup-language.com/docs/getting-started/), then use the provider guides and cookbook to assemble a production workflow. Search the complete documentation with `Ctrl` + `K`. --- # AML authoring skill Install, verify, and use AML's repository-backed guidance with coding agents. Canonical: https://agent-markup-language.com/docs/agent-skill/ Documentation index: https://agent-markup-language.com/docs/ Complete documentation: https://agent-markup-language.com/docs/llms.txt The AML authoring skill gives a compatible coding agent the project’s current API, composition rules, provider boundaries, and security guidance. It is useful when an agent is creating or reviewing AML code; it is not a runtime dependency and does not install the SDK or provider executables for your application. ## Install the skill Run the project-local install from the repository where you want an agent to use AML: ```sh title="Terminal" npx skills add we-are-singular/aml \ --skill aml-jsx ``` The Skills CLI detects compatible clients and asks where to install when a choice is required. To target a supported client explicitly, pass its client identifier: ```sh title="Terminal" npx skills add we-are-singular/aml \ --skill aml-jsx \ --agent codex ``` Use a global install only when you want the skill available across projects: ```sh title="Terminal" npx skills add we-are-singular/aml \ --skill aml-jsx \ --global ``` **Note — Client support changes independently** The skill is a portable `SKILL.md`, but automatic discovery depends on the coding client and the installed Skills CLI version. Let the CLI auto-detect your clients, or use `--agent` with an identifier accepted by `npx skills --help`. Project-local installation is the safer default because it travels with the repository context instead of affecting every project. ## Verify the installation List project-local skills as machine-readable output: ```sh title="Terminal" npx skills list --json ``` For a global installation: ```sh title="Terminal" npx skills list --global --json ``` Confirm that the result contains `aml-jsx`. If you targeted one client, you can also filter the listing with `--agent `. The canonical source remains [`skills/aml-jsx/SKILL.md`](https://github.com/we-are-singular/aml/blob/main/skills/aml-jsx/SKILL.md). Review that file when you need to confirm exactly what an installed copy teaches an agent. ## What the skill asks an agent to do 1. **Preflight the project.** Confirm Node.js, ESM, TypeScript, JSX runtime configuration, and the public `@aml-jsx/sdk` package boundary. 2. **Choose explicit providers.** Separate the [Agent, Sandbox, and Workspace responsibilities](https://agent-markup-language.com/docs/providers/) and check each provider’s prerequisites. 3. **Author the smallest complete tree.** Keep ordinary branching and concurrency in TypeScript while AML owns dependency resolution and resource scopes. 4. **Review authority and lifecycle.** Treat [Sandbox isolation](https://agent-markup-language.com/docs/production/security/), credentials, Workspace publication, cancellation, and cleanup as explicit application decisions. 5. **Verify against public contracts.** Use public SDK imports, compile the workflow, and distinguish deterministic checks from vendor integration evidence. The skill routes an agent to focused references for composition, capabilities, resources, providers, and security. It deliberately tells the agent not to invent SDK exports or silently add infrastructure. ## What the skill does not do **It does not install AML** Your application still needs `npm install @aml-jsx/sdk`, an ESM/TSX configuration, and a way to execute or compile TypeScript. **It does not install providers** Codex ACP, GitHub Copilot CLI, GLM ACP, OpenCode, Pi, Docker, and remote provider clients remain explicit deployment prerequisites. **It does not grant authority** A skill can guide code generation, but only your selected Sandbox and deployment policy control processes, files, network access, and credentials. **It does not replace these docs** Provider versions and public contracts can change while AML is pre-stable. Use the linked documentation and source as the current authority. ## A useful first prompt After installation, give the agent a concrete provider and safety boundary instead of asking only for “an AML workflow”: ```text Use the aml-jsx skill to create a credential-free AML workflow first. Then show the smallest change required to run it with Codex inside Docker. Keep secrets outside the AML tree and explain the Workspace save policy. ``` This prompt forces the important choices into the open: deterministic versus live execution, Agent provider, Sandbox authority, and durable state. ## Update or remove Refresh the installed copy when the SDK or docs change: ```sh title="Terminal" npx skills update aml-jsx ``` Remove the project-local skill with the interactive remover, or name it directly: ```sh title="Terminal" npx skills remove aml-jsx ``` For a global installation, add `--global` to the update or remove command. ## Continue from here - [Install the SDK and run the credential-free tutorial](https://agent-markup-language.com/docs/getting-started/). - [Choose an Agent, Sandbox, and Workspace](https://agent-markup-language.com/docs/providers/). - [Read the canonical execution model](https://agent-markup-language.com/docs/concepts/). - [Review production security boundaries](https://agent-markup-language.com/docs/production/security/). --- # Getting started Install AML and resolve a credential-free workflow before connecting a real Agent provider. Canonical: https://agent-markup-language.com/docs/getting-started/ Documentation index: https://agent-markup-language.com/docs/ Complete documentation: https://agent-markup-language.com/docs/llms.txt A deterministic Agent provider runs AML without model credentials, an agent executable, Docker, or a remote account. Agent providers control how sessions run; the same components can use a [live provider](https://agent-markup-language.com/docs/providers/agents/) once its executable and credentials are configured. ## Prerequisites - Node.js **26 or newer** - an ESM project (`"type": "module"` in `package.json`) - TypeScript if you author `.tsx` **Caution — AML is ESM-only** CommonJS `require()` is not a supported package entrypoint. Use ESM imports and a TSX-capable runner or compile the project before running it. If a coding agent will author or review the workflow, optionally install the [AML authoring skill](https://agent-markup-language.com/docs/agent-skill/). The skill teaches the agent the current public API and safety boundaries; it does not replace the SDK installation below. ## 1. Create a project **npm** ```sh title="Terminal" mkdir aml-first-workflow cd aml-first-workflow npm init -y npm pkg set type=module npm install @aml-jsx/sdk npm install --save-dev typescript vite-node ``` **pnpm** ```sh title="Terminal" mkdir aml-first-workflow cd aml-first-workflow pnpm init pnpm add @aml-jsx/sdk pnpm add --save-dev typescript vite-node ``` Add `"type": "module"` to `package.json`. **Note — pnpm may require build-script approval** pnpm 11 can stop the install with `ERR_PNPM_IGNORED_BUILDS` when it blocks transitive native build scripts. Run `pnpm approve-builds`, approve the dependencies named by pnpm, then run `pnpm install` again. This is pnpm's installation policy; AML does not execute those scripts at runtime. Create `tsconfig.json`: ```json title="tsconfig.json" { "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", "target": "ES2024", "strict": true, "skipLibCheck": true, "jsx": "react-jsx", "jsxImportSource": "@aml-jsx/sdk" } } ``` The automatic JSX runtime turns AML elements into AML nodes. React is not installed or involved. `skipLibCheck` skips checking upstream declaration files loaded by the bundled provider adapters while preserving strict checks for your project source. Add one repeatable command to the generated `package.json`: ```json title="package.json" { "type": "module", "scripts": { "aml": "vite-node src/first-workflow.tsx" } } ``` Keep the dependencies added by your package manager when you merge this snippet into the generated file. ## 2. Evaluate your first tree Create `src/first-workflow.tsx`: ```tsx title="src/first-workflow.tsx" import { Agent, AmlRuntime } from "@aml-jsx/sdk" import { DeterministicAgentProvider } from "@aml-jsx/sdk/testing" const agentProvider = new DeterministicAgentProvider({ name: "first-workflow", respond: request => ({ text: `Resolved: ${request.prompt}` }), }) const runtime = new AmlRuntime({ agentProvider }) const result = await runtime.evaluate(Explain what AML evaluates.) console.log(result) ``` Run it with the script you just added: ```sh title="Terminal" npm run aml # or: pnpm aml ``` Expected output: ```text title="Output" Resolved: Explain what AML evaluates. ``` 1. JSX creates an AML node tree; it does not run `` during rendering. 2. `AmlRuntime.evaluate()` validates and resolves the tree. 3. [``](https://agent-markup-language.com/docs/reference/primitives/agent/) builds a normalized request from its system text, prompt, capabilities, and effective scopes. 4. The selected provider returns an `AgentResponse`; the runtime returns its text from the root. 5. The runtime releases acquired resources in reverse order. The [`DeterministicAgentProvider`](https://agent-markup-language.com/docs/reference/testing/#deterministicagentprovider) deliberately echoes a known result and records calls. It is part of the public testing entrypoint, making it useful for tutorials, examples, and workflow tests—not just AML's own test suite. ## 3. Compose an agent team An AML component can combine several agents into a reusable unit. Here two specialists receive the same change description in parallel. Their results become input to a release editor, which starts after both specialists finish. `AML.Component<{ change: string }>` declares the component's input and lets it return any AML value. Import `AML` as a type. When a component accepts nested content, declare it with [`AML.PropsWithChildren` or `AML.PropsWithRequiredChildren`](https://agent-markup-language.com/docs/ast/#optional-and-required-children). Replace `src/first-workflow.tsx` with this credential-free example: ```tsx title="src/first-workflow.tsx" import { type AML, Agent, AmlRuntime, Block, Parallel } from "@aml-jsx/sdk" import { DeterministicAgentProvider } from "@aml-jsx/sdk/testing" const ReleaseBrief: AML.Component<{ change: string }> = ({ change }) => { return ( {change} {change} ) } const provider = new DeterministicAgentProvider({ respond(request) { if (request.system === "Explain the user impact.") { return { text: "Users can export their invoices as CSV." } } if (request.system === "List checks before rollout.") { return { text: "Check account permissions and CSV escaping." } } return { text: request.prompt } }, }) const runtime = new AmlRuntime({ agentProvider: provider }) console.log(await runtime.evaluate()) console.log(`Agent sessions: ${provider.calls.length}`) ``` Run `npm run aml`. The editor fixture echoes the resolved specialist sections, followed by `Agent sessions: 3`. The output contains: ```text Users can export their invoices as CSV. Check account permissions and CSV escaping. Agent sessions: 3 ``` Each `` adds blank lines around its section, so adjacent Blocks produce four newline characters between tags. JSX children otherwise concatenate without automatic separators. The fixture supplies known answers; it demonstrates composition, not live reasoning. `` starts independent branches and preserves their authored output order. Each `` is a separate session. Its result flows upward; its tools and system instructions do not transfer to its parent. The runtime default supplies a provider to every Agent that omits a `provider` prop. To run this team live, keep `ReleaseBrief`, replace the fixture provider using the next section, and remove the `provider.calls` diagnostic. The same pattern is available from a repository checkout as `npm run example -- agent-team`. ## 4. Connect a real Agent The authored node remains the same. Replace the contents of `src/first-workflow.tsx` with one complete tab below, then run the same `aml` script. **Note — There is no universal default provider** Start with the coding harness and model account you already operate. The Codex tab is the shortest path when you have an OpenAI API key; choose OpenCode for its model catalog and native tool policy, or Pi for its extensible Tool and MCP path. The provider comparison explains the trade-offs in detail. **Codex** ```tsx title="src/first-workflow.tsx" import { Agent, AmlRuntime, codexAgent } from "@aml-jsx/sdk" const apiKey = process.env.OPENAI_API_KEY if (!apiKey) throw new Error("OPENAI_API_KEY is required") const runtime = new AmlRuntime({ agentProvider: codexAgent({ apiKey, model: "gpt-5.6-luna", reasoningEffort: "low", }), }) const result = await runtime.evaluate(Describe this project in three bullets.) console.log(result) ``` Install and verify the ACP adapter version exercised by this repository, then supply a credential through your shell or secret manager: ```sh npm install --global @agentclientprotocol/codex-acp@1.4.0 @openai/codex@0.147.0 codex-acp --help codex --version export OPENAI_API_KEY="your-development-key" npm run aml ``` Do not commit the key or place it in a Workspace. See the [Codex guide](https://agent-markup-language.com/docs/providers/agents/codex/) for executable overrides, `CODEX_API_KEY`, model precedence, permissions, and Sandbox compatibility. **OpenCode** ```tsx title="src/first-workflow.tsx" import { Agent, AmlRuntime, opencodeAgent } from "@aml-jsx/sdk" const apiKey = process.env.OPENCODE_API_KEY if (!apiKey) throw new Error("OPENCODE_API_KEY is required") const runtime = new AmlRuntime({ agentProvider: opencodeAgent({ env: { OPENCODE_API_KEY: apiKey }, model: "opencode-go/deepseek-v4-flash", }), }) const result = await runtime.evaluate(Describe this project in three bullets.) console.log(result) ``` Install and verify the OpenCode executable, then configure a model provider: ```sh npm install --global opencode-ai@1.18.30 opencode --version export OPENCODE_API_KEY="your-development-key" npm run aml ``` The OpenCode configuration passes the model credential through `env`. An interactive `opencode auth login` alone is insufficient for AML's default isolated session: AML gives each invocation a private `XDG_DATA_HOME`. To use file-based login, stage the required credentials in a dedicated data directory and pass its path through [`env.XDG_DATA_HOME`](https://agent-markup-language.com/docs/providers/agents/opencode/#install-and-verify). Select a model available to that account. **Pi** ```tsx title="src/first-workflow.tsx" import { Agent, AmlRuntime, piAgent } from "@aml-jsx/sdk" const apiKey = process.env.OPENCODE_API_KEY if (!apiKey) throw new Error("OPENCODE_API_KEY is required") const runtime = new AmlRuntime({ agentProvider: piAgent({ command: "pi-acp", env: { OPENCODE_API_KEY: apiKey }, model: "opencode-go/deepseek-v4-flash", piCommand: "pi", }), }) const result = await runtime.evaluate(Describe this project in three bullets.) console.log(result) ``` Install and verify the ACP bridge and Pi CLI: ```sh npm install --global pi-acp@0.0.33 @earendil-works/pi-coding-agent@0.84.2 pi --version command -v pi-acp export OPENCODE_API_KEY="your-development-key" npm run aml ``` This follows the repository smoke path with DeepSeek V4 Flash through OpenCode Go. If you select another Pi model provider, change the model identifier and forward that provider's credential instead. The [Pi guide](https://agent-markup-language.com/docs/providers/agents/pi/) explains when AML generates a wrapper and how to install `pi-mcp-adapter` for Tools, authored MCP servers, or structured output. **Tip — Provider selection is lexical too** Set a default on `AmlRuntime`, or pass `provider` directly to an `` when one subtree needs a different model harness. A direct prop wins over the runtime default. Compare the built-in profiles in [Choose an Agent](/docs/providers/agents/). ## 5. Add files and command execution when needed [``](https://agent-markup-language.com/docs/reference/primitives/file/) writes through the nearest active [``](https://agent-markup-language.com/docs/reference/primitives/workspace/) or [``](https://agent-markup-language.com/docs/reference/primitives/sandbox/) filesystem. [` ) ``` The inline shell starts a child process and waits for it. `AML_PROCESS_SAFETY_PID_FILE` is optional; when set, it records the child PID so cleanup can be checked independently. The Sandbox lease tracks the shell process, and local spawning creates a process group, so releasing the lease terminates the shell and its `sleep` descendant rather than abandoning the child. The command does not install its own cleanup abstraction. Process lifetime belongs to the Sandbox provider, and application interruption belongs to the runner. ## Main file: export the tree The maintained file combines the imports and the two blocks above, then exports the AML value directly: ```tsx title="cli-process-safety.tsx" import { cwd } from "node:process" import { localSandbox, Sandbox, Script } from "@aml-jsx/sdk" // LongRunningProcess is the AML tree defined above. export default LongRunningProcess ``` Do not construct `AmlRuntime` in this file. `aml run` must own the runtime for its signal controller to cover the Script, Sandbox release, diagnostics, and final exit code as one lifecycle. ## Run and interrupt it From the repository root: ```sh title="Terminal" npm run build AML_PROCESS_SAFETY_PID_FILE=/tmp/aml-process-safety.pid \ node apps/cli/dist/index.js run ./examples/src/operations/cli-process-safety.tsx --trace ``` Wait for `/tmp/aml-process-safety.pid` to appear, then press `Ctrl`+`C` once. The CLI starts graceful cancellation and allows up to ten seconds for cleanup. A second interrupt explicitly stops waiting; it cannot guarantee JavaScript cleanup completed. Check the conventional status and recorded child PID: ```sh title="Terminal" status=$? pid=$(cat /tmp/aml-process-safety.pid) printf 'exit=%s child=%s\n' "$status" "$pid" kill -0 "$pid" ``` Expected: `exit=130 ...`, and `kill -0` fails because the child no longer exists. If you send `SIGTERM` from another terminal, expect status `143`. ## What happens on the first signal 1. The CLI's process-signal owner aborts the signal passed to `runtime.evaluate()` and starts its ten-second forced-exit deadline. 2. The active Script receives cancellation through the Sandbox command signal. The local provider terminates the tracked process group. 3. AML unwinds the evaluation and releases the acquired Sandbox lease. Release is still called even though the Script did not complete normally. 4. Only after evaluation cleanup settles does the CLI dispose its signal listeners and deadline, set the conventional exit code, and return control to Node. ## Failure and safety boundaries **Caution — Graceful process safety is not crash recovery** `SIGKILL`, a runtime crash, host loss, and power failure cannot execute JavaScript cleanup. Remote or durable providers still need platform TTLs, reapers, and incident detection. - `localSandbox()` executes trusted host commands. Replace it with an appropriately configured container or remote Sandbox for hostile code. - The ten-second deadline bounds shutdown; it does not prove a remote provider reached a terminal state before forced exit. - A second signal is an operator override. Use it only when stopping immediately is more important than completing cleanup. - Application code using `AmlRuntime` directly can use [`ProcessSignalCancellation`](https://agent-markup-language.com/docs/runtime/#process-signals). Do not add a second signal owner around `aml run`. - Remove the optional PID file after the walkthrough; it is verification state, not an AML resource. ## Source and API links - [Maintained CLI process-safety example](https://github.com/we-are-singular/aml/blob/main/examples/src/operations/cli-process-safety.tsx) - [CLI interruption contract](https://agent-markup-language.com/docs/cli/#interrupting-a-run) - [`` and provider cleanup](https://agent-markup-language.com/docs/reference/primitives/sandbox/) - [` ) return await new AmlRuntime({ agentProvider: reviewer }).evaluate( Review only this diagnostic output. Do not claim to have inspected files that are not listed: {evidence} ) } console.log(await new AmlRuntime().evaluate()) ``` ## Run it Save the complete source as `recipe.tsx` in a project configured as shown in [Getting started](https://agent-markup-language.com/docs/getting-started/). Verify the required image, then run that exact workflow: ```sh title="Terminal" docker image inspect node:26 npx vite-node recipe.tsx ``` A successful run prints JSON evidence from the container and then a reviewer message containing that evidence. File names vary with the directory from which the program is launched. ## Observable result The diagnostic emits a line shaped like: ```text {"files":["README.md","package.json"]} ``` The final `` receives that line as ordinary prompt data. Docker Sandbox is acquired and released around the ` ) console.log(await readFile(join(directory, "output.txt"), "utf8")) ``` For a real Agent, replace the image with one that contains the ACP executable and use the corresponding Agent provider inside the same [``](https://agent-markup-language.com/docs/reference/primitives/sandbox/). Do not use a public tutorial image as evidence that your Agent/Sandbox pair is deployable. ## Lifecycle 1. AML resolves the active Workspace directory or the configured fallback. 2. Docker starts a named detached container with `--rm`, the selected image, optional runtime user, `/workspace` bind mount, logical guest cwd, and a keepalive `sh` process. 3. If startup fails, AML attempts to remove the named container and aggregates startup and cleanup failures when both fail. 4. The optional setup command runs after the mount is ready. A non-zero result rejects acquisition and triggers container cleanup. 5. `exec()` invokes `docker exec` with the logical guest cwd and explicit environment values. 6. `spawn()` invokes a process-group wrapper inside the container, captures output from the beginning, and can kill the remote process group. 7. Complete-file reads and writes use confined guest paths plus `docker cp`; writes upload a temporary file and rename it over the destination. Agent staging uses a unique writable directory under `/tmp`. 8. Timeout or cancellation of `docker exec` removes the disposable container because the remote command may otherwise survive the local client process. 9. Release removes the container. Because the Workspace is a same-host mount, writes are already present in the host materialization; Workspace save/revision behavior remains the Workspace provider’s responsibility. ## Read-only behavior Docker is the built-in provider that can execute commands with a read-only Workspace mount. AML passes the mount as `/workspace:ro` and still permits `exec()` and `spawn()` against the image filesystem. The Agent may still need writable state outside `/workspace`; its process permissions and image filesystem are separate concerns. Read-only does not mean “no side effects anywhere in the container.” It protects the mounted Workspace. Container-level filesystem, network, process, and credential behavior depends on the image and Docker daemon configuration. ## Security posture The adapter invokes `docker run` with an image, `--detach`, `--rm`, a bind mount, a working directory, and a shell entrypoint. It does not configure: - network isolation or egress policy; - Linux capabilities, seccomp, AppArmor, or SELinux policy; - rootless daemon mode or automatic container-user selection; `user` only passes an explicit identity to Docker; - CPU, memory, PID, or disk limits; - a read-only root filesystem; - secret injection or credential redaction at the Docker daemon boundary. Treat the Docker daemon and selected image as part of your security boundary. Pin trusted image digests, use a hardened daemon/runtime policy, choose a non-root image where appropriate, configure network and resource limits outside AML, and do not mount sensitive host directories. Do not run untrusted model-generated code with a default Docker installation and call that complete hostile-code isolation. ## Failure modes and troubleshooting | Symptom | Cause | What to check | | ------------------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `docker: command not found` | The Docker CLI is absent from the host. | Install/configure the CLI in the application environment. | | Cannot connect to the Docker daemon | The daemon socket or context is unavailable. | Check `docker info` as the same user that runs AML. | | Container exits before acquisition | Image lacks `sh`, cannot start, or has incompatible architecture/permissions. | Run the image manually with the expected user and shell. | | Agent executable not found | The image does not contain the selected ACP command. | Install it in the image or use a trusted setup hook; AML does not install it. | | `Workspace` mount fails | Host source is missing, not a directory, or inaccessible to the Docker daemon. | Verify the active/fallback path and daemon access to the host filesystem. | | Workspace permission denied | The image user cannot access the host-owned bind mount. | Set `user` to the Workspace owner's `UID:GID`, or align ownership in the image. | | `exec` exits with code 126/127 | Command is not executable or not found inside the image. | Check image PATH, executable permissions, architecture, and runtime dependencies. | | Output limit exceeded | Combined command output exceeded `maxOutputBytes`. | Reduce output, use `spawn()`, or raise the limit deliberately. | | Remote command survives cancellation | Docker exec cannot always clean up the child independently. | AML removes the disposable container; inspect daemon logs if termination is delayed. | | Files changed remotely are missing | The container was released before a same-host mount write completed or the command wrote outside `/workspace`. | Keep writes below the mounted root and wait for command completion. | ## References - [Sandbox provider overview](https://agent-markup-language.com/docs/providers/sandboxes/) - [Docker’s security documentation](https://docs.docker.com/engine/security/) - [Docker image and container reference](https://docs.docker.com/reference/) - [AML Docker provider implementation](https://github.com/we-are-singular/aml/blob/main/providers/sandboxes/docker/src/docker-sandbox.ts) - [AML Docker provider tests](https://github.com/we-are-singular/aml/blob/main/providers/sandboxes/docker/tests/docker-sandbox.test.ts) - [Sandboxing architecture](https://github.com/we-are-singular/aml/blob/main/SANDBOXING.md) - [AML specification: Sandbox composition](https://github.com/we-are-singular/aml/blob/main/SPEC.md) --- # Alternative and custom Sandbox images Evaluate third-party images, custom image recipes, and compatibility requirements for AML Sandbox providers. Canonical: https://agent-markup-language.com/docs/providers/sandboxes/images/ Documentation index: https://agent-markup-language.com/docs/ Complete documentation: https://agent-markup-language.com/docs/llms.txt AML's own full and single-Agent images, Docker Hub tags, bleeding-edge GHCR channel, usage, and extension model are documented in [AML Agent Sandbox images](https://agent-markup-language.com/docs/sandbox-images/). Start there unless a third-party image or provider-native recipe is an explicit deployment requirement. This page covers alternatives we have inspected and the compatibility checks required before replacing AML's image. A public image containing the desired Agent is useful evidence, but it does not prove model credentials, network policy, Workspace transfer, entrypoint behavior, or production isolation. ## Replacement image baseline An alternative or custom image must provide the complete executable chain required by the selected Agent plus the tools required by its Sandbox provider: - `sh`, `mkdir`, and `rm` for every image-backed provider; - `tar` for Daytona and Modal Workspace transfer; - the selected ACP Agent executable and its language/native runtime; - a writable home and Workspace path for the configured user; - project dependencies and every command launched by ` ``` ## Result and failures Successful standard output becomes AML text for later composition. A non-zero exit code rejects with `EvaluationError` and includes trimmed stderr detail when available. AML bounds, cancels, and reaps host execution directly; inside a Sandbox, its provider owns those runtime details. Trace spans report `environment="host"` or `environment="sandbox"`. Generated source is executable authority. If [``](https://agent-markup-language.com/docs/reference/primitives/agent/) produces the children of `