Skip to content

Lab 07: Handoffs, names, and descriptions

Time
About 45 minutes
Level
intermediate
Platforms
Windows 11, macOS (file mode, no Desktop)
Copilot surfaces
VS Code
You'll use
custom-agent, handoff, prompt-file, skill, hook
Starts from
lab06-complete: Adds a sample assessment (lab/samples/assessment.md, copied to out/assessment.md).
Ends at
lab07-complete: Business names, descriptions, hidden keys, display folders, and a rebound report.
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.

A person reading fact_rx_fill[proc_mins] can guess what it means. An AI tool can’t, and neither can a new analyst. Business names and one-line descriptions are the cheapest improvement you can make to a semantic model, and they’re what Copilot, Q&A, and data agents read first. In this lab you let an agent do the tedious part, and you learn why renames in a model-as-code repo always need a second step: fixing the report that refers to the old names.

  • Handoff: a button a custom agent shows after it answers. It switches the chat to another agent and pre-fills a prompt, so work moves along a chain (assess, improve, test, review) with context carried over. See Copilot customization.
  • Prompt file: a reusable task you run with /name in chat. /improve-names-and-descriptions scopes this lab’s work so the agent doesn’t also add measures or change relationships. See Prompts.
  • Skill loading: the improver loads pharmacy-model-conventions (for the rename map), tmdl-authoring (for syntax), and pbir-rebinding (for the report). See Skills.
  • Lineage tag: the stable ID Power BI uses to track an object across renames. It must not change when the name does.
  • You finished Lab 06 and out/assessment.md exists.
  • The model-assessor chat from Lab 06 is still open, or you can reopen it from the chat history.
  • Close Power BI Desktop. The agent edits the .tmdl files directly in this lab. If Desktop has the project open, it can overwrite those edits when you save or close it.

The improver refuses to work on main, because every model change should arrive through a pull request (Lab 12).

Terminal window
git switch -c feature/ai-ready-names

You should see: Switched to a new branch 'feature/ai-ready-names'. The branch name also shows in the VS Code status bar, bottom left.

  1. Open Copilot Chat: Ctrl+Alt+I (macOS: Ctrl+Cmd+I), or View > Chat.
  2. Go back to the model-assessor conversation from Lab 06. If you closed it, open the chat history (the clock icon at the top of the Chat view) and pick it.
  3. Under the assessor’s last answer, click Fix these findings.

You should see: the agent picker switch to model-improver, and the chat input filled with “Fix the findings in out/assessment.md, highest severity first. Start with names and descriptions, and rebind the report after any rename.” The prompt isn’t sent yet, because the handoff has send: false. Don’t send it. You’ll use a narrower prompt in the next step.

This is the handoff definition in the assessor’s agent file:

.github/agents/model-assessor.agent.md (lines 1-11)
---
name: model-assessor
description: Reviews the Contoso Pharmacy semantic model against the team conventions and AI-readiness checklist, without changing it, and writes prioritized findings to out/assessment.md. Use before improving the model or to explain why AI answers are weak.
argument-hint: Optional focus, for example "names only" or "measures and time intelligence"
tools: ['read', 'search', 'execute', 'edit', 'todo', 'powerbi-modeling-mcp/*']
handoffs:
- label: Fix these findings
agent: model-improver
prompt: Fix the findings in out/assessment.md, highest severity first. Start with names and descriptions, and rebind the report after any rename.
send: false
---
  1. Clear the prefilled text in the chat input.
  2. Type /improve-names-and-descriptions and press Enter.
  3. When the agent asks whether Power BI Desktop has the project open, answer No, it’s closed.
  4. Approve each terminal command it wants to run (Continue or Allow) after you read it. It runs only the validation and convention scripts.

The prompt file limits the scope to names, descriptions, hidden keys, and summarization:

.github/prompts/improve-names-and-descriptions.prompt.md
---
name: improve-names-and-descriptions
description: Rename tables and columns to business names, add descriptions, hide keys, set summarization and display folders, then rebind the report.
agent: model-improver
---
Improve names and descriptions in the Contoso Pharmacy semantic model. Use the `pharmacy-model-conventions`, `tmdl-authoring`, and `pbir-rebinding` skills.
Scope for this change:
1. Rename every table and visible column to the business name in the conventions skill's data dictionary. Keep `sourceColumn` values unchanged. Update `model.tmdl`, `relationships.tmdl`, table file names, and any DAX.
2. Rebind every report visual to the new names, and replace implicit aggregations with measures if the measures already exist.
3. Add a `///` description to every table and visible column: what one row is, or what the value means, with an example value where it helps. Keep each under 200 characters.
4. Hide surrogate keys and sort helpers. Set `summarizeBy: none` on keys, codes, years, and other non-additive numbers.
Out of scope: new measures, relationship changes, and AI prep drafts.
After each group of edits run:
```powershell
pwsh ./scripts/Invoke-Validation.ps1 -Only tmdl,bindings
pwsh ./scripts/Test-ModelConventions.ps1 -Rule C01,C02,C03,C04,C05
```
Finish when the lint and bindings pass and C01 to C05 report no findings.

