Repository navigation
Agent Costs Import Configuration
Agent Costs → Agent Costs Import Configuration
-
Decide which scopes to read. A scope is a full resource path, most commonly a subscription:
/subscriptions/00000000-0000-0000-0000-000000000000Billing-account, management-group, department and enrollment-account scopes are also supported. -
Grant the runtime service principal
Cost Management Readeron each scope. For subscriptions and management groups this is a normal Azure RBAC assignment (Access control (IAM) → Add role assignment). For EA and MCA billing-account scopes the equivalent role is granted in the billing portal, not through Azure RBAC. -
For an EA enrollment, also make sure the "AO view charges" policy is enabled, or the subscription-scoped queries return nothing. For a Microsoft Customer Agreement, a Billing profile owner must allow Azure charges to be visible to subscription-scope users, or the same happens.
-
Set
AzureCostScopes(below) and restart the web-job.
If the service principal is not authorised you will see the import log entry name the Cost Management Reader role explicitly.
Tick these in the installer, on the Targets page (each has a needs setup link beside it):
- Copilot Studio credits
- Azure costs
Both are off by default, and neither does anything until the matching permission above is in place.
Set these on the App Service (Configuration → Application settings). None are required except AzureCostScopes, which the Azure import will not run without.
| Setting | Default | What it does |
|---|---|---|
CopilotStudioCreditsIntervalHours |
24 |
Minimum hours between Copilot Studio credit imports. 0 runs every cycle. |
CopilotStudioCreditsTrailingWindowDays |
7 |
How many days back to re-read each run, so restated usage days are corrected. Capped at 180 — the import makes at least one request per day in the window. |
AzureCostScopes |
(none) | Required for the Azure import. Semicolon-separated Cost Management scopes. |
AzureCostMeterFilterValues |
(none) | Semicolon-separated values to filter to. For Copilot spend use Microsoft Copilot Studio (see below). Empty means import every meter at the scope.
|
AzureCostMeterFilterDimension |
ServiceName |
Which dimension the filter matches. MeterCategory and Meter are the other sensible choices. |
AzureCostGroupBy |
ResourceId;Meter |
Which two dimensions to group by. Cost Management allows a maximum of two — more are ignored. An entry TagKey:<tag name> groups by a tag instead of a dimension, for example ResourceId;TagKey:serviceName — see Microsoft Cowork. |
AzureCostTrailingWindowDays |
5 |
Minimum days back to re-read. The import automatically reaches further when an older billing period is still open. Raise it (for example to 60) for a first run that should cover more than the current month. |
AzureCostIntervalHours |
24 |
Minimum hours between Azure cost imports. Set it to 1 while testing a new filter or grouping, then set it back. 0 re-runs even a successful import on every cycle, spending the same Cost Management quota each time — avoid leaving it there. (A throttled run is retried on the next cycle at any interval; see HTTP 429.) |
For Copilot spend, filter on Microsoft Copilot Studio. Microsoft bills Copilot pay-as-you-go consumption to Azure under that service name. The public Azure Retail Prices API lists its meter Pay As You Go Copilot Credit (effective 1 September 2025) alongside the older Pay As You Go Message, which is still listed; filtering on the service rather than the meter catches both. With the default ServiceName dimension:
AzureCostMeterFilterValues = Microsoft Copilot Studio
To find anything else, you can leave AzureCostMeterFilterValues empty for one run. The import then brings back every meter at the scope, including your ordinary infrastructure spend. Look at the Azure breakdown on the Agent costs page, identify the service or meter you care about, then set the filter and let the next run replace the data.
⚠️ Avoid an unfiltered run on a large subscription or management group. It is one row per resource, meter and day. Up to and including build 1838, storing a large result gets quadratically slower (measured: 20,000 rows took 167 seconds; 100,000 rows would take roughly an hour), and it runs inside the importer's cycle. A very large result can also exceed the import's 200-page safety limit, in which case nothing is stored and the import retries on the next cycle. Stable 1852 stores rows in linear time, but filtering first is still the better habit.
The import replaces each scope's refresh window on every run, so narrowing the filter removes the rows in that window that no longer match. The window always covers the current billing month (and the previous one until the 8th), so a change made early in the month rewrites the whole month. Rows older than the window keep the filter they were imported with.
Cost Management permits only two group-by clauses per query. Whichever dimensions you do not group by are simply not returned, and the portal will not offer them as a breakdown option.
The default ResourceId;Meter is chosen because a resource ID contains the subscription and resource group, so two groupings still yield four usable dimensions. Choosing ServiceName;Meter instead gives you service-level reporting but loses per-resource detail. The page only offers a breakdown for a dimension that some stored row has a value for — so the Service breakdown needs ServiceName as one of the two groupings (filtering on it is not enough), and the Tag value breakdown appears only once at least one row carries a tag value.
TagKey:<tag name> uses one of the two slots to group by a tag. The query API returns tags only when grouped by them. The result is stored in tag_key / tag_value, and the Agent costs page offers a Tag value breakdown. The trade-off is real: with ResourceId;TagKey:serviceName the meter is not returned, so meter_name is empty for those rows — and the page's summary shows no credit quantity once more than one tag value has spend, because it only totals a quantity when a single meter/tag combination contributes.
Changing the grouping mid-month is safe for the refresh window, but rows older than it keep the grouping they were imported with. A breakdown across the change will show a "Not reported" bucket on whichever dimension the older or newer rows lack.
Return to Agent Costs · All topics in this guide
Previous: Agent Costs Billing Connection · Next: Agent Costs Verification and Troubleshooting
- Copilot analytics overview
- Copilot Adoption user guide
- Copilot Adoption setup (admins)
- Work Trend Index
- Copilot investment
- Copilot spend
- Agent costs
- Prompt categories
- Copilot credit history (preview)
- Agent 365 package catalog
- The Copilot data in depth
- Prerequisites
- App registrations setup
- Install with the installer
- Verify the deployment
- Security & permissions model
- Private endpoints (optional)
- Certificate authentication (optional)
- Manual installation
- Activity & usage analytics (Power BI)
- SharePoint page tracking