Cloud & Background Agents

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

This page covers the two background-agent products in the AI section’s tool set: the Copilot cloud agent (formerly called Copilot coding agent) and Claude Code on the web / GitHub Actions, checked against the official Copilot docs and Claude Code — GitHub Actions as of 2026-09-28. Both run a task on a remote machine from a short instruction — an assigned issue or an @-mention — and open a pull request for review, instead of working in a session you drive turn by turn the way Claude Code and Copilot do locally. The running example is again DocsAssistant API, the Spring Boot + Python sample with its controller at src/main/java/com/example/docsassistant/DocsController.java and a Python ingestion script under ingest/.

Copilot cloud agent

Assigning an issue

The most direct way to start a cloud-agent run is assigning a GitHub issue to Copilot the same way you would assign it to a teammate: open the issue on github.com and set Copilot as the assignee (or, on a pull request, comment @copilot with the change you want). Copilot then researches the repository, drafts an implementation plan, and starts making changes on a new branch — all inside a GitHub Actions-backed environment, so the whole run is visible as commit history and job logs rather than a private session. Suppose issue #241 in the DocsAssistant repository reads:

Title: Add a health endpoint
Body: Add GET /api/health to DocsController that returns 200 with {"status":"ok"}.
Add a test for it under src/test/java/com/example/docsassistant/.

Assigning that issue to Copilot starts a run that ends with a draft pull request implementing it. See GitHub — About Copilot cloud agent.

Setting up the environment: copilot-setup-steps.yml

By default, the cloud agent’s environment starts from a base image with common language runtimes already installed and no repository-specific setup. A workflow file at .github/workflows/copilot-setup-steps.yml, containing a single job named exactly copilot-setup-steps, runs before the agent starts working, so its steps can install dependencies, restore caches, or install project tooling the agent will need; only steps, permissions, runs-on, services, snapshot and timeout-minutes are read from this job, and the workflow must exist on the repository’s default branch. For DocsAssistant API, a Java + Python repo, one job installs both toolchains and pre-fetches their dependencies:

In .github/workflows/copilot-setup-steps.yml
name: "Copilot Setup Steps"

on: workflow_dispatch

jobs:
  copilot-setup-steps:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-java@v5
        with:
          java-version: '21'
          distribution: 'temurin'
          cache: maven

      - name: Pre-fetch Maven dependencies
        run: mvn -B dependency:go-offline

      - uses: actions/setup-python@v6
        with:
          python-version: '3.12'
          cache: pip

      - name: Install ingestion script dependencies
        run: pip install -r ingest/requirements.txt

The on: workflow_dispatch trigger lets you also run this job manually from the Actions tab to confirm the setup steps still succeed, independent of any agent run. See GitHub — Customizing the development environment for Copilot cloud agent.

The firewall and the allowlist

