Governing AI Agents in Entra ID: Why Observability Comes Before Policy

Before you can govern agentic identities, you have to see them. All of them.

The rise of Microsoft Copilot Studio and Power Virtual Agents has quietly created a new class of identity problem. Every agent an employee builds gets its own Entra ID object — sometimes two. At scale, a large enterprise can accumulate thousands of these registrations before anyone in the security or identity team has written a single governance policy for them.

The instinct is to jump straight to policy: block creation, enforce naming conventions, require manager approval. But policy without visibility is just noise. Before any of that works, you need a reliable, recurring answer to a deceptively simple question: what agents exist right now, who created them, and what can they access?

This post describes a strategy for answering that question using the Microsoft Graph API — and why, given the current state of the API, reaching that answer requires covering four distinct identity surfaces rather than calling a single endpoint.

First, Some Conceptual Grounding

Before getting into the data collection strategy, it helps to understand how Microsoft conceptualizes these identity objects — because the terminology matters when reasoning about governance gaps.

Entra Agent ID

An Entra Agent ID is a first-class identity type in Microsoft Entra, purpose-built for AI agents. It sits alongside users and service principals as a native identity object — designed specifically for autonomous and semi-autonomous agents rather than adapted from an existing type. Like any Entra identity, it can be subject to Conditional Access policies, lifecycle management, and identity governance controls.

Agent 365

Agent 365 is Microsoft’s control plane and inventory system for agents. An Agent 365 agent represents a real, active agent instance in the tenant — it could be Microsoft-built, partner-built, a custom line-of-business agent, a Copilot Studio agent, or an Azure AI Foundry agent. Think of Agent 365 as the operational registry: it shows agents that are active and available for use.

The Critical Relationship Between the Two

Microsoft states the foundational principle clearly:

“An agent may exist without an Entra Agent ID, but an Entra Agent ID does not exist without an agent.”

In a healthy, fully synchronized tenant, this means the Entra Agent ID count should be less than or equal to the Agent 365 agent count. Agent 365 is the broader population; Entra Agent IDs are the subset that has been formally provisioned with an identity.

In practice, however, this relationship can invert — and understanding why is central to building an effective observability strategy.

Why Identity Lifecycle ≠ Agent Lifecycle

Entra Agent IDs can be created during Copilot Studio authoring, during Azure AI Foundry deployment, during preview or Frontier experiments, or via registration APIs — and they persist even if the agent is later deleted, disabled, hidden, or never published to the Agent 365 registry. Meanwhile, Agent 365 applies Frontier gating and compliance filtering that can hide certain agents from the registry entirely, while Entra does not apply equivalent filtering to identities.

The result: during registry convergence and Frontier rollout phases, Entra identity counts can legitimately exceed Agent 365 counts. Microsoft explicitly allows this state because identity creation and registry convergence are not yet perfectly synchronized. The divergence exists to preserve audit trails, maintain security logs, and support forensics and rollback scenarios.

For governance purposes, this divergence is not noise to be ignored — it is a signal. An Entra Agent ID without a corresponding Agent 365 entry may represent a staged identity, a decommissioned agent whose identity was not cleaned up, or an agent hidden by compliance policy. Each case has different remediation implications, and none of them are visible through Agent 365 alone.

Blueprints

Microsoft explicitly compares the blueprint model to the relationship between app registrations and enterprise applications:

“Blueprints serve as the parent of an agent identity, similar to how an app registration relates to enterprise applications.”

A blueprint is a parent template in Entra that defines how one or more agent identities are created, authenticated, and governed. The chain is: Blueprint → Agent Identity (Entra Agent ID) → Agent (runtime/logical agent). Without blueprints, every agent would require a brand-new identity configuration with no inheritance and inconsistent authentication. Blueprints enable centralized configuration, predictable identity creation, and consistent token scopes at scale.

A blueprint is technically an application object in Entra ID — it lives in the applications collection and shares that structural foundation with any app registration. The more precise framing, however, is that the blueprint-to-agent-identity relationship mirrors the app-registration-to-service-principal relationship: an app registration governs a service principal, and a blueprint governs an agent identity. A blueprint is a specialized subtype (microsoft.graph.agentIdentityBlueprint), purpose-built as a provisioning template — a generic app registration plays no such role. This distinction matters in practice: querying the applications collection without the typed cast will surface blueprints alongside all other app registrations with nothing to distinguish them.

Microsoft’s stated rule is that no agent identity can exist without a blueprint. In practice, however, many blueprints are system-managed, legacy, or hidden and therefore not visible in the tenant UI. This means agent identities whose blueprint is not surfaced through standard queries are not misconfigured — they are a direct result of Microsoft-managed agents, legacy migrations, and the ongoing convergence between the identity and registry systems.

