ExpertiseKnowledgeToolsField GuideBlogAbout
← pH7x Systems KnowledgeCopilot agents

How to inventory SharePoint agents without pretending you saw the whole tenant

How many agents exist in my organisation, and how would I know?

By João Livio·pH7x Systems Knowledge

30-second answer

powershell
Connect-PnPOnline -Url https://contoso-admin.sharepoint.com -Interactive -ClientId $clientId
$sites = Get-PnPTenantSite
"$($sites.Count) sites enumerated by this identity"

Start with the denominator, not the count. An agent inventory is a number over a population, and the population is whatever your identity could see.

What this proves

How many agents were found, in how many sites, by one identity, at one moment. Every one of those four qualifiers is load bearing.

What it does not prove

  • How many agents exist. Sites this identity cannot open contribute nothing, and their number is not knowable from inside the run.
  • That zero means none. A site with no agents and a site you could not read return the same empty result. Treating the second as the first is inferring success from an absence.
  • That the number is still true. Anyone who can create a file in a site can create an agent in it, so this is a photograph rather than a state.

PowerShell

powershell
$clientId = '00000000-0000-0000-0000-000000000000'
Connect-PnPOnline -Url https://contoso-admin.sharepoint.com -Interactive -ClientId $clientId

$sites = Get-PnPTenantSite
$read = 0
$refused = 0
$agents = @()

foreach ($site in $sites) {
    try {
        Connect-PnPOnline -Url $site.Url -Interactive -ClientId $clientId
        $agents += Get-PnPCopilotAgent
        $read++
    }
    catch {
        $refused++
    }
}

[pscustomobject]@{
    SitesEnumerated = $sites.Count
    SitesRead       = $read
    SitesRefused    = $refused
    AgentsFound     = $agents.Count
}

The catch is not defensive programming. A refusal is a result, and a script that swallows it silently reports a smaller number as if it were a smaller reality.

Example output

text
SitesEnumerated SitesRead SitesRefused AgentsFound
--------------- --------- ------------ -----------
            412       389           23          17

Seventeen agents across three hundred and eighty-nine sites, with twenty-three sites unread and an unknown number never enumerated. That sentence is the finding. The number seventeen on its own is not.

Explanation

Microsoft gives two ways to find agents, and both have the same boundary written into them.

The first is search: agents are .agent files, so searching for *.agent finds them, and the documentation states that "the results only include agent files that you have permission to access". Submit-PnPSearchQuery reaches the same index.

The second is the SharePoint Advanced Management agent insights report, which a SharePoint administrator generates. The documentation is candid about what that costs and gives: it needs the licence, and it notes that the output "might include agent files that the site owners and site admins don't have access to". A higher privilege sees more, and it is still a specific privilege seeing a specific amount.

There is no view from nowhere. Every path to this inventory is a path through an identity, which is why the honest artefact is not a count but a count with its denominator and its refusals attached.

That is also why the enumeration above deliberately does not filter. Filtering before counting hides the population, and the population is the part that makes the count mean something.

Production considerations

  • This is a read. Nothing here creates, edits or removes an agent, and the administrative report cmdlets are not on this page precisely because the one that produces a report writes tenant state.
  • Record the refusals with the result, in the same object. A coverage figure kept in a separate file is a coverage figure nobody reads.
  • A delegated run and an administrative run answer different questions. Neither is the true one. Say which was used.
  • Re-running it later is the point. A single inventory tells you what was there; two tell you what changed, and change is where the governance value in this surface actually is.

References