Repository navigation
Description
PRD: ADO-Driven Squadding — Full Azure DevOps Support
Author: Jack Batzner
Status: Draft — Proposal
Problem Statement
Squad's automation layer — squad watch, triage, agent dispatch, and CI workflows — is hardcoded to GitHub. The SDK has a full AzureDevOpsAdapter with area path, iteration, and work item type support, but nothing above the SDK layer uses it. Teams using Azure DevOps for work tracking cannot adopt Squad without abandoning their existing workflow tooling.
This PRD proposes enabling 100% ADO-driven squadding: work item creation through agent implementation through PR review, entirely within Azure DevOps.
Current State
What exists (SDK layer — ready)
AzureDevOpsAdapter— full CRUD for work items, PRs, branches, tags, comments (feature-parity withGitHubAdapter)- Area path / iteration / work item type support — config-driven via
.squad/config.json detectPlatform()— auto-detects GitHub vs ADO from git remote URLdetectWorkItemSource()— exists but is never called- Ralph command templates for ADO — defined in
ralph-commands.tsbut never invoked
What's hardcoded to GitHub (automation layer — the gap)
watch.ts— callsghIssueList(),ghIssueEdit(),ghPrList()directly, never usesPlatformAdapter- Agent dispatch — uses GitHub's proprietary
agent_assignmentAPI viasecrets.COPILOT_ASSIGN_TOKEN - 5 CI workflows — webhook-driven, GitHub Actions-specific (
squad-triage.yml,squad-issue-assign.yml,squad-label-enforce.yml,squad-heartbeat.yml,sync-squad-labels.yml)
What already works without any changes
- Squad config files are platform-agnostic —
.squad/team.md,.squad/routing.md,.squad/agents/*/charter.mdare all plain markdown with no GitHub-specific content squad.config.ts— the SDK mode config is platform-neutralsquad build— generates.squad/from config, no platform dependency
Feature Parity Matrix: GitHub vs ADO
Every Squad capability on GitHub mapped to its ADO equivalent.
Core Squad Files
| Capability | GitHub | ADO | Parity |
|---|---|---|---|
Team roster (.squad/team.md) |
✅ Works | ✅ Works | 🟢 Full — plain markdown |
Routing rules (.squad/routing.md) |
✅ Works | ✅ Works | 🟢 Full — plain markdown |
Agent charters (.squad/agents/*/charter.md) |
✅ Works | ✅ Works | 🟢 Full — plain markdown |
Config (.squad/config.json) |
✅ Works | ✅ Works | 🟢 Full — already has ADO fields |
squad build |
✅ Works | ✅ Works | 🟢 Full — no platform dependency |
squad init |
✅ Scaffolds GitHub templates | 🟡 Needs --platform ado |
Work Item Management
| Capability | GitHub | ADO | Parity |
|---|---|---|---|
| Create work items | gh issue create |
AzureDevOpsAdapter.createWorkItem() |
🟢 SDK ready |
| List/query work items | gh issue list |
adapter.listWorkItems() + WIQL |
🟢 SDK ready |
| Update work items | gh issue edit |
adapter.updateWorkItem() |
🟢 SDK ready |
| Add comments | gh issue comment |
adapter.addComment() |
🟢 SDK ready |
| Labels / Tags | GitHub labels (flat) | ADO tags (flat) | 🟢 Functionally equivalent |
| Area path routing | ❌ N/A | ✅ Native | 🟢 Supported natively |
| Iteration / Sprint | ❌ N/A | ✅ Native | 🟢 Supported natively |
| Work item types | Issue only | PBI / Bug / Task / Epic / Feature | 🟢 Supported — config-driven |
Pull Request Management
| Capability | GitHub | ADO | Parity |
|---|---|---|---|
| Create PRs | GitHubAdapter.createPullRequest() |
AzureDevOpsAdapter.createPullRequest() |
🟢 SDK ready |
| List PRs | GitHubAdapter.listPullRequests() |
AzureDevOpsAdapter.listPullRequests() |
🟢 SDK ready |
| Merge PRs | GitHubAdapter.mergePullRequest() |
AzureDevOpsAdapter.mergePullRequest() |
🟢 SDK ready |
| Create branches | GitHubAdapter.createBranch() |
AzureDevOpsAdapter.createBranch() |
🟢 SDK ready |
| PR → work item linking | #123 references |
AB# linking (native) | 🟢 Different syntax, same result |
Agent Dispatch
| Capability | GitHub | ADO | Parity |
|---|---|---|---|
| Manual dispatch | Click "Assign to Copilot" on issue | Click "Create PR with Copilot" on work item | 🟢 Azure Boards + Copilot Coding Agent (GA) |
| Custom agent selection | .github/agents/*.agent.md in Copilot UI |
Same files in Azure Boards Copilot dropdown | 🟢 Same mechanism |
| Auto-dispatch (event) | GitHub Actions → agent_assignment API |
Service Hook → Pipeline → ? | 🟡 No public API to invoke Copilot Coding Agent programmatically |
| Auto-dispatch (polling) | squad watch (GitHub only) |
squad watch --platform ado |
🔴 watch.ts hardcoded to gh CLI |
Event-Driven Automation
| GitHub Workflow | What It Does | ADO Equivalent | Parity |
|---|---|---|---|
squad-triage.yml |
Issue created → route via routing.md | Service Hook → Pipeline | 🟢 Direct equivalent |
squad-issue-assign.yml |
Issue labeled squad:* → assign Copilot |
Service Hook → Pipeline → assign | 🟡 Assign works, but Copilot invocation needs bridge |
squad-label-enforce.yml |
Issue labeled → enforce mutual exclusivity | Service Hook → Pipeline → ADO REST API | 🟢 Direct equivalent |
squad-heartbeat.yml |
Cron 30min → bulk triage | Scheduled Pipeline | 🟢 ADO Pipelines support cron natively |
sync-squad-labels.yml |
Push team.md → sync labels | Pipeline with push trigger | 🟢 Direct equivalent |
squad-ci.yml |
PR → lint, build, test | ADO Pipeline with PR trigger | 🟢 Standard CI |
Board & Planning
| Capability | GitHub | ADO | Parity |
|---|---|---|---|
| Board visibility | GitHub Projects (manual setup) | ADO Boards (native) | 🟢 Supported |
| Sprint planning | Manual | ADO iterations | 🟢 Supported |
| Capacity planning | ❌ N/A | ✅ Native | 🟢 Supported |
| Burndown charts | ❌ N/A | ✅ Native | 🟢 Supported |
Gap Summary
🟢 No changes needed
- All Squad config files (team.md, routing.md, charters, config.json,
squad build) - Work item CRUD + PR management (SDK adapter is complete)
- Manual agent dispatch (Azure Boards + Copilot Coding Agent, GA)
- Custom agent selection from ADO UI (same
.github/agents/files) - CI/CD (ADO Pipelines = GitHub Actions)
- Board/sprint/capacity planning (ADO native)
🟡 Workarounds exist
- Auto-dispatch to Copilot Coding Agent — No public API to programmatically trigger it. Workaround: Pipeline creates a GitHub issue assigned to Copilot → Copilot picks it up. Or use
squad watchlocally. squad init --platform ado— Currently scaffolds GitHub-only. Need--platform adoflag for ADO Pipeline templates.
🔴 Code changes required
squad watchfor ADO — The only blocking code change. Details below.
What Will Be Implemented
Summary
| # | Change | Type | Scope | Files |
|---|---|---|---|---|
| 1 | Platform-agnostic squad watch |
Modified code | ~50-100 lines refactored | watch.ts, detect.ts |
| 2 | Charter dispatch schema | New feature | New frontmatter field parsed | charter.ts, watch.ts |
| 3 | ADO Pipeline templates | New files | 5 YAML templates | templates/ado-pipelines/ |
| 4 | squad init --platform ado |
Modified code | New CLI flag + template copy | init.ts |
| 5 | ADO setup documentation | New file | Setup guide for Service Hooks + Pipelines | docs/ |
What's NOT changing: Squad's core architecture, charter format, team.md/routing.md, squad build, the existing GitHub path, or how agents operate. This is purely wiring the existing PlatformAdapter + AzureDevOpsAdapter into the automation layer that currently skips them.
Details
1. Platform-agnostic squad watch (the main code change)
The problem: watch.ts calls GitHub-specific functions directly.
// BEFORE — watch.ts (hardcoded to GitHub)
const issues = await ghIssueList({ label: 'squad', state: 'open' });
for (const issue of issues) {
await ghIssueEdit(issue.number, { addLabels: [`squad:${agent}`] });
}
const prs = await ghPrList({ state: 'open' });The fix: Route through PlatformAdapter so the same code works for both platforms.
// AFTER — watch.ts (platform-agnostic)
const adapter = await detectPlatform(); // returns GitHubAdapter or AzureDevOpsAdapter
const items = await adapter.listWorkItems({
tags: ['squad'],
state: 'open',
areaPath: config.ado?.areaPath // ADO-only, ignored on GitHub
});
for (const item of items) {
await adapter.addTag(item.id, `squad:${agent}`);
}
const prs = await adapter.listPullRequests({ state: 'open' });Scope: ~50-100 lines changed in watch.ts. The PlatformAdapter interface and AzureDevOpsAdapter already exist — this is wiring, not building.
Files touched:
packages/squad-cli/src/cli/commands/watch.ts— replaceghIssueList/ghIssueEdit/ghPrListwithadapter.*callspackages/squad-sdk/src/platform/detect.ts— calldetectWorkItemSource()(exists but unused)
2. Charter-based dispatch (new schema)
Add a dispatch block to charter frontmatter so agents declare how they receive work:
# .squad/agents/coder/charter.md (frontmatter)
name: coder
dispatch:
strategy: ado-assignment # or: github-copilot, local-cli, webhook
identity: "agent-identity" # who gets assigned in the platform
branch: main| Strategy | How It Works | Who Uses It |
|---|---|---|
github-copilot |
GitHub's agent_assignment API (current behavior) |
GitHub teams |
ado-assignment |
Azure Boards Copilot integration or Service Hook trigger | ADO teams with Copilot |
local-cli |
squad watch dispatches locally |
Anyone, any platform |
webhook |
POST work item payload to URL | Custom platforms |
Files touched:
packages/squad-sdk/src/config/charter.ts— parsedispatchfrom frontmatterpackages/squad-cli/src/cli/commands/watch.ts— read dispatch strategy when assigning
3. ADO Pipeline templates (new files)
Ship ADO Pipeline YAML equivalents of the 5 GitHub Actions workflows. These get scaffolded by squad init --platform ado:
# .azuredevops/pipelines/squad-triage-pipeline.yml
# Triggered by ADO Service Hook on "Work item created"
trigger: none
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
- task: NodeTool@0
inputs: { versionSpec: '20.x' }
- script: |
npx @bradygaster/squad-cli triage \
--platform ado \
--work-item-id $(WORK_ITEM_ID) \
--area-path "$(AREA_PATH)"
env:
ADO_PAT: $(ADO_PAT)
GITHUB_TOKEN: $(GITHUB_TOKEN)# .azuredevops/pipelines/squad-heartbeat-pipeline.yml
# Equivalent of squad-heartbeat.yml (cron every 30 min)
trigger: none
schedules:
- cron: '*/30 * * * *'
displayName: 'Squad heartbeat'
branches: { include: [main] }
always: true
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
- task: NodeTool@0
inputs: { versionSpec: '20.x' }
- script: |
npx @bradygaster/squad-cli heartbeat \
--platform ado \
--area-path "$(SQUAD_AREA_PATH)"
env:
ADO_PAT: $(ADO_PAT)
GITHUB_TOKEN: $(GITHUB_TOKEN)Full set shipped:
| Template | Trigger | Equivalent Of |
|---|---|---|
squad-triage-pipeline.yml |
Service Hook: work item created | squad-triage.yml |
squad-assign-pipeline.yml |
Service Hook: work item updated (tag) | squad-issue-assign.yml |
squad-label-enforce-pipeline.yml |
Service Hook: work item updated | squad-label-enforce.yml |
squad-heartbeat-pipeline.yml |
Scheduled (cron 30 min) | squad-heartbeat.yml |
squad-sync-labels-pipeline.yml |
Push trigger on .squad/team.md |
sync-squad-labels.yml |
Files touched:
templates/ado-pipelines/— new directory with 5 YAML filespackages/squad-cli/src/cli/commands/init.ts— add--platform adoflag, copy templates
4. squad init --platform ado (scaffolding)
$ squad init --platform ado
✓ Created .squad/team.md
✓ Created .squad/routing.md
✓ Created .squad/agents/coder/charter.md (with dispatch.strategy: ado-assignment)
✓ Created .squad/config.json (with ado.org, ado.project, ado.areaPath)
✓ Created .azuredevops/pipelines/squad-triage-pipeline.yml
✓ Created .azuredevops/pipelines/squad-heartbeat-pipeline.yml
✓ Created .azuredevops/pipelines/squad-assign-pipeline.yml
✓ Created .azuredevops/pipelines/squad-label-enforce-pipeline.yml
✓ Created .azuredevops/pipelines/squad-sync-labels-pipeline.yml
✓ Created docs/ado-setup.md (Service Hook configuration guide)Files touched:
packages/squad-cli/src/cli/commands/init.ts— add--platformoptiontemplates/ado-pipelines/— template source files
What Won't Be Supported (Known Limitations)
| Limitation | Why | Workaround |
|---|---|---|
| Programmatic Copilot Coding Agent invocation | No public API exists — it's UI-only (click button on work item) | Pipeline creates GitHub issue → Copilot picks up; or squad watch dispatches locally |
| ADO-native PR agent (no GitHub repo) | Copilot Coding Agent requires a GitHub repo | Use squad watch --platform ado for pure-ADO repos with ADO Repos |
| GitHub label ↔ ADO tag atomicity | ADO tags don't support the same atomic add/remove as GitHub labels | squad watch handles retries; Pipeline templates use ADO REST API with optimistic concurrency |
Open Questions
None — multi-platform (hybrid GitHub + ADO in a single repo) is deferred until there is a concrete need.
Prior Art
Issues
- Please Don't Lock
squadinto using GitHub #8 — "Please Don't Lock squad into using GitHub" (closed, 7 👍) — the original community ask for ADO support - feat: ADO configurable work item types, area paths, and iteration support #240 — "feat: ADO configurable work item types, area paths, and iteration support" (open) — P0/P1 config work for ADO
- Question: what's the intended role of the platform/communication adapter layer? #294 — "Question: what's the intended role of the platform/communication adapter layer?" (closed) — architectural discussion on where platform adapters fit
Pull Requests
- feat: Azure DevOps platform adapter — Squad for enterprise #191 — "feat: Azure DevOps platform adapter — Squad for enterprise" (merged) — shipped the
AzureDevOpsAdapter - ADO configurable work item types #444 — "ADO configurable work item types" (merged) — work item type introspection + config cascade
- feat: CommunicationAdapter — platform-agnostic agent-human communication #263 — "feat: CommunicationAdapter — platform-agnostic agent-human communication" (merged)
External References — Azure Boards + Copilot Coding Agent (Public)
- GitHub Blog: Assign Azure Boards work items to Copilot coding agent (public preview)
- Microsoft Learn: Work Item integration with GitHub Copilot coding agent
- DevBlogs: Azure Boards integration with GitHub Copilot includes custom agent support
- GitHub Docs: Integrating Copilot coding agent with Azure Boards
External References — ADO Automation Primitives (Public)
- ADO Service Hooks overview — event-driven webhooks on work item/PR/build events
- Service Hooks events reference —
workitem.created,workitem.updated - ADO Pipelines scheduled triggers — cron-based execution
- Power Automate + Azure DevOps connector
Community Examples
- Daniel Scott-Raynsford: Enabling GitHub Copilot Coding Agents to Access Azure
- C# Corner: GitHub Copilot Integration in Azure DevOps for 2026 Workflows
- Dom Stamand: Building an AI PR Agent for Azure DevOps using GitHub Copilot SDK
- Sample repo: ado-copilot-coding-agent
Squad Source Code
- ADO adapter:
packages/squad-sdk/src/platform/azure-devops.ts - Platform types:
packages/squad-sdk/src/platform/types.ts - Watch loop:
packages/squad-cli/src/cli/commands/watch.ts - Platform detection:
packages/squad-sdk/src/platform/detect.ts - Agent charters:
.squad/agents/*/charter.md - Routing rules:
.squad/routing.md
CC: @bradygaster , @tamirdresher
Activity
github-actions commentedon Mar 28, 2026
🏗️ Squad Triage — Flight (Lead)
Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support
Assigned to: FIDO (Quality Owner)
Reason: Issue relates to testing/quality work
@copilot evaluation: 🔴 Not suitable — issue involves work outside the coding agent's capability profile.
Team roster:
squad:flightsquad:proceduressquad:eecomsquad:fidosquad:paosquad:capcomsquad:controlsquad:surgeonsquad:boostersquad:gncsquad:networksquad:retrosquad:incosquad:guidosquad:telemetrysquad:voxsquad:dskysquad:simssquad:handbooksquad:ralphsquad:copilotgithub-actions commentedon Mar 28, 2026
📋 Assigned to Flight (Lead)
Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support
Flight will pick this up in the next Copilot session.
github-actions commentedon Mar 28, 2026
📋 Assigned to EECOM (Core Dev)
Issue: #581 — PRD: ADO-Driven Squadding — Full Azure DevOps Support
EECOM will pick this up in the next Copilot session.
diberry commentedon Mar 31, 2026
🔄 Ralph status: PRD — ADO-driven squadding. No PR. Long-term backlog.
3 remaining items
github-actions commentedon Sep 10, 2026
🔄 Ralph — Auto-Triage
Assigned to: CONTROL
Reason: Matched module path "src/config/" to primary owner "CONTROL 👩💻"
Source: module-ownership
github-actions commentedon Sep 11, 2026
🔄 Ralph — Auto-Triage
Assigned to: CONTROL
Reason: Matched module path "src/config/" to primary owner "CONTROL 👩💻"
Source: module-ownership
github-actions commentedon Sep 11, 2026
🔄 Ralph — Auto-Triage
Assigned to: CONTROL
Reason: Matched module path "src/config/" to primary owner "CONTROL 👩💻"
Source: module-ownership
github-actions commentedon Sep 11, 2026
🔄 Ralph — Auto-Triage
Assigned to: CONTROL
Reason: Matched module path "src/config/" to primary owner "CONTROL 👩💻"
Source: module-ownership
github-actions commentedon Sep 11, 2026
🔄 Ralph — Auto-Triage
Assigned to: CONTROL
Reason: Matched module path "src/config/" to primary owner "CONTROL 👩💻"
Source: module-ownership
github-actions commentedon Sep 13, 2026
🔄 Ralph — Auto-Triage
Assigned to: architect
Reason: No module, routing, or role keyword match — routed to Lead/Architect
Source: lead-fallback