Don’t Microsoft’s Own Tools Already Show This?

With Agent 365 and the Entra ID portal both providing agent visibility, the question of why a custom collection strategy is needed deserves a direct answer.

What the Built-in Tools Offer

The Entra ID “Agent Identities” preview blade surfaces formally provisioned Entra Agent IDs — the microsoft.graph.agentIdentity typed service principals — directly in the Entra portal. For an administrator doing an ad hoc review, this is genuinely useful: you can see provisioned agents, inspect their linked blueprints, and check sponsor assignments without writing code.

Agent 365 (accessible through the Microsoft 365 Admin Center and Copilot Studio Admin Center) provides the operational registry view: which agents are active and available, their environments, and basic lifecycle status. For teams managing Copilot Studio deployments day-to-day, this is the natural starting point.

Where They Fall Short for Governance

Coverage is partial. The Entra ID Agent Identities blade covers only formally typed service principals provisioned through the newer flow. As described above, Agent 365 applies Frontier gating and compliance filtering that can hide agents entirely. Neither surface covers agents that exist in the registry without a service principal, legacy PVA and early Copilot Studio registrations that predate the typed schema, or blueprint registrations as a separate auditable population.

Visibility is point-in-time. Portal tools show the current state when a human navigates to them. Governance questions are often longitudinal: when did this agent appear? Has a new delegated permission been added since the last review? Was it active last month but dormant now? Answering those requires periodic snapshots and the ability to diff them.

There is no programmatic alerting. A portal blade cannot send a notification when a new unsponsored agent is provisioned, flag a blueprint whose linked agent count just crossed a threshold, or open a remediation ticket when an agent crosses 90 days of inactivity. Those workflows require structured data flowing into whatever alerting or ITSM system the organization already operates.

Cross-surface correlation is manual. The divergence between Entra Agent ID counts and Agent 365 counts described above — which is a governance signal worth tracking — requires correlating data across two separate systems that the portal does not join for you. At scale, that manual correlation does not hold.

The tools are still maturing. The Entra ID Agent Identities blade is in preview and both it and Agent 365 are evolving rapidly alongside the Copilot Studio product. A governance program built entirely on portal navigation is fragile against that churn in a way that a Graph API-based collection strategy — anchored on stable endpoints — is not.

The Right Mental Model

The portal tools and programmatic collection serve different purposes. The portal is where an administrator investigates a specific agent or responds to an alert. Programmatic collection is how the estate is monitored continuously, how the Entra/Agent 365 divergence is tracked over time, and how remediation workflows are triggered without requiring a human to log in and look. Both have a place; the mistake is assuming one substitutes for the other.

Why There Is No Single “List All Agents” Endpoint

To understand why four surfaces are necessary, it helps to see how Microsoft’s object model maps to the conceptual framework above. The Graph API spans three separate collections, each with its own schema:

agentRegistry (beta)
└── agentInstance ← registered agent, may or may not have an Entra identity
└── agentIdentityId ← links to a servicePrincipal if provisioned

servicePrincipal (v1.0)
└── microsoft.graph.agentIdentity ← typed subtype, only formally provisioned agents
└── agentIdentityBlueprintId ← links back to the blueprint application

application (v1.0 / beta)
└── microsoft.graph.agentIdentityBlueprint ← template used to provision agents
└── (any application) ← older Copilot Studio / PVA registrations
identified by agentic tags

A single Copilot Studio agent can create objects across all three collections. Because identity lifecycle and agent lifecycle are not synchronized, an agent can exist in the registry without a service principal, and a service principal can persist after the agent it represented has been removed from Agent 365. An app registration can predate the new typed schema entirely. A blueprint may be system-managed and not visible in the UI, yet its child agent identities are still queryable.

Any observability strategy that queries only one surface will have blind spots — including the portal tools, which face exactly the same underlying constraint.

Four Identity Surfaces to Cover

A complete picture of the agent estate requires querying four surfaces. The choice of implementation — a scheduled function, a workflow engine, a pipeline job, a notebook on a timer — matters far less than ensuring all four are covered consistently and enriched with the right context.

Surface 1: Agents With No Entra Identity

Agents that exist in the Copilot Studio registry but have never been provisioned with a service principal in Entra ID. Given that identity lifecycle and agent lifecycle are not synchronized, this population can be substantial: agents that were created in Copilot Studio but never formally provisioned, or agents that were deprovisioned from Entra while the registry entry persisted. In most tenants this population is invisible to any query that starts from the applications or servicePrincipals collections — including the Entra portal blade.

Key fields to capture: displayName, originatingStore, createdBy, ownerNames, hasOwner, createdDateTime

Surface 2: Formally Provisioned Agent Identities

