cd /news/developer-tools/example-how-to-query-resource-agents… · home topics developer-tools article
[ARTICLE · art-110773] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Example how to query resource (agents and workflows) Copilot credit consumption for a given time period. Allows for reporting at the user level or total the values per resource.

A developer shared a PowerShell script that queries Copilot credit consumption for Power Platform resources such as agents and workflows over a specified time period. The script uses Azure authentication and the Power Platform API to retrieve resource data, enabling user-level or per-resource reporting.

read9 min views17 publishedAug 24, 2026

| #requries -modules "Az.Accounts" | | | function Get-AccessToken | | | { | | | [CmdletBinding()] | | | param | | | ( | |

| [Parameter(Mandatory=$true)] | |
| [string] | |

| $ResourceUrl | | | ) | | | if (-not (Get-AzContext)) | | | { | | | Write-Host "No Azure context - launching sign-in..." -ForegroundColor Yellow | | | Connect-AzAccount -WarningAction SilentlyContinue | Out-Null | | | } | |

| $azAccessToken = Get-AzAccessToken -ResourceUrl $ResourceUrl -WarningAction SilentlyContinue | |
| if ($azAccessToken.Token -is [System.Security.SecureString]) | |

| { | | | return [System.Net.NetworkCredential]::new('', $azAccessToken.Token).Password | | | } | | | return $azAccessToken.Token | | | } | | | function Get-PowerPlatformResource | | | { | | | [CmdletBinding()] | | | param | | | ( | |

| [Parameter(Mandatory=$false)] | |
| [switch] | |

| $IncludeAgentResources, | |

| [Parameter(Mandatory=$false)] | |
| [switch] | |

| $IncludeWorkflowResources | | | ) | | | begin | | | { | |

| $accessToken = Get-AccessToken -ResourceUrl "https://api.powerplatform.com/" | |
| $headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json"; "Accept" = "application/json" } | |
| $skipToken = "" | |
| $skip = 0 | |
| $top = 1000 | |
| $resourceQueryTemplate = @' | |
| {{ | |
| "Options": {{ | |
| "Top": {0}, | |
| "Skip": {1}, | |
| "SkipToken": "{2}" | |
| }}, | |

| "TableName": "PowerPlatformResources", | |

| "Clauses": [ | |
| {{ | |

| "$type": "where", | | | "FieldName": "type", | | | "Operator": "in~", | |

| "Values": [ {3} ] | |
| }}, | |
| {{ | |

| "$type": "extend", | | | "FieldName": "joinKey", | |

| "Expression": "tolower(tostring(properties.environmentId))" | |
| }}, | |
| {{ | |

| "$type": "project", | | | "FieldList": [ | | | "joinKey", | | | "resourceId = tolower(name)", | | | "type", | | | "resourceName = properties.displayName", | | | "resourceType = iif( type == 'microsoft.powerautomate/agentflows', 'Agent Workflow', iif( properties.isGithubCopilotAgent == 1, 'GitHub Copilot Harness Agent',iif(properties.model == 'Microsoft 365 Copilot','M365 Copilot Chat Harness Agent','Standard Harness Agent')))", | | | "properties" | | | ] | |

| }}, | |
| {{ | |

| "$type": "join", | | | "JoinKind": "leftouter", | | | "RightTable": {{ | | | "TableName": "PowerPlatformResources", | |

| "Clauses": [ | |
| {{ | |

| "$type": "where", | | | "FieldName": "type", | |

| "Operator": "==", | |
| "Values": [ | |

| "'microsoft.powerplatform/environments'" | | | ] | |

| }}, | |
| {{ | |

| "$type": "project", | |

| "FieldList": [ | |
| "joinKey = tolower(name)", | |
| "environmentId = tolower(name)", | |

| "environmentName = properties.displayName", | | | "environmentRegion = location", | | | "environmentType = properties.environmentType", | | | "isManagedEnvironment = properties.isManaged", | | | "environmentGroupId = tolower(properties.environmentGroupId)" | | | ] | | | }} | | | ] | | | }}, | | | "LeftColumnName": "joinKey", | | | "RightColumnName": "joinKey" | |

| }}, | |
| {{ | |

| "$type": "join", | | | "JoinKind": "leftouter", | | | "RightTable": {{ | | | "TableName": "PowerPlatformResources", | |

| "Clauses": [ | |
| {{ | |

| "$type": "where", | | | "FieldName": "type", | |

| "Operator": "==", | |
| "Values": [ | |

| "'microsoft.powerplatform/environmentgroups'" | | | ] | |

| }}, | |
| {{ | |

| "$type": "project", | |

| "FieldList": [ | |
| "environmentGroupId = tolower(name)", | |

| "environmentGroupName = properties.displayName" | | | ] | | | }} | | | ] | | | }}, | | | "LeftColumnName": "environmentGroupId", | | | "RightColumnName": "environmentGroupId" | | | }} | | | ] | | | }} | | | '@ | | | } | | | process | | | { | |

| $uri = "https://api.powerplatform.com/resourcequery/resources/query?api-version=2022-03-01-preview" | |
| $resourceTypes = @() | |

| if( $IncludeAgentResources.IsPresent ) | | | { | | | $resourceTypes += ""'microsoft.copilotstudio/agents'"" | | | } | | | if( $IncludeWorkflowResources.IsPresent ) | | | { | | | $resourceTypes += ""'microsoft.powerautomate/agentflows'"" | | | } | |

| $page = 0 | |
| $resources = do | |

| { | | | $page++ | |

| Write-Verbose "[$(Get-Date)] - Querying Power Platform resources, page $page." | |
| $body = $resourceQueryTemplate -f $top, $skip, $skipToken, ($resourceTypes -join ",") | |
| $response = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Headers $headers -Verbose:$false | |
| $skipToken = $response.skipToken | |

| $skip += $top | | | $response.data | | | } | |

| while( $skipToken ) | |
| $resources = foreach( $resource in $resources ) | |

| { | | | [PSCustomObject] @{ | | | ResourceType = $resource.resourceType | | | ResourceName = $resource.resourceName | | | ResourceId = $resource.resourceId | | | EnvironmentId = $resource.environmentId | | | EnvironmentName = $resource.environmentName | | | EnvironmentRegion = $resource.environmentRegion | | | EnvironmentType = $resource.environmentType | | | EnvironmentIsManaged = $resource.isManagedEnvironment | | | EnvironmentGroupId = $resource.environmentGroupId | | | EnvironmentGroupName = $resource.environmentGroupName | | | ResourceCreatedAt = $resource.properties.createdAt | | | ResourceCreatedBy = $resource.properties.createdBy | | | ResourceOwnerId = $resource.properties.ownerId | | | ResourceLastPublishedAt = $resource.properties.lastPublishedAt | | | } | | | } | | | if( $IncludeAgentResources.IsPresent ) | | | { | |

| $rows = @($resources | where-object -Property ResourceType -eq "Agent Workflow") | |
| Write-Verbose "[$(Get-Date)] - Discovered $($rows.Count) Power Platform Agent resources." | |

| } | | | if( $IncludeWorkflowResources.IsPresent ) | | | { | |

| $rows = @($resources | where-object -Property ResourceType -ne "Agent Workflow") | |
| Write-Verbose "[$(Get-Date)] - Discovered $($rows.Count) Power Platform Workflow resources." | |

| } | | | $resources | | | } | | | end | | | { | | | } | | | } | | | function Get-PowerPlatformResourceMessageConsumption | | | { | | | [CmdletBinding()] | | | param | | | ( | |

| [Parameter(Mandatory=$true)] | |
| [Guid] | |

| $ResourceId, | |

| [Parameter(Mandatory=$true,ParameterSetName="PerUserCreditConsumption")] | |
| [switch] | |

| $PerUserCreditConsumption, | |

| [Parameter(Mandatory=$true,ParameterSetName="TotalCreditConsumption")] | |
| [switch] | |

| $TotalCreditConsumption, | |

| [Parameter(Mandatory=$true)] | |
| [DateTime] | |

| $StartDate, | |

| [Parameter(Mandatory=$true)] | |
| [DateTime] | |

| $EndDate | | | ) | | | begin | | | { | |

| $accessToken = Get-AccessToken -ResourceUrl "https://api.powerplatform.com/" | |
| $headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json"; "Accept" = "application/json" } | |
| $uri = 'https://api.powerplatform.com/licensing/entitlements/MCSMessages/resources/{0}/users?fromDate={1}&toDate={2}&api-version=2024-10-01' -f $ResourceId, $StartDate.ToString("MM-dd-yyyy"), $EndDate.ToString("MM-dd-yyyy") | |

| } | | | process | | | { | |

| Write-Verbose "[$(Get-Date)] - Querying resource '$ResourceId' for usage." | |
| $response = Invoke-RestMethod -Method GET ` | |

| -Uri $uri | | | -Headers $headers | | | -ErrorAction Stop ` | | | -Verbose:$false | | | if( $TotalCreditConsumption.IsPresent ) | | | { | |

| Write-Verbose "[$(Get-Date)] - Calculating total usage across $($response.value.users.Count) users." | |
| $totalBillableCreditsUsed = $totalCreditsUsed = $totalUserCount = $consumedUserCount = $billableConsumedUserCount = 0 | |

| foreach( $user in $response.value.users ) | | | { | | | $totalUserCount++ | | | $totalBillableCreditsUsed += $user.consumed | | | $totalCreditsUsed += $user.metadata.NonBillableQuantity | | | if( $user.consumed -gt 0 ) | | | { | | | $billableConsumedUserCount++ | | | } | | | if( $user.metadata.NonBillableQuantity -gt 0 ) | | | { | | | $consumedUserCount++ | | | } | | | } | | | [PSCustomObject] @{ | | | BillableCreditsUsed = $totalBillableCreditsUsed | | | CreditsUsed = $totalCreditsUsed | | | BillableCreditUserCount = $billableConsumedUserCount | | | CreditUserCount = $consumedUserCount | | | TotalUserConsumptionCount = $totalUserCount | | | } | | | } | | | else | | | { | |

| Write-Verbose "[$(Get-Date)] - Calculating user level usage." | |
| if( $response.value.users ) | |

| { | | | foreach( $user in $response.value.users ) | | | { | | | [PSCustomObject] @{ | | | UserId = $user.userId | | | BillableCreditsUsed = $user.consumed | | | CreditsUsed = $user.metadata.NonBillableQuantity | | | CreditUsageAsOfDate = $user.asOfDate | | | } | | | } | | | } | | | } | | | } | | | end | | | { | | | } | | | } | | | # lookback last 30 days | |