Once running, the cloud agent’s outbound network access goes through a firewall that is on by default: it always allows the hosts Copilot itself needs to talk to GitHub, and a recommended allowlist (also on by default) additionally permits common OS package repositories, container registries, language package registries, certificate authorities and a few other categories, so mvn dependency:go-offline or pip install inside a run works without extra configuration. A repository admin adds further addresses under repository Settings → Copilot → Internet access → Custom allowlist, as either a bare domain (matches that domain and its subdomains, e.g. packages.contoso.corp) or a full URL restricted to one scheme, host and path (e.g. https://packages.contoso.corp/project-1/); the same settings page can also disable the firewall entirely where an organization policy allows it. When a request is blocked, Copilot doesn’t fail silently: it adds a warning to the pull request body (or a comment, if the PR already exists) naming the blocked address and the command that tried to reach it, which is usually enough to decide whether to allowlist it or change the approach. This firewall applies to commands the agent runs through its own shell tool; it does not cover MCP servers or the copilot-setup-steps job itself, so a dependency the setup job needs must already be reachable during that job. See GitHub — Customizing or disabling the firewall for Copilot cloud agent.

The PR loop and iterating via comments

All of the agent’s work happens on GitHub, not in a hidden sandbox: Copilot pushes commits to the branch as it goes, opens a pull request once it has something to show, and the PR’s own timeline is the run’s audit trail. Once the PR is open, review it the way you would a teammate’s: reading the diff, checking CI, and leaving comments. Commenting with feedback is how you iterate — 

@copilot the health endpoint should also check the database connection before returning "ok"

 — picks the agent’s run back up, and it pushes a follow-up commit addressing the comment rather than starting a new PR. Repeating this comment-review cycle is the normal way to drive a cloud-agent task to completion, and it is the same PR review, merge and cross-linking machinery documented in Pull Requests. See GitHub — About Copilot cloud agent.

Choosing the model

Where you start a cloud-agent task determines whether you get to choose its model: assigning an issue on github.com, @copilot-mentioning it in a pull request comment, or starting one from the Agents tab or panel (also GitHub Mobile and the Raycast launcher) all show a model picker before the run starts, offering an Auto option plus specific models from several providers; starting a run any other way defaults to Auto. Some models expose a second dropdown for a reasoning-effort level, trading more time and usage for more careful answers on harder tasks. Since the available models and their names change over time, pick from the picker’s current list rather than a hard-coded one here, and see Choosing Models in Your Assistant for how this compares to model selection elsewhere in Copilot and in Claude Code. See GitHub — Changing the AI model used by Copilot cloud agent.

Claude Code on the web / GitHub Actions

Claude Code reaches a repository on GitHub in two different ways that this sub-section keeps distinct: Claude Code in the cloud at claude.ai/code runs a full session on hosted infrastructure instead of your machine, started from the browser, the Claude app or claude --cloud; the Claude Code GitHub Action (anthropics/claude-code-action) is a workflow you add to the repository so @claude mentions and other GitHub events start a run inside GitHub Actions itself. Their GitHub prerequisites differ. A cloud session connects GitHub in one of two ways: authorizing the Claude GitHub App during web onboarding, or running /web-setup in a local Claude Code session, which sends your local gh CLI token to your Claude account so sessions can reach any repository that token can. The GitHub Action, and Auto-fix for pull requests in cloud sessions, require the Claude GitHub App installed on the repository, granting it read/write access to contents, issues and pull requests so it can push commits and comment.

Starting a cloud session

Open claude.ai/code, pick the DocsAssistant repository and type the task, or start the same session from a local checkout with the --cloud flag:

$ claude --cloud "add GET /api/health to DocsController that returns 200 with a JSON status of ok,
plus a test under src/test/java/com/example/docsassistant/"

The cloud VM clones the repository’s GitHub remote at your current branch, not your local working tree, so push any local commits first; the session keeps running after you close the terminal, and claude --teleport pulls it back into a local session later. As of 2026-09-28, cloud sessions are available on Pro, Max and Team plans and for Enterprise premium or Chat + Claude Code seats. See Claude Code — Use Claude Code in the cloud.

Installing the GitHub App and @claude mentions

The fastest path is running /install-github-app inside a local Claude Code session, which installs the Claude GitHub App, stores an ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN repository secret, and opens a pull request adding the workflow file:

$ claude
> /install-github-app

Without a local Claude Code session, install the Claude GitHub App manually, add one of those two secrets under repository Settings → Secrets and variables → Actions, and copy the workflow file from the action’s own examples/claude.yml into .github/workflows/. Either way, once the workflow is merged, mentioning @claude in an issue or pull request comment starts a run:

@claude add a GET /api/health endpoint to DocsController that returns {"status":"ok"}, with a test

Claude replies on that same issue or PR with a comment, and updates it as it works. See Claude Code — GitHub Actions.

The claude-code-action workflow

The action detects two modes from the workflow’s own inputs: leaving out a prompt puts it in interactive mode, responding only when the trigger phrase (@claude by default) appears; setting a prompt puts it in automation mode, running on whatever event triggers the workflow with no mention needed. A minimal interactive workflow, the "Respond to @claude mentions" example from the Claude Code GitHub Actions docs:

In .github/workflows/claude.yml
name: Claude Code
on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]
jobs:
  claude:
    if: contains(github.event.comment.body, '@claude')
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write
      id-token: write
      actions: read
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

The if condition keeps the job from starting a runner for every comment; the action itself checks the trigger phrase again, and separately requires the commenting user to have write access to the repository and not be a bot, unless explicitly allowed. id-token: write is needed for the action’s GitHub App authentication and actions: read lets Claude read CI results on the PR. Passing CLI options — for example capping turns and naming a model — goes through claude_args, using the same baseline model as the rest of this sub-section:

      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          claude_args: |
            --max-turns 5
            --model claude-sonnet-5

See Claude Code — GitHub Actions and Headless & CI Automation for claude -p and other non-interactive uses of the CLI itself.

Choosing tasks and reviewing the result

A checklist for bounded, measurable tasks

Both agents run unattended for minutes at a time before you see a result, so the task you hand one matters more than with an interactive session where you can redirect it mid-turn. Before assigning an issue or firing off an @claude mention, check that the task is:

  • Bounded — one endpoint, one bug, one refactor; not "improve the API" or "modernize the codebase".

  • Locatable — the issue or prompt names the file or module to change, e.g. DocsController.java, not just a symptom.

  • Verifiable — there is an existing test, or the task asks for one, that the agent (and you) can run to check the result, rather than relying on eyeballing the diff.

  • Independent — it doesn’t depend on another in-flight change to the same files, which invites merge conflicts once the PR is ready.

  • Reviewable in one pass — the expected diff is small enough that Reviewing AI-Generated Code's checklist can be applied to the whole PR at once.

A task like "add GET /api/health returning \{"status": "ok"}, with a test" satisfies all five; "clean up the ingestion pipeline" satisfies none of them and is better run as an interactive session where you can steer it, per Agent Mode.

"Coherent incorrectness"

A background agent’s plan-then-execute loop tends to produce pull requests that are internally consistent — matching naming, matching style, a plausible-looking test — even when the underlying approach is wrong, for example solving the wrong ambiguity in the issue, or adding a health check that always returns ok without actually checking the database. Nothing about the diff looks wrong, which is exactly what makes this failure mode easy to approve without reading closely; a well-formed PR is not the same signal as a correct one. The practical defense is unchanged from any other PR: read the diff against the original issue’s acceptance criteria, not just against "does this compile and pass CI", and treat a cloud-agent PR as a first draft from an unfamiliar contributor rather than as ground truth.

flowchart LR I["Issue assigned\nor @claude mention"] --> A["Agent plans\nand edits"] A --> P["Pull request opened"] P --> R["Human review"] R -->|comment| A R -->|approve| M["Merge"]

See Pull Requests for the review and merge mechanics this loop relies on, and Issue for a worked issue-to-PR pipeline built on top of the same idea.