Service principals typed as microsoft.graph.agentIdentity — created through the newer Copilot Studio agent identity flow, linked to a blueprint via agentIdentityBlueprintId, and capable of holding delegated permissions and app role assignments. This is the population visible in the Entra ID Agent Identities preview blade, and the one that most future governance tooling will converge on. It is already served by a stable v1.0 endpoint.

Tracking this population programmatically — and comparing its count against the Agent 365 registry over time — is one way to surface the Entra/Agent 365 divergence described earlier.

Most Copilot Studio agents in this population carry empty delegatedPermissions and appRoleResources. The platform manages permissions at the environment level rather than granting them per agent identity. That is expected behavior — but it also means permission auditing for these agents requires a different approach than traditional application governance.

Key fields to capture: sponsors, hasSponsor, delegatedPermissions, appRoleResources, lastSignInDateTime, agentIdentityBlueprintId

Surface 3: Agent Blueprints

Application registrations typed as microsoft.graph.agentIdentityBlueprint — the parent templates that define how agent identities are created and governed. As Microsoft notes, blueprints relate to agent identities the same way app registrations relate to enterprise applications. Each blueprint can generate many agent identities, and each has a corresponding service principal subtype (microsoft.graph.agentIdentityBlueprintPrincipal) accessible via a separate beta endpoint.

The governance risk is concentrated here: a misconfigured or unowned blueprint propagates its gap to every identity it creates. Note that many blueprints are system-managed or hidden and therefore not visible in the tenant UI — agent identities whose blueprint does not surface through standard queries are not anomalies, but they still warrant ownership and credential tracking at the blueprint level.

Deriving a linkedAgentCount per blueprint directly answers: if this blueprint is misconfigured, how many agents are affected?

Key fields to capture: owners, hasOwner, hasSecret, hasCertificate, linkedAgentCount

Surface 4: The Full Historical Estate (Tag-Based Apps)

The typed agentIdentity cast on Surface 2 covers only agents provisioned through the newer flow. Everything built before that schema existed — every Power Virtual Agents bot, every early Copilot Studio registration — appears only as an application object tagged with one or more agentic markers. Identifying this population requires a full scan of the applications collection with an in-memory filter for the following tags:

Agentic · AIAgentBuilder · AgenticApp · AgentCreatedBy: · AgenticInstance · power-virtual-agents

This surface typically represents the largest share of the agent estate in any mature tenant and is the most complete view of agent proliferation over time.

Key fields to capture: tags, owners, hasOwner, lastSignInDateTime, hasServicePrincipal, classification

How the Four Surfaces Relate

Surfaces 2 and 4 have overlapping appId values. A single Copilot Studio agent creates both an app registration (Surface 4) and a typed agentIdentity service principal (Surface 2) sharing the same appId. They are different Entra object types contributing different fields — not duplicates.

Surface 1 sits entirely outside the application/service principal object model. It is only accessible through the agent registry beta endpoint and is invisible to any query starting from applications or servicePrincipals.

┌──────────────────────────────────────────────────────┐
│ Surface 4 · Tag-based app registrations │
│ Full historical estate · PVA + Copilot Studio │
│ │
│ ┌────────────────────┐ ┌──────────────────────┐ │
│ │ Surface 3 │────▶│ Surface 2 │ │
│ │ Blueprints │ │ Agent Identities │ │
│ │ Blast-radius risk │ │ Typed SPs · sponsors │ │
│ └────────────────────┘ └──────────────────────┘ │
│ shared appId ↑↗ │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ Surface 1 · Agents with no Entra identity │
│ Registry entries · agentIdentityId = null │
│ Governance gap - no SP, no audit trail │
└──────────────────────────────────────────────────────┘

Graph API Reference

The following lists document the complete set of Graph API calls required to cover all four surfaces, including enrichment calls for ownership, permissions, and sign-in activity.

Agent Registry (beta)

  • GET /beta/agentRegistry/agentInstances?$filter=agentIdentityId eq null — Agents with no Entra identity (Surface 1)

Agent Identities — servicePrincipal typed subtype

  • GET /v1.0/servicePrincipals/microsoft.graph.agentIdentity — All formally provisioned agent identities, paginated (Surface 2)
  • GET /v1.0/servicePrincipals/microsoft.graph.agentIdentity?$filter=agentIdentityBlueprintId eq ‘{appId}’&$count=true&$top=1 — Count of agent identities linked to a given blueprint (Surface 3 enrichment)
  • GET /v1.0/servicePrincipals?$filter=appId eq ‘{appId}’ — Resolve service principal object ID from an app registration’s appId
  • GET /v1.0/servicePrincipals/{id}/owners — Service principal owners / sponsors
  • GET /v1.0/servicePrincipals/{id}/oauth2PermissionGrants — Delegated permission grants
  • GET /v1.0/servicePrincipals/{id}/appRoleAssignments — App role assignments