| $startDate = [DateTime]::Today.AddDays(-31) | |
| $endDate = [DateTime]::Today.AddDays(-1) | |

| # show total or per user per resource credit consumption | | | $reportPerUserCreditConsumption = $false | | | # get all copilot studio agents and agent workflows | | | $resources = Get-PowerPlatformResource -IncludeAgentResources -IncludeWorkflowResources -Verbose | | | # example filters if you want to narrow the scope | |

| # $resources = $resources | Where-Object -Property ResourceType -eq "Agent Workflow" | |
| # $resources = $resources | Where-Object -Property ResourceType -eq "GitHub Copilot Harness Agent" | |
| # $resources = $resources | Where-Object -Property ResourceType -eq "Standard Harness Agent" | |

| # pull agent usage | | | $results = foreach( $resource in $resources ) | | | { | | | if( $reportPerUserCreditConsumption ) | | | { | |

| $messages = Get-PowerPlatformResourceMessageConsumption -ResourceId $resource.ResourceId -StartDate $startDate -EndDate $endDate -PerUserCreditConsumption -Verbose | |
| foreach( $message in $messages ) | |

| { | | | $row = $resource.psobject.Copy() | | | $row | Add-Member -MemberType NoteProperty -Name "UserId" -Value $message.UserId | | | $row | Add-Member -MemberType NoteProperty -Name "BillableCreditsConsumed" -Value $message.BillableCreditsUsed | | | $row | Add-Member -MemberType NoteProperty -Name "CreditsConsumed" -Value $message.CreditsUsed | | | $row | Add-Member -MemberType NoteProperty -Name "CreditUsageAsOfDate" -Value $message.CreditUsageAsOfDate | | | $row | | | } | | | } | | | else | | | { | | | $messages = Get-PowerPlatformResourceMessageConsumption -ResourceId $resource.ResourceId -StartDate $startDate -EndDate $endDate -TotalCreditConsumption -Verbose | | | $resource | Add-Member -MemberType NoteProperty -Name "BillableCreditsConsumed" -Value $messages.BillableCreditsUsed | | | $resource | Add-Member -MemberType NoteProperty -Name "CreditsConsumed" -Value $messages.CreditsUsed | | | $resource | Add-Member -MemberType NoteProperty -Name "BillableCreditUserCount" -Value $messages.BillableCreditUserCount | | | $resource | Add-Member -MemberType NoteProperty -Name "CreditUserCount" -Value $messages.CreditUserCount | | | $resource | Add-Member -MemberType NoteProperty -Name "TotalUserConsumptionCount" -Value $messages.TotalUserConsumptionCount | | | $resource | | | } | | | } | | | $timestamp = Get-Date -Format FileDateTime | | | $results | Export-Csv -Path "C:_temp\PowerPlatformResourceMessageConsumption_$timestamp.csv" -NoTypeInformation |

── more in #developer-tools 4 stories · sorted by recency
── more on @power platform 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/example-how-to-query…] indexed:0 read:9min 2026-08-24 ·