Orchestrate multi-agent coordination

What changes when there is more than one agent. Give each a narrow role, coordinate them through events and artifacts rather than hidden chatter, isolate them so they cannot collide, make every handoff observable, and design recovery and lifecycle changes that never break a running workflow.

Skill 5 15–20% of the exam Skills measured: study guide revision of May 4, 2026
Four objectives in this skill area:

5.1 Operate and manage multi-agent workflows

Start with responsibilities

Multi-agent failures are predictable: overlapping responsibilities produce duplicated work, conflicting pull requests and unclear ownership. Assign each agent a narrow role, limit it by path and artifact type, and give it a completion signal GitHub can verify. The boundary stays the same as for one agent: agents propose; humans and policy accept.

AgentMay changeMust not changeDone when
Dependency agentManifests and lockfilesApplication behaviour, workflowsPR open, checks green, alert closed
Refactoring agentsrc/Manifests, lockfiles, workflowsPR open, behaviour unchanged (tests green)
Security agentNothing, or security fixes when explicitly askedUnrelated refactoringReport referencing checks and scan results
Documentation agentdocs/, *.mdCodePR open, link check green

Apply an orchestration pattern

Orchestration decides when agents run, in what order, and how outputs move between them. In GitHub it works best expressed through workflow events and shared artifacts, because then coordination is visible in runs, checks and pull requests. Hidden coordination makes failures impossible to diagnose.

PatternUse whenGitHub mechanism
SequentialOne step's output must be validated before the nextworkflow_run triggers, needs chains
Parallel fan-out / fan-inIndependent analyses that merge into one resultParallel jobs joined by needs: [a, b]
Orchestrator–worker (subagents)A main agent decomposes a task and delegates partsCustom agents invoked through the agent tool; CLI built-in agents; /fleet
Artifact-based coordinationYou want a hard line between reasoning and writingAgent writes a plan or report artifact; a separate, controlled step applies only allowed operations
Event-drivenRecurring or reactive workSchedules, issues and pull_request events, Copilot automations, Agentic Workflows
flowchart LR
  DEP["Dependency agent<br/>opens PR"] --> CI["CI validation<br/>workflow"]
  CI -->|"workflow_run: completed"| SEC["Security validation<br/>workflow"]
  SEC --> HUMAN["Human review"]
  HUMAN --> MERGE["Merge when<br/>all gates pass"]
Sequential orchestration: the security workflow starts only after CI completes, and a human still approves the merge.
yaml
# .github/workflows/security-validate.yml — runs after CI finishes
name: Security validation
on:
  workflow_run:
    workflows: ["CI validation"]
    types: [completed]

jobs:
  validate:
    if: github.event.workflow_run.conclusion == 'success'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    steps:
      - run: echo "Run security validation for ${{ github.event.workflow_run.head_sha }}"
flowchart LR
  START["workflow_dispatch"] --> SPEC["spec_analyzer"]
  START --> RISK["risk_reviewer"]
  SPEC --> MERGER["plan_merger<br/>needs: both"]
  RISK --> MERGER
  MERGER --> PLAN["Merged plan<br/>artifact"]
Fan-out / fan-in: two analysis jobs run in parallel and a merger job waits for both through needs.
yaml
name: multi-agent-orchestration
on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  spec_analyzer:
    runs-on: ubuntu-latest
    steps:
      - run: ./executors/spec_analyzer.sh

  risk_reviewer:
    runs-on: ubuntu-latest
    steps:
      - run: ./executors/risk_reviewer.sh

  plan_merger:
    needs: [spec_analyzer, risk_reviewer]     # fan-in: waits for both
    runs-on: ubuntu-latest
    concurrency:
      group: multiagent-${{ github.ref }}    # never two merges on one branch
    steps:
      - run: ./executors/plan_merger.sh

Fan-in means needs

The Learn module calls out fan-out / fan-in with needs as an exam topic. A job listing needs: [spec_analyzer, risk_reviewer] waits for both; combined with a concurrency group it also cannot overlap with another merge on the same branch. Parallelism is only safe when the agents' scopes do not overlap — otherwise it increases instability, not throughput.

