Created
August 5, 2026 18:47
-
-
Save joerodgers/224ee9739afdf083400a6825044fbe38 to your computer and use it in GitHub Desktop.
Reports number of prompts sent to an MCS agent by an Entra user, per day. This requires the user running the script to have read permissions to the conversationtranscript table in all environments being scanned.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #requires -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-AgentUserPromptMetadata | |
| { | |
| [CmdletBinding()] | |
| param | |
| ( | |
| [Parameter(Mandatory=$true)] | |
| [string] | |
| $OrganizationUrl | |
| ) | |
| begin | |
| { | |
| $token = Get-AccessToken -ResourceUrl $OrganizationUrl | |
| $headers = @{ Authorization = "Bearer $token"; "accept" = "application/json" } | |
| $uri = '{0}/api/data/v9.2/conversationtranscripts?$select=content,_bot_conversationtranscriptid_value' -f $OrganizationUrl | |
| } | |
| process | |
| { | |
| try | |
| { | |
| do | |
| { | |
| $response = Invoke-RestMethod -Method Get -Uri $uri -Headers $headers -ErrorAction Stop | |
| $uri = $response."@odata.nextLink" | |
| foreach( $row in $response.value ) | |
| { | |
| $content = $row.content | ConvertFrom-Json -ErrorAction Stop | |
| foreach( $activity in $content.activities | Where-Object -Property type -eq "message" ) | |
| { | |
| if( $activity.from.aadObjectId ) | |
| { | |
| # epoch time > timestamp | |
| $timestamp = (Get-Date -Date "01-01-1970") + ([System.TimeSpan]::FromSeconds($activity.timestamp)) | |
| [PSCustomObject]@{ | |
| BotId = $row."_bot_conversationtranscriptid_value" | |
| EntraObjectId = $activity.from.aadObjectId | |
| Timestamp = $timestamp | |
| OrganizationUrl = $OrganizationUrl | |
| } | |
| } | |
| } | |
| } | |
| } | |
| while( $uri ) | |
| } | |
| catch | |
| { | |
| Write-Error "Error processing env: $($OrganizationUrl). Error: $($_)" | |
| } | |
| } | |
| end | |
| { | |
| } | |
| } | |
| function Get-PowerPlatformEnvironment | |
| { | |
| [CmdletBinding()] | |
| param | |
| ( | |
| ) | |
| begin | |
| { | |
| $accessToken = Get-AccessToken -ResourceUrl "https://api.bap.microsoft.com" -ErrorAction Stop | |
| $headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json"; "Accept" = "application/json" } | |
| } | |
| process | |
| { | |
| $uri = 'https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments?api-version=2020-06-01&$expand=properties.addons,properties.capacity,properties.permissions&$top=999' | |
| do | |
| { | |
| $response = Invoke-RestMethod -Method GET ` | |
| -Uri $uri ` | |
| -Headers $headers ` | |
| -ErrorAction Stop ` | |
| -Verbose:$false | |
| $uri = $response.nextLink | |
| foreach( $environment in $response.value ) | |
| { | |
| if( $environment.properties.databaseType -ne "CommonDataService" -or $environment.properties.provisioningState -ne "Succeeded" ) | |
| { | |
| continue | |
| } | |
| if( $environment.properties.displayname -eq "Microsoft 365" ) | |
| { | |
| continue | |
| } | |
| [PSCustomObject] @{ | |
| EnvironmentId = $environment.name | |
| EnvironmentName = $environment.properties.displayname | |
| EnvironmentUrl = $environment.properties.linkedEnvironmentMetadata.instanceUrl | |
| EnvironmentType = $environment.properties.environmentSku | |
| EnvironmentCreated = $environment.properties.createdTime | |
| EnvironmentLastModified = $environment.properties.lastModifiedTime | |
| } | |
| } | |
| } | |
| while( $response.nextLink ) | |
| } | |
| end | |
| { | |
| } | |
| } | |
| # get all environments that have dv | |
| $environments = Get-PowerPlatformEnvironment | |
| # enum all envs | |
| $tenantResults = foreach( $environment in $environments ) | |
| { | |
| # get all instances of user prompt per agent per day | |
| $results = Get-AgentUserPromptMetadata -OrganizationUrl $environment.EnvironmentUrl.TrimEnd("/") | |
| # merge w/ env properties | |
| $results | Select-Object *, | |
| @{Name="EnvironmentId"; Expression={$environment.EnvironmentId }}, | |
| @{Name="EnvironmentName"; Expression={$environment.EnvironmentName }}, | |
| @{Name="EnvironmentType"; Expression={$environment.EnvironmentType }} | |
| } | |
| # write results to csv | |
| $tenantResults | Export-Csv -Path "C:\_temp\org-results.csv" -NoTypeInformation |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment