Skip to content

Lab 13: Copilot cloud agent

Time
About 35 minutes
Level
advanced
Platforms
Windows 11, macOS (file mode, no Desktop)
Copilot surfaces
github.com, Copilot cloud agent, VS Code
You'll use
cloud-agent, custom-agent, skill, hook, apm
Starts from
lab09-complete: Adds AI metadata: Q&A on, default labels, and the fabric/ai-prep drafts.
Ends at
lab09-complete: Adds AI metadata: Q&A on, default labels, and the fabric/ai-prep drafts.
Last verified
Not yet run end to end on Windows 11

Works on macOS

Nobody has run this lab end to end on Windows 11 yet. The steps follow the current docs for each tool, but menu labels may differ. The verify command at the end is the source of truth, and feedback is welcome.

Some model work is clear enough to hand to an agent and review later. Copilot cloud agent is built for that kind of scoped issue. It runs in a GitHub Actions-backed environment, creates a branch, pushes commits, and raises a pull request for you to review. In this lab you give it a small AI-readiness change: add descriptions and synonyms for Payer Type, whose source column is payer_typ.

The cloud agent runs on Linux by default. It doesn’t have Power BI Desktop, so this lab avoids live Desktop and DAX work. The agent edits TMDL and YAML as text, then relies on the repo’s lint, report binding checks, and bash hooks.

  • Copilot cloud agent: a GitHub-hosted agent that researches an issue, plans, edits code, validates, and pushes a branch. It is different from local VS Code agent mode because it works in its own cloud session. Needs a paid Copilot plan
  • Setup steps: .github/workflows/copilot-setup-steps.yml prepares the agent environment before work starts. The job must be named copilot-setup-steps.
  • Custom cloud agent: the assignment dialog can pick a repository custom agent, such as model-improver, so the cloud task uses the same role and tool boundaries you used locally.
  • Session log: the GitHub Agents view shows setup, commands, file changes, validation, and follow-up prompts. Use it to audit what the agent did.
  • Iteration by PR comment: after the agent opens a pull request, a top-level @copilot comment asks it to continue on that PR branch.
  • You finished Lab 12 or restored lab09-complete and pushed the repo to your own GitHub copy.
  • You have GitHub CLI signed in, because the verify check reads pull requests with gh.
  • Your Copilot plan supports Copilot cloud agent, and the repository has the feature enabled. Business and Enterprise seats may also need an org admin policy. Needs a paid Copilot plan
  • The upstream branch has .github/workflows/copilot-setup-steps.yml on the default branch. GitHub only uses setup steps after they are on the default branch.

Start by checking what the cloud agent gets before it starts the issue.

  1. In VS Code, open Explorer: Ctrl+Shift+E (macOS: Cmd+Shift+E), or View > Explorer.
  2. Open .github/workflows/copilot-setup-steps.yml.
  3. Check the job name, runner, pinned setup actions, Python version, Node version, and APM install.
  4. Open .github/hooks/guardrails.json and note that every hook has a bash command and a PowerShell command. On the cloud Linux runner, the bash form runs.

The setup job installs the same repo tools you used locally and installs the pinned Skills for Fabric skill with APM:

.github/workflows/copilot-setup-steps.yml (lines 16-43)
jobs:
copilot-setup-steps:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
- name: Python tools and validation
shell: pwsh
run: ./scripts/Initialize-DevEnvironment.ps1
# Installs the pinned Skills for Fabric skill from apm.yml into .agents/skills, where the
# cloud agent discovers project skills. --only apm skips the MCP servers that package declares.
- name: Skills for Fabric (APM)
run: |
python -m venv "$RUNNER_TEMP/apm"
"$RUNNER_TEMP/apm/bin/pip" install --disable-pip-version-check --quiet apm-cli==0.31.0
"$RUNNER_TEMP/apm/bin/apm" install --only apm --target copilot

The hooks are configured for both shells:

