Tool-belt series · Playbook · Copilot & Claude × Power BI
A working plan for optimizing a Power BI semantic model and rebuilding its reports with agentic AI — without breaking things. Start from a defensible baseline, let VertiPaq Analyzer point at the weight, delete only what is provably dead, then turn a lean model into reports Treasury actually opens. Check items off as you go; every section, part, and the top bar tracks progress, and collapsed sections stay collapsed the next time you open this file.
This is a review-and-do playbook, built to be read the way you work: top to bottom. Part A pressure-tests your plan and locks in the safety setup, Part B is the VertiPaq-driven model cleanup, Part C modernizes the reports, and Part D turns it into Treasury value and a way to out-deliver the outside vendor. Check items off as you complete them — sections, parts, and the top bar all track progress.
The prompts assume you have the PBIP folder open in VS Code with GitHub Copilot in agent mode (or Claude), referencing files with #file / #folder and the whole project with @workspace. Progress and collapsed-section state save automatically in this browser on this device; they reset if you clear browser data or open the file elsewhere.
When a new situation comes up that this page doesn't cover, bring it back to Claude and ask for another section — it's built to be extended like the rest of the tool belt.
Yes — feeding the VPAX into Copilot and letting it point at bloated tables and measures is exactly the right raw material. The VertiPaq Analyzer view tells you where the bytes and cardinality actually live, which is far better than guessing. The one risk in your plan is sequencing: “identify and delete tables not used at all” is the last step, not an early one. VPAX shows you what is expensive; it does not prove what is unused. A table can be tiny and still feed a critical measure, an RLS rule, or a downstream report. Prove it is orphaned and check what consumes it before it goes.
Reframe the effort into phases
The whole reason PBIP exists is that it saves the model as plain-text TMDL and the report as PBIR — both diffable, both Git-friendly. That is your safety net. The agent edits text files; Git records every change; you review before anything is committed or opened in Desktop. Never let the agent operate against the published/live dataset in the Service — work only against the local PBIP folder on a branch.
.tmdl file. If a “small” change rewrites half the model, that is the model warning you.You cannot claim an improvement you never measured. Before the first edit, capture the current state and write down where you intend to land. This does double duty: it protects you (regressions are obvious) and it is your scoreboard against the external vendor — when Treasury asks who delivered more, you have hard numbers, not a story.
Capture & record
The agent is fast and confident — which is exactly why you gate it. Make it justify a change before it makes it, and never accept a bulk delete on faith. For anything destructive, stage it: hide the object first, watch it survive a refresh and a report render, then delete. Keep a decision log so every removal has a reason attached — future-you (and the audit) will need it.
Prompt to try
@workspace Using #file:model.vpax and the TMDL in #folder:Model,
list every table & column that is NOT referenced by any measure,
relationship, RLS role, calc group, or report visual.
For each candidate: show what DOES reference it (or state "none"),
its size & cardinality, and a risk rating.
Do NOT edit anything yet — output the analysis as a table.
Verification loop
The agent can only triage what it can see. Give it the measured cost (the exported .vpax), the full model definition (the TMDL), and the constraints it must respect (star schema, what has already changed). Precise file references keep it grounded instead of guessing.
Context to load
Prompt to try
@workspace You are helping me clean up a Power BI semantic model (PBIP/TMDL) for
our Treasury group. Attached is the VertiPaq Analyzer export #file:model.vpax and
the model definition in #folder:Model.SemanticModel/definition.
It is a star schema — fact tables plus conformed dimensions; preserve the grain.
Hidden report pages have already been deleted.
Triage, do not change anything yet. Produce a ranked table of the heaviest columns
and tables by Total Size and % of model, note Cardinality for each, and flag
obvious optimization or deletion candidates. Ask me before assuming anything is unused.
.vpax and the TMDL together in the first message — the agent triages far better with measured size next to the definition than with either alone.Two separate questions: what costs the most (VertiPaq), and what is actually referenced (dependency analysis + the report layer). A deletion candidate must be expensive-or-irrelevant and unreferenced everywhere. DAX dependencies alone are not enough.
Surface the cost, then prove non-use
Prompt to try
Using #file:model.vpax and #folder:definition, list every column with Total Size
> 1% of the model. For each, tell me whether it is referenced by: any measure or
calculated column (via dependencies), a relationship, an RLS role expression, a
field parameter, a sort-by-column, or the incremental refresh policy. Then scan
#folder:Report/definition for any visual, slicer, tooltip or filter binding.
Return three buckets: confirmed-unreferenced-everywhere, referenced, and uncertain.
Do not call anything unused unless it is clear in all of those places.
Deletion is destructive and version control is your safety net. Move in stages, one table at a time, so every removal is an isolated, reversible commit with a readable diff.
Staged removal
VertiPaq compresses column by column, and compression works by building a dictionary of distinct values. So size is driven by cardinality (number of distinct values), not the number of rows. A 50M-row table with a low-cardinality column stays tiny; a few million rows of unique GUIDs or full-precision timestamps dominate the model. Attack the highest-cardinality columns first.
Cut cardinality
Prompt to try
From #file:model.vpax, list the 10 highest-cardinality columns with their Total
Size and data type. For each, recommend a cardinality reduction (datetime split,
precision/rounding, integer key, move-to-dimension, or drop) and note which
requires a Power Query / source change vs. a model change. Rank by expected
size saving, and flag any that participate in a relationship before proposing a drop.
Measures change results, so correctness comes before speed. Find the expensive ones with real timings, have the agent explain what a measure is supposed to do before touching it, then rewrite and confirm the numbers match.
Rewrite with proof
Prompt to try
Look at the measure [Treasury Net Position] in #folder:definition. First, explain
in plain English what it computes and its filter context — do not rewrite yet.
Then propose an optimized version: remove any FILTER over the full fact table, use
variables, and drop unnecessary iterators. Keep semantics identical. Show old vs new
side by side, list the filter contexts I should test, and give me a DAX query that
returns both versions so I can confirm they match before I replace anything.
The cleanup is only real if you can quantify it. Re-run the same instruments you started with and record the deltas — that decision log is your evidence for stakeholders and your scorecard against the outside vendor.
Close the loop
You can't modernize what you haven't measured. Hidden pages were already removed — good. Now take stock of what remains: every page, every visual, and every place the reports contradict themselves. PBIR stores each page, visual, and bookmark as its own JSON file, so the agent can read the whole report and hand you a structured inventory in minutes.
Baseline the reports
Prompt to try
Read every visual.json under #folder /definition/pages in this .Report.
Build a Markdown inventory table with one row per visual:
page name, visual name/title, visual type, fields/measures used,
and whether the title is meaningful or a default placeholder.
Add a second table listing bookmarks and, for each, whether any
button or visual action references it. Flag likely duplicates
(same measure, same or similar visual type on the same page).
Do not edit anything — read and report only.
Modern doesn't mean flashy — it means disciplined. A single theme JSON sets colors, fonts, and default formatting once, so every visual inherits consistency instead of being styled by hand. Aim for restrained color (a neutral base plus one or two accents), clear visual hierarchy, generous spacing, and fewer visuals per page. Drive the changes through the agent, keep them small, and review every diff.
Set the design foundation
Prompt to try
Here is our Treasury theme JSON (attached). Update it to a modern,
restrained scheme: neutral canvas, one primary accent (#hex),
one emphasis accent, and semantic red/green reserved for variance.
Set default fonts, title sizes, and card/label formatting.
Add dataColors, and set default formatString for currency
("\$#,0;(\$#,0)") and percentage where applicable.
Return the full valid theme JSON only — do not modify any
visual.json yet. I'll load it in Desktop and confirm before we
apply it across pages.
This is where the agent shines — and where it can bite. Each visual is a JSON file with a public schema, so the agent can add or reshape visuals directly. But PBIR is newer and less forgiving than the model layer: a malformed visual.json can make Desktop drop the visual or refuse to open the report. Move one visual at a time, validate in Power BI Desktop after every edit, and commit only what opens cleanly.
Iterate safely on visuals
Prompt to try
On the Liquidity page, replace the crowded per-currency line chart
with a small-multiples line chart: one small chart per currency,
measure = [Closing Cash], axis = Date, sorted by currency.
Create/modify only that one visual.json, follow the PBIR visual
schema exactly, keep the existing visual's position/size, and
inherit the theme (no hard-coded colors). Show me the JSON diff
and stop — I'll validate in Desktop before you touch anything else.
A modern report is fast and easy to move through. Fewer visuals per page cuts query load and cognitive load at once. Use bookmarks and navigation for clean page flow, tooltips and drill-through for detail on demand, and field parameters to let users shape their own view. Finish with a mobile layout, then re-run Performance Analyzer to prove the redesign is actually faster.
Tighten performance and flow
Treasury does not want dashboards — it wants answers to a short list of recurring questions about cash, liquidity, and risk. Frame every report around the question, not the visual, and your work will land with the people who fund it.
Anchor each report to a real Treasury question
Concrete builds, each mapped to a core visual type and the decision it unlocks. Pick one, ship it end-to-end, then expand — a working artifact beats a backlog of ideas.
Candidate reports — visual × decision
Prompt to try
Act as a senior Power BI developer for a corporate treasury team.
Draft a DAX measure for a 13-week rolling cash forecast that returns
forecast-vs-actual variance by week. Assumptions:
- Fact table 'CashFlow'[Amount], [Date], [Scenario] = "Actual" | "Forecast"
- A marked Date table 'Calendar'[Date]
Return: (1) the measure, (2) a short comment on each step,
(3) how to guard against blanks in weeks with no actuals yet.
Do NOT give financial advice — reporting logic only.
The vendor may bring polish and scale — be candid about that. But you own advantages a vendor structurally cannot match. Do not try to boil the ocean; build one polished dashboard on real data that is undeniable, and let it argue for you.
Differentiators you own — lean into them
Stakeholders fund momentum they can see. Package your model cleanup and new reports as a scoreboard, a rhythm, and a simple roadmap — framed in business outcomes, not technical effort.
Make the work legible to decision-makers
Prompt to try
You are my analytics-engineering mentor. Draft a one-page
stakeholder update for a corporate Treasury audience.
Inputs I'll paste: before/after model metrics, reports shipped
this sprint, and next-sprint plan.
Rules:
- Lead with business outcomes, not technical detail.
- Include a small before & after scoreboard table.
- End with a 3-item now/next/later roadmap.
- Tone: confident, concise, no jargon, no financial advice.