Skip to content

Container Execution Guide

This guide walks you through setting up the container runtime, building the agent runner image, and configuring mount security before running agents in containers.

Step 1: Install a Container Runtime

Backend.AI GO supports two container runtimes:

  • Apple Container — preferred on Apple Silicon Macs, lighter-weight than Docker
  • Docker — supported on all platforms (macOS, Windows, Linux)

Apple Container (macOS Apple Silicon only)

  1. Download the Apple Container installer from the Apple Container GitHub releases page.

  2. Open the downloaded .pkg file and follow the installation wizard.

  3. After installation, verify it works:

    container --version
    
  4. Start the container system service:

    container system start
    

Platform Support

Backend.AI GO supports Apple Silicon Macs from macOS 15 (Sequoia). Apple Container itself requires macOS 26 (Tahoe). Use Docker on macOS 15 through 25. Intel Macs are not supported by the macOS app.

Docker

  1. Download Docker Desktop for Mac and install it.

  2. Start Docker Desktop from your Applications folder.

  3. Verify Docker is running:

    docker version
    
  1. Download Docker Desktop for Windows and install it.

  2. During installation, choose WSL 2 as the backend.

  3. Start Docker Desktop from the Start menu.

  4. Verify Docker is running in PowerShell:

    docker version
    

Install Docker Engine using the official convenience script:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
docker version

Step 2: Verify Runtime Detection

Backend.AI GO automatically detects the best available container runtime on startup.

  1. Open Settings > Squad.

  2. Check Container Runtime in the Agent Runner Image section. It shows Available or Not Available for a supported runtime. Use the Management API below when you need the detected backend and version.

You can also query the Management API directly:

curl http://localhost:8001/api/v1/container/runtime

Example response:

{
  "available": true,
  "backend": "apple_container",
  "version": "0.2.0",
  "networking": {
    "hostGateway": "192.168.64.1",
    "extraRunArgs": []
  },
  "message": "Apple Container runtime detected"
}

Step 3: Build the Agent Runner Image

The agent runner image (aigo-agent-runner:latest) is a pre-configured container image that includes the Claude Code SDK and supporting tools needed by squad agents.

Build from the App

  1. Go to Settings > Squad.

  2. In the Agent Runner Image section, click Build Image (Rebuild Image when the image already exists). The button is disabled while no container runtime is available.

  3. The button reads Building... until the build ends. Then Build Successful or Build Failed appears below it, with the build output.

  4. When Image Status shows Ready, the image is available.

Build via Management API

curl -X POST http://localhost:8001/api/v1/container/image/build \
  -H "Content-Type: application/json" \
  -d '{"tag": "aigo-agent-runner:latest"}'

Check Image Status

curl http://localhost:8001/api/v1/container/image/status

Response:

{
  "exists": true,
  "tag": "aigo-agent-runner:latest"
}

Custom Images

You can specify a custom image tag for specialized agents. The default tag is aigo-agent-runner:latest. Custom images must be pre-built and available locally.

Step 4: Configure the Mount Allowlist

The mount allowlist controls which host directories containers are permitted to access. Only paths under an allowed root can be mounted — all other paths are rejected.

Default Blocked Patterns

The following path component patterns are always blocked, regardless of allowlist settings:

Pattern Reason
.ssh SSH keys
.gnupg GPG keys
.env Environment files
.aws AWS credentials
.azure Azure credentials
.gcloud Google Cloud credentials
.docker Docker credentials
.kube Kubernetes config

A mount at, inside, or above the application data directory is always refused as well, even when an allowed root contains it, because that directory holds the settings file, the API access keys, the stored credentials, and this allowlist itself. The same refusal covers the legacy ~/.backend-ai-go directory and the sockets directory, and it applies to a squad's workspace directory too. Allowlisting your home directory therefore stays useful: a mount of the home directory itself is refused, while a project directory inside it is not.

Adding Allowed Roots

  1. Open a Cowork conversation (in Chat, switch the composer's mode to Cowork), open the workspace rail, and click Cowork settings in its Context section.

  2. In the Cowork Settings drawer, select the Mount Security tab and find Allowed Roots.

  3. Enter a host directory (e.g., /Users/you/projects).

  4. Click Add or press Enter. The allowlist is saved right away.

Only subdirectories of the added roots can be mounted into containers.

Via Management API

# Get current allowlist
curl http://localhost:8001/api/v1/container/mount/allowlist

# Set allowlist
curl -X PUT http://localhost:8001/api/v1/container/mount/allowlist \
  -H "Content-Type: application/json" \
  -d '{
    "allowedRoots": ["/Users/you/projects", "/Users/you/data"],
    "blockedPatterns": [".ssh", ".gnupg", ".env", ".aws", ".azure", ".gcloud", ".docker", ".kube"]
  }'

Validate a Mount Path

Before running containers, you can validate whether a specific path would be allowed:

curl -X POST http://localhost:8001/api/v1/container/mount/validate \
  -H "Content-Type: application/json" \
  -d '{"hostPath": "/Users/you/projects/myapp", "containerPath": "/workspace/extra/myapp", "readOnly": true}'

Step 5: Configure the Credential Proxy

The credential proxy keeps real credentials out of containers. Squad container agents need no setup here: the app starts the proxy when a container task needs it, and the task reaches its model through the proxy's router route with a token valid only while it runs (see Model Route). The mappings below are optional. A mapping forwards /{id}/... to one external upstream and swaps the placeholder CREDENTIAL_PROXY_PLACEHOLDER for a real credential; the bundled agent runner does not use one.

The current navigation does not expose a Credential Proxy settings tab. Configure it through the Management API:

Keep the credential out of shell history

Do not paste a real credential into a command argument or a saved request body. The example below reads it without echoing and sends the generated JSON through standard input. Run it from Bash or Zsh.

# Start the proxy on its configured port (default: 3001)
curl -X POST http://localhost:8001/api/v1/container/credential-proxy/start

# Read the credential into a shell variable without echoing it.
printf "Credential: "
IFS= read -rs CREDENTIAL
printf '\n'

# Add an in-memory mapping without placing the credential in process arguments.
printf '%s' "$CREDENTIAL" \
  | python3 -c 'import json,sys; print(json.dumps({"id":"anthropic","upstreamUrl":"https://api.anthropic.com","authMode":"api_key","credential":sys.stdin.read()}))' \
  | curl -X POST http://localhost:8001/api/v1/container/credential-proxy/mappings \
  -H "Content-Type: application/json" \
  --data-binary @-

unset CREDENTIAL

Use oauth_bearer instead of api_key when the upstream expects an OAuth bearer token. Mappings live in the running process and are not returned in status responses.

A client using a mapping presents only the placeholder string CREDENTIAL_PROXY_PLACEHOLDER; the proxy injects the real credential when forwarding the request.

Next Steps