You should see:

  • A todo list in the chat, built from out/assessment.md.
  • The skills it loaded listed under the answer (expand Used n references).
  • Edits to fabric/ContosoPharmacy.SemanticModel/definition/tables/*.tmdl, with table files renamed to match: dim_date.tmdl becomes Date.tmdl, dim_store.tmdl becomes Store.tmdl, dim_med.tmdl becomes Medication.tmdl, and fact_rx_fill.tmdl becomes Prescription Fill.tmdl.
  • Edits to model.tmdl and relationships.tmdl for the new table names.
  • A lint result after each edit, reported by the post-edit hook.

The rename map comes from the conventions skill:

.github/skills/pharmacy-model-conventions/references/data-dictionary.md (lines 1-12)
# Data dictionary
Standard business names for every source column. Rename the model object to the business name and keep `sourceColumn` set to the source name.
## Tables
| Source table | Business name | Grain |
|---|---|---|
| `dim_date` | Date | One row per calendar day, 2024-01-01 to 2025-12-31 |
| `dim_store` | Store | One row per store (12 stores, 4 regions) |
| `dim_med` | Medication | One row per medication product |
| `fact_rx_fill` | Prescription Fill | One row per prescription fill, new or refill |

Step 4. Review descriptions, hidden keys, and summarization

Section titled “Step 4. Review descriptions, hidden keys, and summarization”

The same prompt continues with descriptions and column properties. When it finishes, review the diff before you accept it.

  1. Open Source Control: Ctrl+Shift+G, or View > Source Control.
  2. Click Store.tmdl to open the diff.
  3. Check these on at least one table:
    • Every table and visible column has a /// description line right above it, under 200 characters.
    • Store Key has isHidden and summarizeBy: none.
    • Numbers that aren’t additive, such as Year, have summarizeBy: none.
    • The lineageTag: line of each column is unchanged. The diff shows only the name line and new lines around it.
  4. Ask the agent about anything that looks wrong, for example “Why is Open Date not hidden?”. It should point to the conventions skill.

Then confirm with the convention check:

Terminal window
pwsh ./scripts/Test-ModelConventions.ps1 -Rule C01,C02,C03,C04,C05

You should see: 0 finding(s).

The hook already ran the lint after each edit. Run it once yourself to see the whole model at once:

Terminal window
pwsh ./scripts/Invoke-Validation.ps1 -Only tmdl

You should see: PASS tmdl. If there are errors, each line names the file, line number, and a rule code such as TMDL003. Paste the output into the chat and ask the improver to fix it.

Report visuals refer to model objects by name. Renaming dim_store to Store in TMDL leaves every visual pointing at a table that no longer exists. The prompt asks the agent to rebind, but check it yourself:

Terminal window
pwsh ./scripts/Test-ReportBindings.ps1

You should see: PASS every report field exists in the model.

If it fails instead, it lists each visual.json file and the missing field, for example Entity 'fact_rx_fill' not found. Ask the improver: “Fix the report bindings listed by Test-ReportBindings.ps1.” It loads the pbir-rebinding skill, which explains the three parts of a field reference that must agree:

.github/skills/pbir-rebinding/SKILL.md (lines 17-40)
```powershell
pwsh ./scripts/Test-ReportBindings.ps1
pwsh ./scripts/Test-ReportBindings.ps1 -Json # machine-readable
```
Each problem names the file and the missing table, column, or measure. Zero problems means the report binds.
## Step 2. Fix each field reference
A field reference has three parts that must agree. Here's a column before and after renaming `dim_date.yr_mth` to `Date[Year Month]`:
```json
{
"field": {
"Column": {
"Expression": { "SourceRef": { "Entity": "Date" } },
"Property": "Year Month"
}
},
"queryRef": "Date.Year Month",
"nativeQueryRef": "Year Month"
}
```
Windows only
  1. Open fabric\ContosoPharmacy.pbip in Power BI Desktop.
  2. Click Refresh on the Home ribbon.
  3. Open the report page and check that every visual renders.
  4. In the Data pane, hover over a column. The tooltip shows its new description.

You should see: tables named Date, Store, Medication, and Prescription Fill, and no visual with a red “Something’s wrong with one or more fields” message.

Close Desktop when you’re done, without saving, so it doesn’t rewrite the files before you commit.

Terminal window
git add fabric
git commit -m "Rename model objects and add descriptions"

You should see: a commit with the renamed table files and the report visual.json changes. git status then shows a clean tree, apart from out/, which is ignored.

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 07

When everything is done you should see:

Expected output
PASS L07-names Tables and visible columns use business names (rule C01)
PASS L07-descriptions Every table and visible column has a description under 200 characters (C02, C03)
PASS L07-hidden-and-summarize Keys are hidden and only additive columns summarize (C04, C05)
PASS L07-lint TMDL lint passes
PASS L07-bindings Every report visual binds to a field that exists
Lab 07: 5 of 5 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
L07-namesTables and visible columns use business names (rule C01)Ask model-improver to finish the renames listed by pwsh ./scripts/Test-ModelConventions.ps1 -Rule C01. Go to step 3
L07-descriptionsEvery table and visible column has a description under 200 characters (C02, C03)Run /improve-names-and-descriptions again for the objects listed. Go to step 4
L07-hidden-and-summarizeKeys are hidden and only additive columns summarize (C04, C05)Set isHidden on keys and summarizeBy: none on IDs, years, and numbers. Go to step 4
L07-lintTMDL lint passesRun pwsh ./scripts/Invoke-Validation.ps1 -Only tmdl and fix the listed lines. Go to step 5
L07-bindingsEvery report visual binds to a field that existsRun pwsh ./scripts/Test-ReportBindings.ps1 and use the pbir-rebinding skill. Go to step 6
My edits disappeared, or the files changed back

Power BI Desktop had the project open while the agent edited the files, and it wrote its in-memory copy back when you saved or closed it. Close Desktop, run git restore fabric to go back to your last commit, and run /improve-names-and-descriptions again with Desktop closed.

The agent renamed more than it should, or started adding measures

Reject the extra changes in the diff (right-click the file in Source Control, then Discard Changes), and remind it of the scope: “Only names, descriptions, hidden keys, and summarization. No measures.” The prompt file lists the scope, but agents sometimes read the whole assessment and try to do everything.

Visuals are blank or show “Something’s wrong with one or more fields”

A visual still refers to an old name. Run pwsh ./scripts/Test-ReportBindings.ps1, then ask the improver to fix the files it lists. Reopen the project in Desktop afterward. Desktop doesn’t reload PBIR files while it’s open.

The handoff button isn’t there

It appears only under the latest answer from the model-assessor, and only in VS Code. Pick model-improver from the agent dropdown instead. The handoff only saves you from typing the prompt.

The lint reports TMDL001 or mixed indentation

TMDL uses tabs. If you edited a file by hand, VS Code may have inserted spaces. The repo’s .vscode/settings.json sets tabs for .tmdl files. Open the command palette (Ctrl+Shift+P), run Convert Indentation to Tabs, and save.

You rename the column rgn to Region in TMDL. What else has to change?

Show the answer

Every report visual, measure, and relationship that refers to the old name.

Report visuals and DAX refer to model objects by name. The lineageTag keeps identity in the service, but the PBIR files still say rgn until you rebind them. sourceColumn must stay rgn, because that's the column in the CSV.

Why close Power BI Desktop before an agent edits the TMDL files?

Show the answer

Desktop keeps the model in memory and can write it back over the files, undoing the edits.

Desktop doesn't watch the files for outside changes. When you save or close it, it serializes its own copy of the model. Either edit through MCP while Desktop is open, or close Desktop and edit the files.

What does the handoff button do?

Show the answer

It switches the chat to model-improver and pre-fills a prompt, which you can edit before sending.

With send: false, the handoff switches agents and fills in the prompt, but waits for you. That gives you a chance to narrow the scope, as you did in step 3.

You used a handoff to move from a read-only assessment to an agent that edits, scoped the work with a prompt file, reviewed an agent’s TMDL diff, and fixed the report bindings that every rename breaks. The model now has business names, descriptions, hidden keys, and correct summarization, but it still has a missing relationship and no measures.

Next: Lab 08: Relationships, date table, and measures

  • Open Prescription Fill.tmdl and read the descriptions the agent wrote for Processing Minutes and Fill Type Code. Would a new analyst understand them? Rewrite one, run pwsh ./scripts/Test-ModelConventions.ps1 -Rule C02,C03, and commit.
  • Ask the model-reviewer agent: “Review the rename commit for anything that would break a Power BI report in the service.” Compare its answer with what you checked in step 4.