Agent identities authenticate as service principals, hold OAuth scopes, and act autonomously across the tenant. This is a reference architecture for enforcing owner accountability, declarative permission scoping, and lifecycle deprovisioning on every agent, implemented through the Microsoft Graph API with Conditional Access as the enforcement backstop.
An agent identity is a first-class security principal in the tenant. It inherits from servicePrincipal, carries delegated and application permissions, and acquires tokens. When one is provisioned without an owner relationship, without declared scopes, and without a lifecycle trigger, it becomes an unmanaged non-human identity with standing access and no control plane.
Disabling the creating user's account has no cascading effect on the agents they own. Without an explicit owner-to-principal link and a leaver trigger, orphaned agents retain active credentials indefinitely.
Agents accrue appRoleAssignments and OAuth grants with no baseline to audit against. There is no declared scope to certify during access reviews and no authoritative state to revoke against.
The platform performs no automatic disablement on owner departure. Absent custom automation against the Graph API, an agent's accountEnabled state never changes when its accountable human leaves.
Copilot Studio, Azure AI Foundry, the Graph API, and custom code all emit agent identities today, with no shared convention, and additional provisioning surfaces are likely as the platform evolves. Owner and sponsor relationships can be assigned, but enforcement is conditional at best, and custom security attributes, tags, and approval state are inconsistent across every path.
Sponsor is auto-assigned to the calling user only in delegated (user-context) creation, only when no sponsor is specified, and not for Agent ID admin-role callers. App-only flows must set it explicitly. The outcome is an inconsistent governance posture, not a deliberate one.
Every agent identity, regardless of provisioning channel, surfaces in the Entra admin center under Agent ID and Enterprise applications. Administrators can enumerate principals, inspect native properties (display name, blueprint ID, owners, sponsors, sign-in activity), and disable individual objects. The surface is sufficient for visibility and reactive containment but does not provide the governance primitives this architecture introduces: no native intake or approval workflow, no enforced ownership or metadata contract at creation, no policy-driven denial of unapproved principals, no scheduled certification or owner-departure cascade, and no aggregated view across blueprint, classification, and lifecycle state. The architecture below adds those capabilities as a control plane on top of the native surface.
Each agent carries a structured metadata set split between enforcement-grade custom security attributes and auditable tags. A Conditional Access policy evaluates the approval attribute and blocks token issuance for any principal not explicitly approved, independent of the provisioning channel.
Typed, schema-validated, and queryable. Only string-typed CSA can be referenced by a CA policy filter, so all enforcement-targetable fields, including ownership, approval state, classification, and department scope, are modeled here.
A self-sufficient label set that forms an auditable record for inventory, chargeback, and compliance dashboards, readable without the elevated CSA role. Tags are not CA-targetable, so they carry audit-only attributes and mirrored copies of enforcement fields for traceability.
The enforcement backstop. A policy excludes only principals carrying approvalStatus: Approved from a block rule, so any agent lacking the attribute is denied token issuance until governance is satisfied.
Every agent is provisioned with approvalStatus: New and is denied by policy from inception. A security review is the only transition that sets Approved. This converts "governable in principle" into "governed by default," uniformly, across all provisioning channels.
The model maps to recognized non-human identity controls: owner accountability and least-privilege scoping satisfy the identity-governance expectations in NIST SP 800-53 (AC-2, AC-6) and ISO/IEC 27001 Annex A access-control objectives, while periodic certification and automated deprovisioning address the lifecycle requirements increasingly called out for machine and agent identities. Conditional Access enforcement provides the Zero Trust verification layer Microsoft's own guidance recommends for agent principals.
Metadata is distributed across three locations on the agentIdentity object. Native fields are platform-managed; tags carry auditable labels; custom security attributes form the enforcement-grade store, grouped by function.
CA app-filter rules can target a class of agents by a string-typed custom security attribute. Modeling blueprint name as a CSA enables a single durable policy expression across an entire blueprint class, complementing native blueprint-ID targeting rather than enumerating object IDs.
Free-text purpose is never CA-targetable, so it adds no enforcement value as an attribute. As a tag it remains accessible to reporting pipelines and review notifications without provisioning the elevated CSA assignment role.
Most agents originate in Azure AI Foundry and Copilot Studio, which provision identities directly without passing through a central intake. Governance therefore runs as a detection-and-remediation loop: every agent is discovered, evaluated against the metadata contract, and held at the CA gate until it is complete and approved.
New and InReview are denied; Approved is the only token-issuing state. Owner departure or a failed certification transitions the principal to Suspended, also denied. The CA policy expression is static; only the attribute value transitions.
CA-AGENT-001 denies any principal not carrying approvalStatus: Approved throughout the lifecycle, so the agent remains non-functional during the window before either detection path completes its evaluation.
# Path B: enumerate all agent identities (authoritative sweep) GET /servicePrincipals/microsoft.graph.agentIdentity ?$select=id,displayName,accountEnabled,createdDateTime, agentIdentityBlueprintId,tags,customSecurityAttributes &$orderby=createdDateTime desc &$top=100 # Sample response: each item is typed as agentIdentity, a subtype of servicePrincipal { "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#servicePrincipals", "value": [ { "@odata.type": "#microsoft.graph.agentIdentity", "id": "8a2f9c41-1d4e-4b87-9a3c-7e9f2d11c91d", "displayName": "Finance-Invoice-Processor-v1", "accountEnabled": true, "createdDateTime": "2026-06-01T09:14:22Z", "servicePrincipalType": "ServiceIdentity", "agentIdentityBlueprintId": "a1b2c3d4-BPW01", "tags": [ "env:production", "team:finance-automation", "blueprint:files-readwrite", "status:Approved" ], "customSecurityAttributes": { "AgentGov": { "approvalStatus": "Approved", "ownerObjectId": "7c4f...e21a", "dataClassification": "Confidential" } } } ] } # Completeness check: read CSA + owners for one agent GET /servicePrincipals/{id}?$select=customSecurityAttributes GET /servicePrincipals/{id}/microsoft.graph.agentIdentity/owners # Automation step: PATCH tags + CSA from RITM submission PATCH /servicePrincipals/{id}/microsoft.graph.agentIdentity { "tags": [ "env:production", "team:finance-automation", "blueprint:files-readwrite", "status:New" ], "customSecurityAttributes": { "AgentGov": { "@odata.type": "#microsoft.graph.CustomSecurityAttributeValue", "approvalStatus": "New", "ownerObjectId": "{ownerObjectIdFromRITM}", "sponsorUPN": "{sponsorUPNFromRITM}", "blueprintName": "{blueprintFromRITM}", "dataClassification": "{classificationFromRITM}" } } } # Backstop: deny token issuance until approved (Conditional Access) POST /identity/conditionalAccess/policies { "displayName": "CA-AGENT-001: Block unapproved agent identities", "state": "enabled", "grantControls": { "operator": "OR", "builtInControls": ["block"] } }
The reconciliation sweep is the authoritative source because the dedicated microsoft.graph.agentIdentity endpoint returns only agent identities and includes the blueprint ID and custom security attributes in a single paged response, unlike the generic audit event, which does not reliably carry agent-specific fields at creation time.
The accountability chain only holds if it survives joiner-mover-leaver events. A scheduled job evaluates the directory state of each agent's owner and sponsor, escalates when one role is unresolvable, and suspends the principal when both are. Conditional Access remains the enforcement backstop throughout.
If the owner or sponsor is disabled, soft-deleted, or no longer a member of the directory, the lifecycle job notifies the remaining principal with the agent identifier, the missing role, and a link to the ServiceNow RITM template for ownership update. The agent continues to operate so business workloads are not interrupted while the gap is being closed.
If both owner and sponsor are unresolvable, no accountable human remains. The job stamps approvalStatus: Suspended on the agent (CA-AGENT-001 then denies all tokens) and PATCHes accountEnabled: false on the principal. A P1 ServiceNow incident is raised to the blueprint owner team for review or formal decommission.
Once approvalStatus transitions off Approved, CA-AGENT-001 denies token issuance immediately, even while accountEnabled changes are still propagating. The CSA value is the authoritative enforcement signal.
# Resolve owner state: check if user exists and is enabled GET /users/{ownerObjectId}?$select=id,accountEnabled,userPrincipalName # A 404 response (or accountEnabled: false) indicates the owner is unresolvable # Both principals unavailable: suspend the agent and disable the SP PATCH /servicePrincipals/{id}/microsoft.graph.agentIdentity { "accountEnabled": false, "customSecurityAttributes": { "AgentGov": { "@odata.type": "#microsoft.graph.CustomSecurityAttributeValue", "approvalStatus": "Suspended", "suspendedReason": "OwnerSponsorBothUnresolvable", "suspendedDate": "2026-06-13" } } }
Microsoft Entra Conditional Access for Agent ID treats agent identities as first-class principals and evaluates their token-acquisition flows against tenant policy. Two scenarios apply directly to this architecture: restrict token issuance to approved agents only, and deny token issuance to agents flagged high-risk by Microsoft Entra ID Protection. Both target string-typed custom security attributes on the agent identity.
Token acquisition triggers CA evaluation against the agent's AgentGov.approvalStatus CSA. Agent A matches the exclusion criterion and is granted access. Agents B and C do not (New, or attribute absent) and are denied, irrespective of provisioning channel. This implements the Scenario 1 pattern documented in Microsoft Learn for CSA-driven agent targeting: the rule is expressed as exclusion-from-block, so any principal lacking the attribute fails closed.
The target resource carries ResourceAccess.department: HR. The policy grants only agents whose approvedForDepts CSA contains the resource's department value. Agent A is scoped to HR and Finance and is granted; Agent B is scoped to Marketing only and is denied; Agent C has no department scope and fails closed.
The risk signal is sourced from Microsoft Entra ID Protection, which evaluates behavioral and contextual anomalies for each agent identity. Agents A and B are at Low and Medium risk respectively and are granted. Agent C is flagged High and is denied, even though its approvalStatus is Approved. Risk-based and attribute-based policies compose additively: the principal must clear every policy on the token-acquisition path.
Every applicable policy is evaluated for each agent token request. CA-AGENT-001 enforces approval state; CA-AGENT-002 enforces resource-department scope; CA-AGENT-003 enforces risk-based denial. The principal must clear all three; failure of any single policy results in token denial. Each policy reads a distinct CSA group or Microsoft Entra ID Protection signal, so the controls are independent and additive.
Every CA evaluation for an agent identity is captured in the Microsoft Entra sign-in logs. Filter Service principal sign-ins on agentType = agent identity to retrieve the policies applied, the inclusion or exclusion clauses evaluated, and the CSA values read at decision time. This is the authoritative diagnostic source when an approved agent is unexpectedly denied or an unapproved agent is observed acquiring tokens.
The placement rule is deterministic: enforcement-targetable fields are modeled as custom security attributes; audit-only fields as tags; fields serving both are mirrored. Only string-typed CSA are CA-targetable.
| Attribute | Placement | Rationale |
|---|---|---|
| approvalStatus | CSA Tag | CA policy evaluates the CSA; the tag mirror feeds dashboards without the CSA read role. |
| blueprintName | CSA · Tag · Native | CA-targetable as a string CSA, reportable as a tag, and present as the native blueprint ID. |
| dataClassification | CSA Tag | Scopes CA policy by sensitivity tier and feeds classification reporting. |
| approvedForDepts | CSA | Drives department-scoped CA; multi-value, enforcement-only. |
| ownerObjectId / ownerUPN | CSA Tag | Leaver automation resolves the object ID; reporting reads the tag mirror. |
| agentPurpose | Tag | Free text is not CA-targetable; reporting and review notifications only. |
| serviceNowRITM | CSA Tag | Binds the principal to its originating request record for audit traceability. |
| costCenter / team | Tag | Chargeback and ownership reporting; no enforcement dependency. |
Primary Microsoft Learn references for the agent identity resource model, administrative relationships, Conditional Access targeting, and the Graph endpoints used throughout this architecture.
Microsoft Entra Agent ID is in preview at the time of writing; resource shapes and endpoint paths may change before general availability. Verify against the live documentation before implementation.