.github/hooks/guardrails.json (lines 13-29)
"preToolUse": [
{
"type": "command",
"bash": "./scripts/hooks/run-hook.sh pre-tool-use",
"powershell": "pwsh -NoProfile -File ./scripts/hooks/run-hook.ps1 -HookEvent pre-tool-use",
"cwd": ".",
"timeoutSec": 20
}
],
"postToolUse": [
{
"type": "command",
"bash": "./scripts/hooks/run-hook.sh post-tool-use",
"powershell": "pwsh -NoProfile -File ./scripts/hooks/run-hook.ps1 -HookEvent post-tool-use",
"cwd": ".",
"timeoutSec": 30
}

You should see: runs-on: ubuntu-latest, Python 3.12, Node 22, apm-cli==0.31.0, and ./scripts/hooks/run-hook.sh for Linux hook events.

The cloud agent works best when the issue states the object, the source column, and the acceptance checks. Use the prompt file to draft the issue, then paste it into GitHub.

  1. Open Copilot Chat in VS Code: Ctrl+Alt+I (macOS: Ctrl+Cmd+I), or View > Chat.
  2. Open the Command Palette: Ctrl+Shift+P (macOS: Cmd+Shift+P), then run Chat: Run Prompt.
  3. Pick create-cloud-agent-issue.
  4. When prompted for the change, enter:
Add descriptions and synonyms for Payer Type.
  1. Review the drafted issue. Make sure it uses these facts:
    • Goal: make Payer Type clearer for people and AI tools.
    • Objects in scope: Prescription Fill table, Payer Type column, source column payer_typ, and fabric/ai-prep/synonyms.yaml.
    • Out of scope: no new measures, no Desktop-only work, no real data.
    • Acceptance: pwsh ./scripts/Invoke-Validation.ps1 and pwsh ./scripts/Test-ReportBindings.ps1 pass.
  2. On GitHub.com, open your repo, then Issues > New issue > Semantic model change.
  3. Paste the text into the form fields and select Submit new issue.

The issue form already asks for the fields the cloud agent needs:

.github/ISSUE_TEMPLATE/model-change.yml (lines 10-45)
- type: textarea
id: goal
attributes:
label: Goal
description: What should the model do after this change? Write it as the business question or behavior you want.
placeholder: Add a measure that shows the share of fills paid by Medicare, with a description and a display folder.
validations:
required: true
- type: textarea
id: scope
attributes:
label: Objects in scope
description: Tables, columns, measures, or report pages this change should touch.
placeholder: "'Prescription Fill' table, Payer Type column, new measure in the Payer display folder"
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: How will a reviewer know it's done? Include the validation command.
value: |
- [ ] `pwsh ./scripts/Invoke-Validation.ps1` passes
- [ ] New or changed objects have descriptions and display folders
- [ ] `pwsh ./scripts/Test-ReportBindings.ps1` passes
validations:
required: true
- type: dropdown
id: agent
attributes:
label: Suggested custom agent
options:
- model-improver
- model-assessor
- model-reviewer
- none

The prompt reminds you not to ask for Desktop or live DAX work:

.github/prompts/create-cloud-agent-issue.prompt.md (lines 11-22)
Follow the `model-change` issue form in `.github/ISSUE_TEMPLATE/model-change.yml`. Use its headings:
- **Goal**: the business behavior you want, in one or two sentences.
- **Objects in scope**: the exact table, column, and measure names in the current model. Check the TMDL so they exist.
- **Acceptance criteria**: a checklist the agent can verify itself. Keep the form's three default items and add specifics, such as exact measure names, display folders, and format strings.
- **Suggested custom agent**: `model-improver`.
Add an **Out of scope** line under Goal listing what the agent must not change.
The cloud agent runs on Linux without Power BI Desktop, so don't ask for anything that needs Desktop or live DAX results.
Show me the issue text. Don't create the issue unless I ask. If I do, create it with the `model-change` label, using `gh issue create` or the GitHub MCP server.

You should see: a new issue titled similar to [model] Add descriptions and synonyms for Payer Type, labeled model-change, with model-improver listed as the suggested custom agent.

Needs a paid Copilot plan

GitHub’s current issue flow starts a cloud agent session by assigning the issue to Copilot. You can also choose a custom agent in the assignment dialog.

  1. Open the issue you created.
  2. In the right sidebar, select Assignees.
  3. Select Copilot from the assignee list.
  4. In the Assign to Copilot dialog, keep the target repository as your lab copy and the starting branch as the default branch.
  5. Open the agent dropdown, the Copilot icon in the dialog, and choose model-improver.
  6. In Optional prompt, add:
Use the model-improver agent. Edit TMDL and fabric/ai-prep text files only. Do not require Power BI Desktop. Keep sourceColumn payer_typ unchanged. Run pwsh ./scripts/Invoke-Validation.ps1 before opening the PR.
  1. Start the task.

You should see: an issue timeline event saying Copilot started work, and a new session in the repository Agents tab or the global Agents page.

Step 4. Follow the session and open the PR

Section titled “Step 4. Follow the session and open the PR”

Open the session log while Copilot works. This step is the lab check anchor: it passes when a pull request authored by Copilot exists.

  1. On GitHub, open your repository.
  2. Select the Agents tab, or open the global Agents panel from the top-right GitHub navigation and choose this session.
  3. Watch the setup section. It should show copilot-setup-steps, Python setup, Node setup, initialization, and APM install.
  4. Watch the command section. You should see validation commands such as pwsh ./scripts/Invoke-Validation.ps1.
  5. When Copilot finishes, select Open pull request if it hasn’t already opened one.
  6. Open the pull request.

You should see: a pull request authored by Copilot. The changed files should be limited to model metadata and AI-prep text files, such as fabric/ContosoPharmacy.SemanticModel/definition/tables/Prescription Fill.tmdl and fabric/ai-prep/synonyms.yaml.

Now treat the agent’s work like any other pull request.

  1. In the PR, open Files changed.
  2. Confirm sourceColumn: payer_typ did not change.
  3. Confirm the Payer Type description is short, business-facing, and not medical advice.
  4. Confirm fabric/ai-prep/synonyms.yaml adds payer-related phrases, such as payer, insurance type, plan type, payment type, and payer mix.
  5. Open the Checks tab and wait for CI.
  6. Add a top-level PR comment:
@copilot also add an example prompt about payer mix to the changed AI-prep file, if there is an appropriate section. Keep validation green.
  1. Watch for an eyes reaction and a timeline event that Copilot started work.

You should see: a new Copilot session tied to the PR, then a follow-up commit or comment. If the requested file doesn’t have an appropriate section, Copilot should explain that instead of inventing a new file.

You decide whether to keep the change in your lab copy.

  1. If the PR is useful, select Merge pull request on GitHub, then Confirm merge.
  2. If you don’t want the change, select Close pull request. Closing is fine for the lab check, because the check only verifies that a Copilot-authored PR exists.
  3. Back in VS Code, update your local default branch if you merged:
Terminal window
git switch main
git pull

You should see: either a merged PR and local branch updated, or a closed PR you can still inspect later.

Run this from the repo root in a PowerShell 7 terminal (Terminal > New Terminal in VS Code):

Terminal window
pwsh ./scripts/lab/Test-LabProgress.ps1 -Lab 13

When everything is done you should see:

Expected output
PASS L13-cloud-agent-pr A pull request authored by Copilot exists
Lab 13: 1 of 1 checks passed.

Each FAIL line prints a hint and a link back to the step on this page that fixes it. The command exits with code 0 when every required check passes.

CheckWhat it looks atIf it fails
L13-cloud-agent-prA pull request authored by Copilot existsAssign a model-change issue to Copilot. Needs gh signed in. Go to step 4
Copilot is not listed as an assignee

Copilot cloud agent is not enabled for the repository, your plan doesn’t include it, or an org policy blocks it. The feature requires a paid Copilot plan. For Business and Enterprise, ask an admin to enable Copilot cloud agent for the organization and repository.

The setup steps fail before Copilot starts editing

Open the session log and expand copilot-setup-steps. The common causes are package downloads blocked by firewall rules, a changed APM installer, or a workflow edit that changed the job name. The job must be named copilot-setup-steps, and the repository firewall must allow GitHub Actions and package registry traffic.

Copilot tries to use Power BI Desktop or live DAX

Comment on the PR: @copilot do not use Power BI Desktop or live DAX in this cloud session. Edit TMDL and AI-prep files as text, then run pwsh ./scripts/Invoke-Validation.ps1. The cloud agent can use the text model checks without Desktop.

The PR changes too many files

Ask Copilot to narrow the scope on the PR: @copilot revert unrelated files. Keep only the Payer Type description and synonyms changes, then rerun validation. If it still overreaches, close the PR and start a smaller issue.

Why does the Lab 13 issue include acceptance criteria instead of only a goal?

Show the answer

Cloud agent needs exact checks it can run without asking more questions.

The agent can work in the background only when it knows what done means. Checks such as Invoke-Validation.ps1 give it a concrete finish line, but you still review the PR.

What does the cloud agent do when you assign an issue to Copilot?

Show the answer

It starts a GitHub-hosted session, creates a branch, pushes changes, and raises a PR.

Cloud agent runs in a GitHub Actions-backed environment. It does not use your local Desktop session.

Where should you add new instructions after Copilot has already been assigned the issue?

Show the answer

As a top-level PR comment with @copilot, because the PR branch is where follow-up work happens.

GitHub sends the current issue context at assignment time. Use @copilot on the PR for follow-up work.

You delegated a small semantic model task to Copilot cloud agent, picked the model-improver custom agent, watched the setup and validation in the session log, and reviewed a Copilot-authored pull request. You also saw why cloud tasks need tight scope when Desktop isn’t available.

Next: Lab 14: Build your own agent, skill, and prompt

  • Create a second issue that asks Copilot to improve one description only. Compare the PR size with this lab’s PR.
  • Open the session log from the Copilot-authored commit link and note which validation command gave you the most confidence.
  • Try the same assignment without choosing model-improver, then close the session after the plan. Compare the plan to the custom agent run.