Module 6: Scaling to the Cloud
This is the key module for going from "I ran ADW on my own machine" to "ADW
runs on demand, without me babysitting it." Everything up to now has run
locally — on your own Claude Code subscription, unmetered, dispatched with
ops digest runner --local. That's deliberately where every team starts (see
Module 8 for why). This module covers the two ways to run ADW without a
human sitting at a keyboard.
There is no single "the cloud ADW." There are exactly two supported execution models, chosen per repo depending on where the repo lives. Mixing them up is the most common mistake — know which one applies to your project before you wire anything.
The two cloud execution models

Model 1 — the central ADO pipeline
For repos hosted in Azure DevOps, ADW runs as pipeline 9
(azure-pipelines-adw.yml) in the central wg-orchestration project. It
queues to a self-hosted agent pool named ADW-Agents, backed by two
always-on Container Apps (adw-agent and adw-agent-2) — which means two
concurrent self-hosted jobs, no more, no less.
The pipeline takes a targetRepo runtime parameter (it defaults to
wg-orchestration itself, but is designed for cross-repo use). For a
cross-repo build:
- The pipeline re-validates the requested repo name against a hardcoded allowlist before doing anything else — this is a deliberate guard against an arbitrary/typo'd repo name triggering a clone of something unintended.
- It clones the target ADO repo.
- It runs the ADW loop against that repo's task.
- It opens a draft ADO PR in the target repo.
For step 4 to succeed, the container's identity needs Contribute + Create-PR permission on each target repo before you ever dispatch to it — this is a one-time per-repo grant, not something the pipeline can grant itself.
Model 2 — repo-native GitHub Actions (the "Mars model")
For repos hosted on GitHub, ADW runs entirely inside that repo via a
workflow file: .github/workflows/adw-issue-trigger.yml. The trigger is
social, not a dashboard button:
- Someone labels a GitHub issue
adw. - The workflow runs
anthropics/claude-code-actionon an ephemeralubuntu-latestrunner — a fresh VM per run, nothing persists between runs. - It opens a draft PR.
This pattern originated on the Mars work-order system and is now the standard for GitHub repos (in force since 2026-07-20). Two things make it safe to run from an untrusted trigger (an issue anyone can label):
- Injection-safe by construction: only the issue number is passed into
the workflow. The issue body is fetched inside the job as data (via
gh issue view), not interpolated into a prompt or shell command — so nothing in the issue body can smuggle in commands. - It needs a repo secret,
ANTHROPIC_API_KEY, plus theadwlabel to exist on the repo — both are one-time setup per repo (Module 7 covers this).
Wastey says
Notice the diagram converges on the same box at the bottom for both models: human merge gate. Cloud scaling changes where the agent runs and how it's triggered — it never changes who presses merge.
How dispatch picks the model for you
You don't usually choose a model by hand. adws/dispatch.py's
dispatch_gap_task routes automatically based on the project registry's
github_repo field:
- Registered with a
github_repo→ Model 2 (Mars model / GitHub Actions). - ADO-only, no
github_repo→ Model 1 (pipeline 9 withtargetRepo).
Dispatch is dry-run by default — it will tell you what it would do without actually triggering a run, which is the safe way to sanity-check routing before committing to a live dispatch.
Local vs. cloud: when to use which
Local (ops digest runner --local) | Cloud (pipeline 9 or Mars model) | |
|---|---|---|
| Runs on | Your Claude Code subscription | Metered Anthropic API (org Admin API spend) |
| Concurrency | However many sessions you run yourself | 2 concurrent jobs (ADO pool) / GitHub runner limits (Mars) |
| Trigger | You, at your keyboard | Tirion recommendation, a labeled issue, or a scheduled/dispatched task |
| Best for | Learning the loop, one-off tasks, anything you want to watch closely | Unattended work, off-hours throughput, tasks queued faster than you can run them by hand |
| Cost model | Flat/unmetered | Metered — see Module 8 |
Start local (Module 4). Reach for cloud once you have more ADW-shaped work than you have hands to run it locally, or you want work to happen without you initiating each run.
Hands-on lab
You will not actually spend API budget in this lab — the goal is to practice the trigger mechanics safely.
If your practice repo is on GitHub:
- Confirm (or ask whoever owns the repo to confirm) that
.github/workflows/adw-issue-trigger.ymlexists and that the repo secretANTHROPIC_API_KEYand theadwlabel are configured. If they aren't, stop here — do not add the label yet (Module 7 covers wiring this up properly). - If they are configured on a sandbox repo, open a small test issue
describing a trivial, low-risk task and add the
adwlabel. Watch the Actions tab foradw-issue-trigger.ymlto fire. - Confirm it opens a draft PR — not a ready-for-review or auto-merged one.
If your practice repo is in Azure DevOps (or you don't have label access):
- Locate pipeline 9 (
azure-pipelines-adw.yml) in the ADO project. - Without actually running it, inspect its parameters — confirm you can find
targetRepoand see the default value. - Using
adws/dispatch.py(or theopsCLI equivalent your team uses), run a dry-run dispatch against a task and read the output: which model did it choose, and why (does the target project registry have agithub_reposet or not)?
Either way, write one sentence explaining which model your practice project would route to and why.
Decide: local or cloud?
Answer two questions and get the right execution model for your situation.
Are you iterating on this change right now, at your keyboard?