Implement tool use and environment interaction

The heaviest skill area. It is about what an agent can reach and where it runs: which tools it is given, how MCP extends them and how organizations govern that, the boundaries of each execution context, and how to fail safely — bounded retries, rollbacks, escalation and a trail that attributes every action.

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

2.1 Select and configure agent tools

Identify required tools

Agents act through tools: every file read, edit, shell command, API call or subagent invocation is a tool call. Choosing tools is choosing capability, so start from the task and add only what it needs.

Tool familyExamplesNeeded for
Read and searchread / view, search, grep, globPlanning, review, research — safe by default
Editedit, write, createImplementation agents only
Executeexecute / shell / bash / powershellBuild, test, lint — the most powerful and most dangerous
Agentagent / task / custom-agentInvoking another custom agent as a subagent
Webweb (web_fetch, web_search)External docs — not applicable to cloud agent today
GitHub MCP servergithub/*, github/list_workflow_runsIssues, PRs, Actions logs, code scanning alerts
Playwright MCP serverplaywright/*Browsing and screenshotting the app running on localhost
Custom MCP serverssentry/get_issue_detailsExternal systems: observability, tickets, cloud resources

Configure agent tools

In a custom agent profile, the tools property filters every tool available to the agent, built-in or from MCP servers. Its semantics are a classic exam target:

tools valueEffect
Omitted, or ["*"]All available tools, including every configured MCP server tool
[]No tools at all
["read", "search", "edit"]Only those tools (aliases are case-insensitive)
["github/*"]All tools from the github MCP server
["sentry/get_issue_details"]One named tool from one MCP server
An unknown nameSilently ignored — so a profile can list product-specific tools safely
AliasAlso acceptedCloud agent mapping
executeshell, Bash, powershellShell tools
readRead, NotebookReadview
editEdit, MultiEdit, Write, NotebookEditEdit tools such as str_replace
searchGrep, Globsearch
agentcustom-agent, TaskCustom agent tools
web, todoWebSearch, WebFetch, TodoWriteNot applicable to cloud agent
.github/agents/security-reviewer.agent.md
---
name: security-reviewer
description: Reviews changes for vulnerabilities and reports findings. Read-only; never edits code.
tools: ["read", "search", "github/*"]
---

Review the changes on this branch for injection, secrets, unsafe deserialization and
missing authorization checks. Report each finding with file, line and a suggested fix.
Do not modify files.

Configure agent tool permissions

"Which tools exist" and "which tools may run without asking" are separate questions, and each surface answers them differently.

SurfaceHow permissions work
Copilot cloud agent Non-interactive: configured MCP tools are used autonomously, without asking for approval. The only gate is what you allowlist — the tools field of each MCP server and of the agent profile. Allowlist specific read-only tools wherever possible.
Copilot CLI Read-only operations run automatically; tools that modify the system prompt for approval. --available-tools / --excluded-tools decide which tools the model even knows about; --allow-tool / --deny-tool pre-approve or forbid them. Deny always wins, even over --allow-all and saved approvals.
Automations You select exactly which tools each automation may use (or let Copilot Suggest tools from the prompt)
GitHub Agentic Workflows tools: in frontmatter enables toolsets; writes happen only through declared safe-outputs
Copilot SDK Per-agent tools lists, session availableTools / excludedTools, and an onPermissionRequest handler
Agent skills The allowed-tools frontmatter field pre-approves tools a skill's scripts need — pre-approve shell only for skills you fully trust
Copilot CLI optionEffect
--allow-tool='shell(git:*)' --deny-tool='shell(git push)'Every git command except git push
--allow-tool='read, write(.github/copilot-instructions.md)'All reads; writes to one file only
--allow-tool='MyMCP(create_issue)'One tool from one MCP server
--deny-tool=writeNo file writes, whatever else is allowed
--available-tools='bash,edit,view,grep,glob'The model cannot see any other tool, so it cannot even try
--allow-all / --yoloAll tools, paths and URLs — isolated environments only; can be blocked by enterprise settings
/reset-allowed-toolsRevokes approvals granted during the session and clears saved ones for the location

Two layers, two different questions

--available-tools and --excluded-tools change what the model can choose from; --allow-tool and --deny-tool change what runs without a prompt. A tool missing from the available set cannot be used even if it is in --allow-tool. Command-line options last for the session only; approvals such as "don't ask again in this repo" persist in ~/.copilot/permissions-config.json.

2.2 Configure MCP servers

The Model Context Protocol is an open standard for connecting AI clients to tools. Instead of a one-off integration per system, a client talks to an MCP server that exposes tools in a structured format and performs the real action against the underlying service. Three concepts work together:

  • An MCP server exposes tools — locally (a process on your machine, stdio) or remotely (hosted, http/sse).
  • An MCP registry makes approved servers discoverable.
  • An allowlist policy decides which servers may actually run.
flowchart LR
  subgraph GOV["Organization and enterprise policy"]
    direction LR
    REG["MCP registry<br/>catalogue of approved servers"] --> CLIENT["MCP client<br/>IDE · Copilot CLI"]
    ALLOW["Allowlist policy<br/>MCP servers in Copilot · managed settings"] --> CLIENT
  end
  CLIENT --> SERVER["MCP server<br/>local stdio or remote HTTP"]
  SERVER --> SYS["Underlying system<br/>GitHub · Sentry · Azure · Jira"]
Servers expose tools; registries make them discoverable; allowlist policy decides which a client may run.

What cloud agent supports

Copilot cloud agent and Copilot code review use MCP tools only — not MCP resources or prompts — and do not support remote MCP servers that authenticate with OAuth. Code review additionally uses only tools annotated readOnlyHint: true. Once configured, cloud agent calls MCP tools without asking for approval.

Add an MCP server as a tool to an agent

WhereHowScope
Repository settings on GitHubSettings → Copilot → MCP servers: paste JSON with an mcpServers objectCloud agent and code review in that repository
Custom agent profileThe mcp-servers YAML propertyOnly that custom agent (ignored by IDE custom agents)
VS CodeAgent mode → Tools → Add MCP server, or .vscode/mcp.json, or the MCP gallery (@mcp in Extensions)Workspace or user
Copilot CLI/mcp add or copilot mcp add → ~/.copilot/mcp-config.json; workspace .mcp.json; --additional-mcp-config for one sessionUser, workspace or session
Copilot SDKmcpServers on the session or on a custom agentYour application

In the repository JSON, type and tools are required for every server. Local servers need command and args; remote servers need a url and optional headers. Secrets are never pasted in: create an Agents secret whose name starts with COPILOT_MCP_ and reference it as $COPILOT_MCP_NAME, ${COPILOT_MCP_NAME} or ${COPILOT_MCP_NAME:-default}.

Settings → Copilot → MCP servers
{
  "mcpServers": {
    "sentry": {
      "type": "local",
      "command": "npx",
      "args": ["@sentry/mcp-server@latest", "--host=$SENTRY_HOST"],
      "tools": ["get_issue_details", "search_issues"],
      "env": {
        "SENTRY_HOST": "https://contoso.sentry.io",
        "SENTRY_ACCESS_TOKEN": "$COPILOT_MCP_SENTRY_ACCESS_TOKEN"
      }
    },
    "docs": {
      "type": "http",
      "url": "https://docs.contoso.com/mcp",
      "tools": ["search_docs"],
      "headers": { "Authorization": "Bearer $COPILOT_MCP_DOCS_TOKEN" }
    }
  }
}
.github/agents/incident-triage.agent.md
---
name: incident-triage
description: Correlates production errors with recent commits
tools: ["read", "search", "sentry/get_issue_details"]
mcp-servers:
  sentry:
    type: local
    command: npx
    args: ["@sentry/mcp-server@latest"]
    tools: ["*"]
    env:
      SENTRY_ACCESS_TOKEN: ${{ secrets.COPILOT_MCP_SENTRY_TOKEN }}
---

Find the Sentry issue referenced in the task and identify the commit most likely to have caused it.

Configurations combine in a fixed order, each level able to override the one before. An agent can use MCP tools configured in its own profile and in repository settings.

flowchart LR
  OOB["1 · Out-of-the-box servers<br/>GitHub MCP · Playwright MCP"] --> AGENT["2 · Custom agent profile<br/>mcp-servers property"]
  AGENT --> REPO["3 · Repository settings<br/>Settings → Copilot → MCP servers"]
  REPO --> EFFECTIVE["Effective configuration<br/>later levels override earlier ones"]
MCP configuration processing order for cloud agent.

To confirm servers started, open the cloud agent session log, expand the Start MCP Servers step and look for their tools. Servers that need extra runtimes (for example uv or pipx) need those installed in copilot-setup-steps.yml.

Configure the GitHub remote MCP server

The GitHub MCP server gives agents GitHub data — repositories, issues, pull requests, Actions runs, code scanning alerts. It comes in two forms: the remote server hosted by GitHub at https://api.githubcopilot.com/mcp/ (recommended for most users) and a local server you run yourself (the ghcr.io/github/github-mcp-server image). GitHub Enterprise Server supports only the local server.

KnobRemote serverLocal server
Enable toolsetsX-MCP-Toolsets: repos,issues header, or a toolset URL such as /mcp/x/actionsGITHUB_TOOLSETS env var or --toolsets
Individual toolsX-MCP-Tools headerGITHUB_TOOLS / --tools
Read-onlyAppend /readonly to the URL, or X-MCP-Readonly: trueGITHUB_READ_ONLY=true
LockdownX-MCP-Lockdown — hides public issue content from users without push access (a content filter, not a security boundary)GITHUB_LOCKDOWN_MODE
AuthenticationOne-click OAuth in the IDE, or a PATPAT or GitHub App credentials
Remote-only toolsetscopilot (for example, create a PR with Copilot cloud agent) and support docs search—

The default toolsets are repos, issues and pull_requests; others such as actions, code_security and secret_protection are opt-in.

.vscode/mcp.json
// .vscode/mcp.json — the remote GitHub MCP server in VS Code
{
  "servers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/"
    }
  }
}

Inside Copilot cloud agent

Cloud agent gets the GitHub MCP server automatically, connected with a specially scoped token that has read-only access to the current repository only. To give it wider access — for example, to read issues in another repository — configure the server yourself in repository MCP settings with a PAT or a GitHub App, preferably still on the /readonly URL, and store the credential as a COPILOT_MCP_ Agents secret.

Wider but still read-only GitHub access
{
  "mcpServers": {
    "github-mcp-server": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/readonly",
      "tools": ["*"],
      "headers": {
        "X-MCP-Toolsets": "repos,issues,pull_requests,actions,code_security"
      }
    }
  }
}

Configure MCP registries

A registry is a catalogue of MCP servers. IDEs use the GitHub MCP Registry by default; an organization or enterprise can point Copilot at a custom registry so developers discover a curated set of approved servers. A custom registry can be self-hosted (fork the open-source MCP Registry, run it in Docker, or build your own) or provided by Azure API Center with anonymous read access. It must follow the v0.1 registry specification:

Required endpoints and CORS headers
GET /v0.1/servers
GET /v0.1/servers/{serverName}/versions/latest
GET /v0.1/servers/{serverName}/versions/{version}

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type

Enter the registry's base URL in the Copilot policies (enterprise: AI controls → MCP; organization: Settings → Copilot → Policies). For Azure API Center, give the base URL only — not /v0.1/servers.

Configure MCP allow lists

Organizations have three levers, from coarse to fine:

  1. The "MCP servers in Copilot" policy decides whether MCP servers can run at all in Copilot clients for Business and Enterprise users.
  2. Registry-based restriction — "Restrict MCP access to registry servers": Allow all (any server) or Registry only (only servers in the configured registry; even local servers must be listed, with exactly matching IDs). The policy applies immediately.
  3. managed-settings.json allowlists — allowedMcpServers and deniedMcpServers, matching servers securely by name, URL or exact stdio command. This is the method GitHub now recommends.
managed-settings.json
{
  "allowedMcpServers": [
    { "serverUrl": "https://api.githubcopilot.com/*" },
    { "serverCommand": ["npx", "@playwright/mcp@latest"] }
  ],
  "deniedMcpServers": [
    { "serverCommand": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/"] }
  ]
}
Custom registry restrictionmanaged-settings.json allowlist
Release phasePublic preview, not prioritizedGenerally available, recommended
MatchingBy name or ID only — users can bypass it by editing config filesBy name, URL or exact command — secure matching
SetupHost an HTTPS registry that meets the specA settings file, usually in the enterprise's .github-private repository, or deployed by MDM

Managed-settings evaluation is strict and predictable:

  1. Built-in default servers (such as the GitHub MCP server) are always allowed.
  2. A server matching any deniedMcpServers entry is blocked — deny beats allow.
  3. If allowedMcpServers exists, anything not matching it is blocked.
  4. A URL or command containing an unresolved variable is blocked, because it cannot be verified.
  5. A malformed list is treated as an empty allowlist — everything except built-ins is blocked.

Registries and allowlists do not govern cloud agent

Private MCP registries and registry-based restrictions apply to Copilot CLI and IDEs, not to agents running on GitHub. For Copilot cloud agent, MCP servers are controlled through repository MCP settings and custom agent profiles (including enterprise-level profiles), plus each server's tools allowlist. "Private MCP registries" is explicitly listed among the policies that do not apply to cloud agent.

2.3 Integrate agents within development environments

Evaluate the execution context

Execution context is the set of constraints that define where an agent runs and what it can reach: the repository, the branch, the workflow or machine it runs on, and the permissions it holds. It determines both visibility and capability.

ContextRuns onIdentity and tokenNetworkLimits
Copilot cloud agentEphemeral GitHub Actions runner (Ubuntu x64 by default; Windows 64-bit supported; no macOS)Its own scoped token; can push only to its branchAgent firewall with a recommended allowlistOne repository, one branch, one PR per task, 59-minute session
Copilot CLI (local)Your machineYour account and your file-system rightsYour network; URL approvalsWhatever you approve — consider local sandboxing
Copilot CLI in ActionsA workflow runnerGITHUB_TOKEN (with copilot-requests: write) or a PAT in COPILOT_GITHUB_TOKENRunner networkWorkflow permissions; -p denies anything not pre-approved
GitHub Agentic WorkflowsContainerized Actions jobRead-only token by default; no secrets in the agent processFirewalled, allowlisted egressWrites only through safe-outputs, after threat detection
IDE agent modeYour workspaceYour accountYour networkIDE settings and approvals

Scope an agent to a specific repository

Repository scope is the first boundary. Copilot cloud agent can only change the repository specified when the task starts — it cannot change several repositories in one run — and by default it can only read context (issues, past PRs) from that repository through its GitHub MCP token.

  • Availability — for Business and Enterprise, an administrator enables the cloud agent policy (disabled by default); organization owners can opt out some or all repositories; Pro, Pro+ and Max users have it on by default.
  • Per-repository configuration — Settings → Copilot → Cloud agent (validation tools, workflow approval), MCP servers, Internet access (firewall), Memory.
  • Custom agents — a profile in .github/agents/ applies to that repository; organization and enterprise profiles live in the agents/ folder of a .github or .github-private repository. On a name conflict, the lowest level wins: repository over organization over enterprise.

The Learn module's applyTo example

One Learn unit shows an agent profile with an applyTo glob. In the GitHub documentation, applyTo belongs to path-specific instruction files (.github/instructions/*.instructions.md), not to custom agent profiles, whose frontmatter properties are name, description, target, tools, model, disable-model-invocation, user-invocable, mcp-servers and metadata. To narrow what an agent works on, restrict its tools and state its scope in the prompt; to enforce path limits, use CODEOWNERS and hooks.

Configure an agent to be invoked in a CI workflow

Inside a workflow, the workflow is the execution boundary: the trigger, the runner, the permissions block and the secrets define everything the agent can do. There are three ways in:

ApproachWhenKey details
GitHub Agentic Workflows (recommended)Recurring, bounded repository tasks: triage, reports, docs upkeep, CI failure analysisMarkdown + frontmatter, compiled with gh aw compile to a .lock.yml; read-only by default; safe-outputs; engine defaults to Copilot
Copilot CLI in a job stepA one-off scripted task in an existing pipelinenpm install -g @github/copilot; copilot -p with minimal --allow-tool; --no-ask-user; -s for clean output; --agent to pick a custom agent
Hand off to cloud agentThe CI job should produce a PR, not do the work itselfREST API agent tasks, the GitHub MCP server's Copilot tools, or an automation
flowchart TB
  TRIG["Trigger<br/>schedule · workflow_dispatch · pull_request"] --> JOB
  subgraph JOB["Workflow job — the execution boundary"]
    direction TB
    CO["Checkout"] --> INST["Install Copilot CLI<br/>npm install -g @github/copilot"]
    INST --> RUN["copilot -p prompt<br/>--allow-tool · --no-ask-user · -s"]
    RUN --> OUT["Publish result<br/>step summary · artifact · safe output"]
  end
In CI the job is the boundary — the agent inherits exactly the runner, token permissions and secrets the job grants.
.github/workflows/nightly-summary.yml
name: Nightly repository summary
on:
  schedule:
    - cron: '30 17 * * *'
  workflow_dispatch:

permissions:
  contents: read
  copilot-requests: write      # lets GITHUB_TOKEN make Copilot requests (org billing)

jobs:
  summary:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v7
      - run: npm install -g @github/copilot
      - name: Summarize today's changes
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          copilot -p "Summarize today's commits on main as a bullet list in summary.md" \
            -s --no-ask-user \
            --allow-tool='shell(git:*)' --allow-tool='write(summary.md)'
          cat summary.md >> "$GITHUB_STEP_SUMMARY"
Using a custom agent in CI
copilot --agent security-reviewer \
  -p "Review the diff against main for vulnerabilities" \
  -s --no-ask-user --allow-tool='shell(git:*)'

Authentication options for the CLI in Actions:

  • GITHUB_TOKEN — recommended in organization repositories: short-lived, no stored secret, usage billed to the organization. Requires the policy Allow use of Copilot CLI billed to the organization and copilot-requests: write in permissions.
  • A fine-grained PAT with the Copilot Requests permission, stored as an Actions secret and passed as COPILOT_GITHUB_TOKEN — the CLI-specific variable, so Copilot's access can differ from the workflow's GITHUB_TOKEN. Usage is billed to the PAT owner's seat.

Fork pull requests are the risky trigger

Running an agent directly in a workflow step gives it broad access to that environment. Workflows triggered by pull requests from forks are the highest prompt-injection risk; keep permissions minimal and prefer Agentic Workflows, which isolate secrets from the agent process.

Configure an agent to use branch-based scope

  • Cloud agent creates a new copilot/ branch for its work and can only push to that single branch. When triggered by @copilot on an existing PR, it gets write access to that PR's branch instead.
  • You can choose the base branch when starting a task from the Agents tab or panel, so the working branch is cut from, and the PR targets, something other than the default branch.
  • The agent is subject to the repository's branch protections and required checks like any contributor.
  • In CI, the workflow determines the branch — the agent runs in the checked-out ref.
  • Custom agents define focus, tools and behaviour; they do not control branch creation, PR behaviour or execution isolation — that is always the execution context's job.

Enable autonomous actions: branches and pull requests

  1. Enable the agent — policy for Business/Enterprise, and the repository not opted out.
  2. Give it a task — assign an issue to Copilot (it reacts 👀 and opens a draft PR), prompt it from the Agents tab, mention @copilot on a PR, delegate from the CLI with /delegate or an & prefix, or call the API.
  3. Let it work — it researches, plans, creates the branch, commits and pushes, validating with tests and linters in its environment.
  4. Create the pull request — sessions started from the Agents tab do not open a PR automatically; click Create pull request when satisfied, or ask for one in the prompt. Issue assignment and /delegate open a draft PR.
  5. Review and merge — a human marks it ready, approves and merges. Copilot cannot mark it ready for review, approve it or merge it.

When rulesets block the agent

If a ruleset is incompatible with the agent — for example, it only allows specific commit authors — access to cloud agent is blocked. The documented fix is to add Copilot as a bypass actor on that ruleset — which is one reason to express agent policy as rulesets rather than classic branch protection. Copilot can sign its commits, so "require signed commits" is not by itself a blocker.

Handle environment-specific constraints

Cloud agent can discover and install dependencies by trial and error, but that is slow, non-deterministic and fails for private packages. Make the environment deterministic with a Copilot setup steps workflow.

.github/workflows/copilot-setup-steps.yml
name: "Copilot Setup Steps"
on:
  workflow_dispatch:
  push:
    paths: [.github/workflows/copilot-setup-steps.yml]
  pull_request:
    paths: [.github/workflows/copilot-setup-steps.yml]

jobs:
  copilot-setup-steps:          # MUST be named exactly this
    runs-on: ubuntu-latest      # or a larger / self-hosted / Windows runner label
    timeout-minutes: 30         # maximum 59
    permissions:
      contents: read            # Copilot gets its own token for its work
    steps:
      - uses: actions/checkout@v7
        with:
          lfs: true
      - uses: actions/setup-node@v7
        with:
          node-version: "24"
          cache: "npm"
      - run: npm ci
  • The file must contain a single job named copilot-setup-steps, and it only takes effect once it is on the default branch.
  • Only steps, permissions, runs-on, services, snapshot and timeout-minutes (max 59) can be customized; anything else is ignored.
  • If a step exits non-zero, the remaining setup steps are skipped and Copilot starts work with the environment as it is.
  • Any fetch-depth you set on actions/checkout is overridden so the agent can roll back commits on request.
  • The workflow's GITHUB_TOKEN is used by the setup steps only; Copilot receives its own token for the session.
ConstraintConfiguration
Private dependencies or internal registryAgents secrets and variables (Settings → Secrets and variables → Agents), used by setup steps; firewall allowlist entry for the registry host
More CPU, memory or private networkingruns-on a larger runner label; with Azure private networking, allow the Copilot API hosts outbound
Access to internal resourcesSelf-hosted ephemeral runners (ARC or scale sets); disable the integrated firewall, which is not compatible; set proxy variables if needed
Windows toolchainWindows runner label — the integrated firewall is not compatible with Windows, so pair it with your own network controls
Large filesactions/checkout with lfs: true in setup steps
Services such as a databaseservices: in the setup steps job
Blocked outbound requestAdd the domain or URL to the custom allowlist (organization or repository, under Internet access)
Session too longThe 59-minute session limit cannot be raised — split the task

The agent firewall

By default cloud agent's internet access is limited by a firewall, which reduces the risk of code or secrets being exfiltrated by unexpected behaviour or injected instructions. GitHub hosts are always reachable; a recommended allowlist (OS package repositories, container registries, language package registries, certificate authorities, Playwright browser downloads) is on by default. Blocked requests appear as a warning in the PR.

  • Organization owners set Enable firewall and Recommended allowlist to Enabled, Disabled or Let repositories decide (the default), control whether repositories may add custom rules, and maintain an organization custom allowlist that repositories cannot remove.
  • Allowlist entries are domains (the domain and its subdomains) or URLs (scheme, host and path prefix).
  • Limitations: it applies only to processes the agent starts through its shell tool — not to MCP server processes or setup-step processes — only inside the Actions appliance, and sophisticated attacks may bypass it. It is a mitigation, not a complete security boundary.

2.4 Operate agents with safe execution paths and robust error handling

Reliable systems assume failure: agents misread tasks, tests fail, changes collide. The architecture should detect failure early, contain it, and hand it to a person with enough context to act.

flowchart TB
  FAIL["Required check fails"] --> RETRY{"Attempts < 2?"}
  RETRY -->|"yes"| FIX["Agent revises the branch<br/>and re-runs checks"]
  FIX --> FAIL2{"Green?"}
  FAIL2 -->|"yes"| REVIEW["Human review and merge"]
  FAIL2 -->|"no"| RETRY
  RETRY -->|"no"| ESC["Escalate<br/>what failed · what was tried · evidence · next step"]
  ESC --> HUMAN["Human decides<br/>fix · close PR · revert"]
A safe iteration policy: bounded retries on the branch, then escalation with evidence — never an infinite loop.

Implement error handling

  • Fail fast in workflows — leave continue-on-error false, use set -euo pipefail in scripts, and never let a failed agent step be reported as green.
  • Log meaningfully — ::error:: annotations, step summaries and uploaded logs rather than silent failure.
  • Prevent partial changes — work on a branch so an aborted run leaves nothing on the default branch.
  • Hook into errors — the errorOccurred hook fires on agent errors (logging, alerting), and postToolUseFailure can add recovery guidance for the model after a failed tool call.

Implement retries

Retry transient failures — a network blip, a flaky runner — a bounded number of times, with backoff. Do not retry deterministic failures (a real test failure, a security block): that only burns time and AI credits.

yaml
- name: Run agent task with bounded retries
  run: |
    for attempt in 1 2 3; do
      if copilot -p "Fix the failing unit tests" -s --no-ask-user \
           --allow-tool='shell(npm:*)' --allow-tool=write; then
        exit 0
      fi
      echo "::warning::Attempt $attempt failed"
      sleep $((attempt * 10))
    done
    echo "::error::Agent failed after 3 attempts — escalating"
    exit 1
  • Copilot CLI autopilot has --max-autopilot-continues to cap automatic continuations; set it explicitly in automation.
  • An agentStop hook that keeps forcing continuation is overridden after 8 consecutive blocks — a runaway guard.
  • A common team policy: if the same required check fails twice, stop iterating and escalate.

Implement rollbacks

SituationRollback
Agent output is wrong, not mergedRequest changes, or close the PR and delete the branch — branch isolation means nothing reached main
Already mergedRevert the merge commit through a new PR; small, scoped PRs make this safe
Copilot CLI session went wrongPress Esc twice when idle (or /rewind) and choose "rewind conversation" or "rewind and restore files"
Bad deploymentRedeploy an explicit earlier commit or tag — deploy by reference, not "latest on a branch"
Cloud agent should undo its own commitAsk it — it keeps enough history to roll back commits on request

CLI rewind restores only the files Copilot changed, skips files you edited since, and cannot restore files over 10 MB or turns that changed more than 500 files.

Implement escalation paths

  • Required review — every agent PR reaches a human; CODEOWNERS auto-requests the right one.
  • Notify on failure — an if: failure() step that opens an issue or pings maintainers with the run link.
  • Deny with a reason — a preToolUse hook denies a risky tool call and returns permissionDecisionReason, which is surfaced for a human to act on.
  • Steer or stop — follow-up prompts on the Agents page, or Stop session.
  • A clear escalation report — what failed, what was attempted, what evidence exists, and the suggested next step.
yaml
- name: Escalate to maintainers
  if: failure()
  env:
    GH_TOKEN: ${{ github.token }}
  run: |
    gh issue create \
      --title "Agent run ${{ github.run_id }} needs a human" \
      --label needs-human \
      --body "Failed step logs: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"

Implement traceability and accountability

QuestionWhere the answer lives
Who started this?Commit co-author, the automation's creator, audit log user field
Was it really the agent?Commits authored by Copilot and signed ("Verified"); audit events with actor_is_agent: true
Why was this change made?The session log linked from every commit message; the plan in the PR
What did it run?Session log tool calls; workflow run logs; hook audit logs
Which session produced this event?agent_session_id on audit log events (filter with actor:Copilot, 180 days)
What is it doing right now?The Agents page, or gh agent-task view --log --follow

Make evidence traceable to a run and a commit

Name and label evidence so an auditor can answer "which run produced this artifact, against which code state?" — for example, include the commit SHA and run ID in the artifact name, and link both from the PR's Evidence section. The guardrails page covers audit and governance cadence.