Subagents, built-in agents and fleet mode

Within one session, a main agent can run other agents as subagents, each in its own context window, and in parallel where subtasks are independent.

flowchart TB
  TASK["Task from the user"] --> MAINA
  subgraph SESSION["One session — separate context windows"]
    direction TB
    MAINA["Main agent<br/>orchestrator · owns the plan and the final answer"]
    MAINA --> EXPLORE["explore<br/>read-only research"]
    MAINA --> IMPL["implementer<br/>custom agent · edit tools"]
    MAINA --> REVIEW["code-review<br/>read-only"]
  end
Orchestrator–worker: the main agent holds the plan and delegates to specialists that each see only their slice of the work.
  • Custom agents as subagents — give the orchestrator the agent tool; the runtime matches subtasks to agents by name and description, so specific descriptions delegate better.
  • Copilot CLI built-in agents — explore (fast, read-only, safe to run in parallel), task (runs builds and tests, returns a short summary), general-purpose, code-review (high signal, never edits), research (only via /research), rubber-duck (a second opinion from a different model) and security-review.
  • /fleet (or --fleet) — the main agent splits a plan into independent subtasks and runs subagents in parallel, choosing custom agents where they fit (@test-writer names one explicitly). More subagents means more model calls and more AI credits, and it gives no benefit for inherently sequential work.
  • Copilot SDK — customAgents on the session; infer: false stops automatic selection; defaultAgent.excludedTools hides heavy tools from the main agent so it must delegate.
.github/agents/orchestrator.agent.md
---
name: orchestrator
description: Breaks a feature into tasks and delegates to planner, implementer and reviewer agents
tools: ["read", "search", "agent"]
---

1. Ask @planner for a numbered plan and wait for it.
2. Delegate each implementation step to @implementer, one step at a time.
3. Ask @code-review to review the combined diff.
4. Record each handoff and decision in docs/handoffs.md.

Handoffs are an IDE feature

VS Code custom agents support a handoffs property that offers a button to switch to the next agent with a prepared prompt. The GitHub docs state that handoffs and argument-hint are ignored by Copilot cloud agent on GitHub.com. On GitHub, express handoffs through the agent tool, separate sessions, or artifacts and PR comments.

Configure agent isolation for parallel execution

Isolation means each agent operates in its own controlled scope so agents cannot interfere, share an execution context or thrash through repeated runs. It is what makes concurrency safe and attribution clear.

flowchart TB
  subgraph REPO["One repository — isolated agents"]
    direction LR
    A1["agent/dependency/482<br/>lockfiles only · contents: write"]
    A2["agent/refactor/511<br/>src/ only · contents: write"]
    A3["agent/security/482<br/>reports only · contents: read"]
  end
  A1 --> PR1["PR · required checks · CODEOWNERS"]
  A2 --> PR2["PR · required checks · CODEOWNERS"]
  A3 --> RPT["Report artifact"]
Isolation in one repository: a branch, workflow, permission set and concurrency group per agent, and every writer's output funnelled through its own PR.
Isolation layerHow
BranchOne branch per agent and task (agent/dependency/482); Copilot cloud agent works on exactly one branch and opens one PR per task
WorkflowA dedicated workflow, or job, per agent so triggers, permissions and outputs are easy to reason about
PermissionsLeast privilege per workflow or job — the security agent needs contents: read, not write
ConcurrencyA workflow-level group keyed on workflow and ref, with cancel-in-progress
ContextSubagents each get their own context window
Working treeCopilot CLI --worktree / /new worktree runs a session in its own Git worktree
yaml
# Workflow-level: one run per workflow per branch; a newer push cancels the older run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
  • Keying on ${{ github.ref }} alone makes the group global to the branch and can block unrelated workflows.
  • Job-level concurrency only coordinates within a run, and a strategy.matrix controls intra-run parallelism — neither prevents two runs triggered by separate pushes from colliding.
  • For production deploys, use a fixed group such as production to serialize them.