Blueprints — application typed subtype

  • GET /beta/applications/microsoft.graph.agentIdentityBlueprint — All blueprint app registrations, paginated (Surface 3)
  • GET /beta/servicePrincipals/microsoft.graph.agentIdentityBlueprintPrincipal — Service principal counterpart of blueprints
  • GET /v1.0/applications/{id}/owners — Blueprint owners

Tag-Based Apps — full application scan

  • GET /beta/applications?$select=id,appId,displayName,createdDateTime,signInAudience,notes,tags&$top=999 — All app registrations; filter in-memory for tags: Agentic, AIAgentBuilder, AgenticApp, AgentCreatedBy:, AgenticInstance, power-virtual-agents (Surface 4)

Enrichment — shared across surfaces

  • POST /v1.0/directoryObjects/getByIds — Batch-resolve owner GUIDs to display names
  • GET /v1.0/auditLogs/signIns?$filter=appId eq ‘{appId}’&$top=1&$orderby=createdDateTime desc — Most recent sign-in per agentThe API Challenge: Stable vs. Preview Endpoints

Several of the most relevant endpoints are still in beta. Beta endpoints can change schema, pagination behavior, or availability without notice — a real operational risk for any automated, recurring collection process.

A pragmatic mitigation is to anchor enrichment on stable v1.0 endpoints wherever possible, and treat beta calls as narrow, well-isolated collection steps. As the lists above show, all enrichment calls — owner resolution, permission grants, app role assignments, sign-in logs — already have stable v1.0 coverage. If a beta collection step breaks due to schema churn, only that surface’s raw collection is affected; the enrichment logic remains stable.

Authentication should use a Managed Identity or a dedicated service principal scoped to the minimum required Graph permissions: Application.Read.All, AuditLog.Read.All, and Directory.Read.All.

Governance Signals This Data Enables

With all four surfaces collected and enriched, a consistent set of governance signals becomes queryable across the entire agent estate:

  • hasOwner = False (all surfaces) — Assign an owner; check the notes field for the creator UPN, which Copilot Studio often sets at provisioning time
  • hasSponsor = False (Agent Identities) — Trace back via createdByAppName to assign a sponsor to the provisioning team
  • agentIdentityId null (No Identity surface) — Evaluate whether formal Entra provisioning is required for the agent
  • Entra Agent ID count > Agent 365 agent count (cross-surface) — Investigate divergence: look for staged, hidden, or decommissioned identities without corresponding registry entries
  • linkedAgentCount > 0 + hasOwner = False (Blueprints) — Highest priority: unowned templates that are actively generating new identities
  • hasSecret = True (Blueprints) — Audit who holds the credential and verify that a rotation schedule is in place
  • lastSignInDateTime null or >90 days (Identities, Tag-Based) — Flag as a candidate for decommissioning review
  • accountEnabled = False (Agent Identities) — Confirm whether decommissioning is fully complete.

One pattern worth highlighting: hasOwner = False on tag-based application registrations is the norm, not the exception. Most Copilot Studio and PVA registrations are auto-provisioned with no Entra owner. Ownership context, when it exists, is typically found in the notes field as a creator UPN. Surfacing that programmatically is one of the more practically useful things a collection strategy like this enables.

Why Observability Before Policy

The built-in portal tools — the Entra ID Agent Identities blade and Agent 365 — provide useful starting points for ad hoc review. Automated governance requires something different: structured, recurring, queryable data that feeds alerting, longitudinal tracking, and remediation workflows without a human in the loop.

The four-surface model described here is not a finished governance system. It is the foundation. Once that foundation is in place — whatever the implementation technology — automated remediation, lifecycle policies, CMDB integration, and risk scoring can all build on top of it without re-solving the data collection problem each time.

The agent identity estate in any active enterprise tenant will only grow. The Entra/Agent 365 divergence will persist until Microsoft fully synchronizes identity creation and registry convergence. Building strong observability first is the decision that makes everything downstream tractable.

What’s Next

A natural follow-on series from this foundation could explore:

  • Lifecycle automation: using collected inventory data to trigger remediation workflows for unowned agents
  • Permission drift detection: comparing periodic snapshots to surface newly added delegated permissions
  • Registry reconciliation: tracking and closing the divergence between Entra Agent ID counts and Agent 365 agent counts over time

Tags: Microsoft Entra ID, Microsoft Graph API, AI Governance, Copilot Studio, Agent 365, Identity Management, Agentic AI, Zero Trust


Governing AI Agents in Entra ID: Why Observability Comes Before Policy was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Liked Liked