tests/Test-Assessment.61005.ps1
|
<#
.SYNOPSIS Agents deployed to Microsoft 365 Copilot are discoverable in the Agent Registry. .DESCRIPTION The Microsoft 365 Agent Registry is the tenant-scoped catalogue that lists every declarative agent, connected agent, and custom Copilot extension published to users in the tenant. This check verifies that at least one agent is visible in the registry, confirming the registry is populated and providing the baseline visibility required for all downstream agent-governance controls. .NOTES Test ID: 61005 Category: AI Inventory & Lifecycle Pillar: AI Required Permission: CopilotPackages.Read.All (Delegated) #> function Test-Assessment-61005 { [ZtTest( Category = 'AI Inventory & Lifecycle', ImplementationCost = 'Low', Service = ('Graph'), CompatibleLicense = ('Microsoft_365_Copilot','AGENT_365'), Pillar = 'AI', RiskLevel = 'High', SfiPillar = 'Protect tenants and production systems', TenantType = ('Workforce'), TestId = 61005, Title = 'Agents deployed to Microsoft 365 Copilot are discoverable in the Agent Registry', UserImpact = 'Low' )] [CmdletBinding()] param() #region Data Collection Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose $activity = 'Checking agents in the Microsoft 365 Agent Registry' # Q1: List Copilot-hosted agent packages in the tenant Write-ZtProgress -Activity $activity -Status 'Retrieving Copilot agent packages from the Agent Registry' $agentPackages = $null $errorMsg = $null $httpStatusCode = $null try { $agentPackages = Invoke-ZtGraphRequest -RelativeUri 'copilot/admin/catalog/packages' -Filter "supportedHosts/any(h:h eq 'Copilot')" -ApiVersion beta -ErrorAction Stop } catch { $errorMsg = $_ Write-PSFMessage "Failed to retrieve Copilot agent packages: $errorMsg" -Level Warning if ($errorMsg.Exception.Response.StatusCode) { $httpStatusCode = [int]$errorMsg.Exception.Response.StatusCode.value__ } elseif ($errorMsg.Exception.Message -match '403|Forbidden') { $httpStatusCode = 403 } elseif ($errorMsg.Exception.Message -match '404|NotFound') { $httpStatusCode = 404 } } #endregion Data Collection #region Assessment Logic $passed = $false if ($errorMsg) { # 403/404 → tenant not enrolled in Frontier preview or Agent 365 license not activated if ($httpStatusCode -in @(403, 404)) { Write-PSFMessage "Agent Registry not accessible (HTTP $httpStatusCode) - tenant may not be enrolled in the required Frontier preview or lacks an Agent 365 license" -Level Verbose Add-ZtTestResultDetail -SkippedBecause NotApplicable ` -Result 'The tenant is not enrolled in the Microsoft 365 Copilot Frontier preview, or an Agent 365 trial or production license is not activated within the tenant, or the Microsoft 365 environment is in a cloud where the Agent Registry is not yet available.' return } # Other errors Write-PSFMessage "Unexpected error retrieving the Agent Registry (HTTP $httpStatusCode)" -Level Error $passed = $false } elseif (-not $agentPackages -or $agentPackages.Count -eq 0) { # HTTP 200 with empty value array — no agents registered $passed = $false } else { # HTTP 200 with one or more agents $passed = $true } #endregion Assessment Logic #region Report Generation if ($errorMsg) { $testResultMarkdown = "❌ Unable to retrieve agent packages from the Microsoft 365 Agent Registry.`n`nError: $errorMsg" } elseif ($passed) { $testResultMarkdown = "✅ Agents deployed to Microsoft 365 Copilot are visible in the Agent Registry.`n`n%TestResult%" } else { $testResultMarkdown = "❌ No agents are visible in the Microsoft 365 Agent Registry.`n`n%TestResult%" } $mdInfo = '' if ($agentPackages -and $agentPackages.Count -gt 0) { $portalLink = 'https://admin.cloud.microsoft/?#/agents/all' $totalCount = $agentPackages.Count $formatTemplate = @' ## [Agents visible in the Microsoft 365 Agent Registry]({0}) | Display name | Element types | Available to | Deployed to | | :----------- | :------------ | :----------- | :---------- | {1} '@ $tableRows = '' foreach ($package in ($agentPackages | Select-Object -First 10)) { $displayName = Get-SafeMarkdown -Text $package.displayName if ($package.elementTypes) { $elementTypesRaw = ($package.elementTypes | Sort-Object) -join ', ' } else { $elementTypesRaw = 'N/A' } $elementTypes = Get-SafeMarkdown -Text $elementTypesRaw if ($package.availableTo) { $availableToRaw = ($package.availableTo | ForEach-Object { if ($_ -is [string]) { $_ } elseif ($_.displayName) { $_.displayName } elseif ($_.type) { $_.type } elseif ($_.id) { $_.id } else { 'unknown' } }) -join ', ' } else { $availableToRaw = 'N/A' } $availableTo = Get-SafeMarkdown -Text $availableToRaw if ($package.deployedTo) { $deployedToRaw = ($package.deployedTo | ForEach-Object { if ($_ -is [string]) { $_ } elseif ($_.displayName) { $_.displayName } elseif ($_.type) { $_.type } elseif ($_.id) { $_.id } else { 'unknown' } }) -join ', ' } else { $deployedToRaw = 'N/A' } $deployedTo = Get-SafeMarkdown -Text $deployedToRaw $tableRows += "| $displayName | $elementTypes | $availableTo | $deployedTo |`n" } $mdInfo = $formatTemplate -f $portalLink, $tableRows if ($totalCount -gt 10) { $mdInfo += "`n`n_**Note**: This table is truncated and showing the first 10 of $totalCount agents._`n" } } $testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo #endregion Report Generation $params = @{ TestId = '61005' Title = 'Agents deployed to Microsoft 365 Copilot are discoverable in the Agent Registry' Status = $passed Result = $testResultMarkdown } Add-ZtTestResultDetail @params } |