Agent modeParallel sessions across tasks?
Copilot cloud agentYes — many sessions, each on its own branch
Copilot CLIYes — multiple sessions, subagents and /fleet
Local IDE agent sessionNo — one at a time in a workspace

Detect and resolve agent conflicts

ConflictExampleDetection and resolution
Textual (merge) conflictTwo agents edit the same linesMerge-validation check; ask Copilot to resolve the conflict on its PR; escalate if it recurs
Semantic conflictBoth PRs merge cleanly but break togetherRequire branches to be up to date before merging; a merge queue that tests the combined result
Overlapping code changesRefactoring agent edits a lockfile the dependency agent ownsScope boundaries per agent; CODEOWNERS; a scope-check workflow
Duplicated effortTwo PRs fix the same alert differentlyOne owner per issue (assignment); labels; close the duplicate and keep the evidence
Contradictory outputsOne agent recommends 2.x, another pins 1.xArbitration by code owners; decision recorded in the PR; escalate to a human
Policy conflictA path needs a different approval than the rest of the PRRulesets and CODEOWNERS decide, not timing
yaml
- name: Validate the branch still merges cleanly with main
  run: |
    git fetch origin main
    git merge --no-commit --no-ff origin/main || {
      echo "::error::Conflicts with main — rebase or escalate"
      exit 1
    }

Escalate instead of retrying when:

  • a PR still conflicts after two rebase attempts,
  • a required check fails twice with the same failure signature, or
  • two agents propose incompatible fixes for the same alert.

Timing must not pick the winner

Without arbitration rules, whichever PR merges first "wins" and reviewers untangle the mess afterwards. Reliable systems detect conflicts early with required checks and resolve them intentionally through ownership (CODEOWNERS) and explicit escalation.

5.2 Configure observability for multi-agent behaviour

Produce artifacts suitable for review and audit

As the number of agents grows, traceability becomes the primary requirement: which agent produced a change, what it decided, what evidence supports it, and what happened next. Every meaningful step should leave a durable trace in GitHub.

  • Attribution conventions — PR titles such as [agent: dependency] Update axios to 1.8.2; labels agent: dependency, agent: security; Copilot notes the custom agent it used in the PR description.
  • A standard PR body — Objective, Plan, Evidence, Decisions and handoffs, Risks and rollback.
  • Machine-readable evidence — report.json, plan.json and test results uploaded with actions/upload-artifact.
  • Workflow outputs — step and job outputs as explicit contracts between jobs, not values scraped from logs.

Document decisions, handoffs and outcomes

