AACWorkflow Docs

Runtime Labels and Routing

Use labels to control which runtimes can claim and execute specific tasks based on required capabilities.

Runtime labels and routing allow you to control task-to-runtime assignment based on capabilities and requirements. When you create a task, you can specify which labels (OS, toolchain, provider, custom tags) the runtime must have. The scheduler then only assigns the task to runtimes whose label set matches.

Why labels matter

Imagine you have three runtimes:

  • macOS daemon — Claude provider, no Docker
  • Linux daemon — Claude and Cursor, Docker support, Node.js 20
  • Windows daemon — Claude provider only

If you create a task that says "this agent needs Docker and Node 20", AACWorkflow should only offer it to the Linux daemon. Without labels, the task might accidentally be assigned to the macOS daemon, which would fail at runtime.

Labels prevent these mismatches.

What is a label?

A label is a keyword describing a runtime capability or property:

CategoryExamples
OSmacos, linux, windows
Architecturearm64, amd64 (x86-64)
Toolchainnode20, node22, python3.11, go, rust
Providersclaude, codex, cursor
Containersdocker, podman
Customci-runner, production, gpu-enabled

Labels are case-insensitive and use kebab-case (lowercase with hyphens).

Automatic labels from capabilities

When a daemon registers, it automatically advertises labels based on its capabilities:

  • OS and architecture — macos, linux, windows, arm64, amd64
  • AI providers — claude, codex, cursor (one per installed provider)
  • MCP transports — mcp-stdio, mcp-sse, mcp-http

These are the capability labels and are automatically updated when you restart the daemon or install a new provider.

See Runtime capability registry for more details.

Custom labels

In addition to automatic capability labels, you can assign custom labels to a runtime to describe properties AACWorkflow doesn't automatically detect:

  1. Go to Settings → Runtimes
  2. Click on a runtime
  3. Scroll to Custom Labels
  4. Add labels like node20, gpu-enabled, ci-runner, production
  5. Click Save

Use custom labels for:

  • Toolchain versionsnode20, python3.11, go1.21
  • Hardwaregpu-enabled, high-memory
  • Purposeci-runner, local-dev, production
  • Locationus-west, eu-central

Requiring labels on a task

When you create a task or assign an agent to an issue, you can specify required labels. The task will only be claimed by runtimes whose label set is a superset of the required labels.

Via the UI

  1. Create or edit an issue/task
  2. Under Runtime Requirements, click Add Label
  3. Select labels from the list (auto-complete, sourced from all runtimes)
  4. Example: select docker and node20
  5. Save the issue/task

The task will now only run on runtimes that have both docker AND node20 labels.

Inheriting labels from issues

Issues can set default required labels that all their tasks inherit:

  1. Open an issue
  2. Go to Issue Settings → Runtime Requirements
  3. Add required labels
  4. Any agent assigned to this issue will have these requirements by default

You can override the requirements per-task if needed.

Label matching algorithm

AACWorkflow uses set matching:

  • Task required labels: [docker, node20]
  • Runtime labels: [macos, arm64, claude, docker, node20, custom-tag]
  • Match? YES — runtime has all required labels

Another example:

  • Task required labels: [docker, gpu-enabled]
  • Runtime labels: [linux, amd64, claude, docker]
  • Match? NO — runtime has docker but not gpu-enabled

Empty required labels match any runtime (no restrictions).

Viewing runtime labels

In the UI

  1. Go to Settings → Runtimes
  2. Click on a runtime
  3. See both Capability Labels (auto) and Custom Labels (manual)

Via the API

The /runtimes/{id} endpoint returns both sets:

{
  "id": "runtime-123",
  "name": "Linux CI runner",
  "capability_labels": ["linux", "amd64", "claude", "docker"],
  "custom_labels": ["ci-runner", "node20", "python3.11"],
  "effective_labels": ["linux", "amd64", "claude", "docker", "ci-runner", "node20", "python3.11"]
}

The effective labels are what the scheduler uses for matching.

Unschedulable tasks

If a task requires labels that no runtime has, it becomes unschedulable:

  • The task stays in the queue
  • The issue shows a warning: "No runtime matches these requirements"
  • The task waits (it doesn't fail) until a suitable runtime comes online
  • After 7 days, unschedulable tasks expire and are marked incomplete

To resolve:

  1. Review the task's required labels
  2. Check which runtimes are online and what labels they have
  3. Either:
    • Add the required label to a runtime — e.g., install Docker if the task needs it
    • Remove the label requirement — if the task doesn't actually need it
    • Bring online a new runtime with the required capability

Best practices

  • Start simple — don't over-specify labels; rely on automatic capability labels
  • Use custom labels for toolchains — tag runtimes with the language/version they support
  • Document your labels — share a label vocabulary with your team
  • Review unschedulable tasks — if tasks are stuck in queue, check their label requirements

Example scenarios

Scenario 1: Docker + specific Node version

Task: "Run a Docker build for my Node 20 app"

Required labels: docker, node20

Result: Only runtimes with both labels will claim it.

Scenario 2: GPU for ML inference

Task: "Run an ML inference task"

Required labels: gpu-enabled

Result: Only GPU-enabled runtimes will claim it. If no GPU runtime is available, the task waits.

Scenario 3: Production-only changes

Task: "Deploy to production"

Required labels: production

Result: Only runtimes tagged production can run it. Development runtimes are excluded.

Scenario 4: Local development

Task: "Run tests locally"

Required labels: (empty)

Result: Any runtime can run it. AACWorkflow picks the least-loaded available runtime.

Next steps