PR body for a multi-agent handoff
## Objective
Update axios to 1.8.2 (Dependabot alert #57).

## Plan
1. Bump axios in package.json   2. Regenerate the lockfile   3. Run tests

## Evidence
- CI run: https://github.com/org/repo/actions/runs/123456
- Dependency review: clean

## Decisions and handoffs
- Decision: pinned to 1.8.x, not 2.x — 2.x drops Node 18 support
- Handoff: @security-agent to confirm alert closure; next owner if blocked: @platform-team

## Risks and rollback
- Low risk; revert the merge commit

For multi-step orchestrations, keep a running handoff log (for example docs/handoffs.md) committed on the branch, so the next agent — or person — can see who did what and why.

Perform post-hoc analysis

QuestionSource
What did each agent do and why?Session logs (Agents page, linked from every commit)
What did the run produce?Download the run's artifacts from the Artifacts section — the primary evidence even when live logs are gone
An artifact is missing — who deleted it?Organization audit log, action:artifact.destroy
Which agent actions happened across the org?Audit log filtered by actor:Copilot (180 days), grouped by agent_session_id; stream to a SIEM for longer retention
When did each subagent start, finish or fail?SDK subagent.started / completed / failed events; subagentStart / subagentStop hooks; OpenTelemetry traces
What did I run last week?Ask Copilot Chat to search your synced sessions

5.3 Detect and respond to multi-agent failures and degraded behaviour

Identify failed, partial or stalled executions

Multi-agent failures are usually coordination failures, even when each agent is individually capable.

Failure modeWhat you seeSignal
FailedThe session or job erroredFailed run; subagent.failed; errorOccurred hook
PartialA PR exists but evidence or validation is missingMissing required check; empty Evidence section
StalledChecks fail repeatedly or approvals never arrivePR age; pending environment approvals; a session that is still running near its 59-minute limit
ConflictingPRs compete and block each otherMerge conflicts; duplicate PRs on one issue
FlappingWorkflows rerun with no convergenceMany cancelled or failed runs on the same branch
GitHub CLI
# List recent agent tasks, then stream one session's log live
gh agent-task list
gh agent-task view 214 --log --follow
Copilot SDK
session.on((event) => {
  if (event.type === "subagent.failed") {
    logger.error(`${event.data.agentName} failed: ${event.data.error}`);
    // retry, fall back to the parent agent, or escalate
  }
});

Respond to degraded behaviour or coordination

  • Steer a session that is heading the wrong way; stop it if the task is no longer needed — pushed commits are preserved.
  • Pause the automation or workflow that keeps re-triggering (disable the workflow, or the automation's trigger).
  • If an orchestrator cannot call a specialist, check whether that profile sets disable-model-invocation: true — such an agent cannot be invoked as a subagent.
  • If cloud agent is blocked by a ruleset (for example, restricted commit authors), add Copilot as a bypass actor on that ruleset.
  • A policy block from a preToolUse hook ("destructive operation detected") is a designed handoff to a human, not an error to retry.

Implement multi-agent recovery patterns

PatternHow
Bounded retryAn agent may revise its own PR branch to fix failures, within a limit
Escalation thresholdSame required check fails twice → stop and hand to a human with links and a summary
RollbackSmall, scoped PRs; close or revert; deploy explicit refs so a previous version is one redeploy away
Human-in-the-loopEnvironments with required reviewers for high-risk steps; a human decides between competing PRs
Graceful degradationOn subagent.failed, fall back to the parent agent or skip the optional step and report it

5.4 Manage the lifecycle of agents within multi-agent workflows

Add agents to existing workflows

  1. Define the new agent's responsibility and scope so it does not overlap existing agents.
  2. Create the profile — .github/agents/NAME.agent.md for one repository, or the agents/ folder of the organization's .github / .github-private repository for everyone.
  3. For organization or enterprise agents, test privately first in .github/agents of the .github-private repository (only usable from that repository), then release by moving it to the root agents folder.
  4. Wire it in: add it to the orchestrator's prompt, a workflow job, or an automation — and give it its own branch prefix, label and concurrency group.
  5. Protect .github/agents/, .github/hooks/ and MCP configuration with CODEOWNERS and required code-owner review.

Update, reconfigure or replace without disruption

  • Versioning is by commit SHA. A new task uses the latest profile on the repository and branch; once the agent opens a PR, interactions on that PR keep using the same version. Active work is not disrupted by a profile change.
  • Try a change on a branch — you can create a profile on a chosen branch — before merging it to the default branch.
  • Replace by introducing the new agent alongside the old one, moving callers over, then retiring the old one.
  • Use the invocation controls to stage changes: user-invocable: false hides an agent from manual selection while keeping it callable programmatically; disable-model-invocation: true stops automatic selection (and subagent calls) while leaving it selectable by users.
  • Watch name precedence: a repository profile with the same name overrides the organization's, which overrides the enterprise's.

Retire agents while preserving auditability

  • Remove or rename the profile through a pull request — Git history keeps the exact configuration every past PR used.
  • Update every orchestrator prompt, workflow and automation that referenced it first, so nothing fails at call time.
  • Keep the evidence: cloud agent sessions can be archived but not deleted, audit log events remain, and artifacts should be retained long enough for your audit needs.
  • Consider a deprecation window — disable-model-invocation: true and a note in the description — before deletion.

Lifecycle is governance

Agents and their guardrails evolve together: each needs an owner, a runbook and a review cadence. The broader governance loop — weekly failure reviews, monthly permission reviews, quarterly ruleset audits — is on the guardrails page.