Entra Agent Users¶
Overview¶
An Agent User is a specialized user account in Microsoft Entra purpose-built for AI agents. It is NOT the same as the Agent Identity (service principal). It's a second, optional identity paired 1:1 with an Agent Identity, designed for scenarios where the agent needs access to systems that require a user object — mailboxes, Teams channels, OneDrive, calendar, org chart presence.
The Agent User receives tokens with idtyp=user, meaning it looks like a user to every Microsoft 365 API. But it cannot have passwords, passkeys, or MFA factors — it authenticates exclusively through its parent Agent Identity's credentials.
Identity Hierarchy¶
Agent Identity Blueprint (application)
└─ BlueprintPrincipal (service principal)
└─ Agent Identity (service principal)
└─ Agent User (user object, optional, 1:1)
Note: The BlueprintPrincipal must be explicitly created after the Blueprint via a separate
POST /v1.0/serviceprincipals/microsoft.graph.agentIdentityBlueprintPrincipalcall. It is NOT auto-created when the Blueprint is created. This is a load-bearing detail — see the entraclawCLAUDE.mdNon-Negotiables andmsal-entra-agent-ids.mdStep 1 for the canonical creation flow.
The Agent User is:
- Created via POST /beta/users with @odata.type: microsoft.graph.agentUser
- Always linked to exactly one Agent Identity via identityParentId
- Immutable parent link — cannot be re-parented to a different Agent Identity
- Deleted automatically if the parent Agent Identity is deleted
Why Agent Users Exist¶
Agent Identities are service principals. Service principals cannot: - Have a mailbox (Exchange Online) - Join Teams channels or chats as a participant - Have OneDrive storage - Appear in the org chart or people cards - Be @mentioned in Teams, documents, or other M365 apps - Be assigned M365 licenses
Agent Users solve this. They're real user objects in the directory, but marked as agentic — so Conditional Access, ID Protection, and governance treat them appropriately (no MFA prompts, agent-aware audit, etc.).
Creating an Agent User¶
Permission Required¶
The Blueprint must be granted AgentIdUser.ReadWrite.IdentityParentedBy (application permission) in the tenant. This is NOT granted by default — it must be explicitly requested and admin-consented.
Alternatively, a different client (not the Blueprint) can use AgentIdUser.ReadWrite.All.
Least-privilege note:
AgentIdUser.ReadWrite.Allis broader (it can create Agent Users for any Blueprint in the tenant) and is correspondingly more sensitive. For least-privilege deployments, preferAgentIdUser.ReadWrite.IdentityParentedBygranted only to the Blueprint that's creating its own Agent Users — this scopes the permission to the Blueprint's own descendants and avoids granting tenant-wide Agent User creation to a single client.
API Call¶
POST https://graph.microsoft.com/beta/users
OData-Version: 4.0
Content-Type: application/json
Authorization: Bearer <token>
{
"@odata.type": "microsoft.graph.agentUser",
"displayName": "Entraclaw Agent",
"userPrincipalName": "entraclaw-agent@tenant.onmicrosoft.com",
"identityParentId": "{agent-identity-object-id}",
"mailNickname": "entraclaw-agent",
"accountEnabled": true
}
The token must come from the Blueprint (client_credentials) with the AgentIdUser.ReadWrite.IdentityParentedBy permission.
Endpoint status (May 2026):
POST /beta/usersfor Agent User creation remains in Microsoft Graph beta as of May 2026; v1.0 promotion is not yet announced. Continue building against beta but be aware that schema may evolve. TheagentIdentityBlueprintresource was promoted to v1.0 at GA;agentIdentityandagentUserwere not.
Licensing¶
Agent Users require M365 licenses to access M365 services. This is explicit in the docs:
Agentic users require appropriate Microsoft 365 licenses to access services like Teams, Email, Calendar, SharePoint, and OneDrive. Common licenses include Microsoft 365 E5, Teams Enterprise, and Microsoft 365 Copilot.
After assigning a license, resource provisioning (mailbox, OneDrive) typically completes within 10-15 minutes but can take up to 24 hours.
What This Means for Entraclaw¶
To give the agent its own Teams presence, we need: 1. An Agent User created and linked to the Agent Identity 2. A Teams-capable license assigned to the Agent User (E3, E5, or Teams Enterprise) 3. Wait for mailbox/Teams provisioning to complete
The agent then gets its own UPN (e.g., entraclaw-agent@tenant.onmicrosoft.com), its own Teams identity, and can be @mentioned, receive messages, and participate in chats.
Authentication: The Three-Hop Token Flow¶
Agent Users do NOT use device-code flow, OBO, or any interactive human auth. The flow is entirely machine-to-machine:
Hop 1: Blueprint Token¶
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={blueprint-app-id}
&scope=https://graph.microsoft.com/.default
&grant_type=client_credentials
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion={blueprint-credential}
Hop 2: Agent Identity Token (FIC exchange)¶
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={agent-identity-id}
&scope=api://AzureADTokenExchange/.default
&grant_type=client_credentials
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion={blueprint-token}
Hop 3: Agent User Token (user_fic grant)¶
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={agent-identity-id}
&scope=https://graph.microsoft.com/.default
&grant_type=user_fic
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion={blueprint-token}
&user_id={agent-user-object-id}
&user_federated_identity_credential={agent-identity-token}
The result is a delegated access token with idtyp=user that can call any Graph API requiring user context — Teams, Exchange, OneDrive, etc.
No human in the loop. No device-code flow. No OBO. Fully autonomous.
Parameter naming reconciliation (Microsoft canonical doc vs. entraclaw)¶
The Microsoft GA doc agent-user-oauth-flow (updated 2026-05-01) shows the third hop with these parameter names:
&grant_type=user_fic
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion={T1} # Blueprint→Agent Identity token
&user_federated_identity_credential={T2} # Agent Identity self-impersonation token
&username=agentuser@contoso.com # UPN, not object ID
&requested_token_use=on_behalf_of # explicit
Notable differences from this document's Hop 3 example above:
- Microsoft uses
&username=(the Agent User's UPN), not&user_id=(the object ID). - Microsoft adds an explicit
&requested_token_use=on_behalf_ofparameter. - Microsoft naming convention: T1 (Blueprint→Agent Identity), T2 (Agent Identity self-impersonation), then Hop 3 is the OBO-style call passing both T1 (as
client_assertion) and T2 (asuser_federated_identity_credential).
Recommended action: Verify the entraclaw implementation against the Microsoft canonical doc and harmonize parameter names. If &user_id= works against the live Entra endpoint, document it as an undocumented-but-functional alias and note that Microsoft's preferred parameter is &username=. Don't depend on either parameter being permanently aliased — the user_fic parameter naming may converge in a future post-GA migration.
Consent for Agent User¶
Before the Agent Identity can get tokens as the Agent User, an oAuth2PermissionGrant must be created:
POST https://graph.microsoft.com/v1.0/oauth2PermissionGrants
Authorization: Bearer {token}
Content-Type: application/json
{
"clientId": "{agent-identity-object-id}",
"consentType": "Principal",
"principalId": "{agent-user-object-id}",
"resourceId": "{ms-graph-sp-object-id}",
"scope": "Chat.Create Chat.ReadWrite ChatMessage.Send User.Read"
}
This grants the Agent Identity permission to act as the Agent User when calling Graph. This is a one-time admin operation per Agent User — not per session, not per token acquisition, not per scope-superset. Once granted, the Agent Identity can mint Agent User tokens with the granted scopes for that specific Agent User indefinitely (until the grant is revoked or the Agent User is deleted).
The consentType: "Principal" + principalId: <agent-user-oid> combination is the correct shape for Agent User consent. This is per-principal consent, distinct from tenant-wide admin consent (consentType: "AllPrincipals"). Tenant-wide consent for Agent User scopes would grant the Agent Identity the right to mint Agent User tokens for every Agent User in the tenant — almost certainly broader than intended.
Security Constraints¶
- No passwords/passkeys/MFA — only authenticates through parent Agent Identity
- No privileged admin roles — cannot be Global Admin, etc.
- No role-assignable groups — cannot be added to groups used for admin role assignment
- Guest-like default permissions — can enumerate users/groups but has limited directory access
- Immutable parent link — cannot be re-parented once created
- Auto-deleted with parent — if Agent Identity is deleted, Agent User is deleted too
Design Patterns (from Microsoft docs)¶
Digital Worker (our use case)¶
"A fully autonomous agent acts as a digital employee, provisioned with resources typically reserved for human employees: an Exchange mailbox, OneDrive share, and Teams presence."
Structure: One Blueprint → One Agent Identity → One Agent User
The Agent User gets: - Its own mailbox - Its own Teams presence - Listing in the Global Address List - Ability to be @mentioned - A human manager in the org chart (the sponsor)
When NOT to use Agent Users¶
- If the agent only needs application-level API access (use Agent Identity alone)
- If the agent only needs to call other agents (use Agent Identity with app roles)
- Scale-out replicas (share one Agent Identity, don't create per-replica)
Implications for Entraclaw¶
What Changes¶
- No device-code flow needed — Agent User authenticates via the three-hop machine-to-machine flow
- No OBO needed — Agent User gets its own delegated tokens without a human token exchange
- No refresh token caching in keychain — no human tokens to cache
- Blueprint needs FIC, not a client secret on device — production auth uses Federated Identity Credentials
- Agent needs a license — E3/E5/Teams Enterprise assigned to the Agent User
- Agent has its own Teams identity — messages come FROM the agent, not "on behalf of" the human
What Stays¶
- Provisioner app pattern (for creating Blueprint + Agent Identity + Agent User)
- Blueprint + BlueprintPrincipal + Agent Identity hierarchy
- Sponsor relationship (human accountable for the agent)
- Audit attribution (agent actions show as agent in sign-in logs)
- Conditional Access governance (admin can block the agent)
Directory Scale Constraints (Learning from 2026-04-08 debate)¶
Agent Users are directory objects. Every Agent User counts against the tenant's directory quota:
| Directory Size | Platform Support | Operational Risk |
|---|---|---|
| ≤300K | default | trivial |
| 300K–500K | common enterprise | low |
| 500K–1M | supported w/ approval | lifecycle needed |
| 1M–2M | achievable | RP propagation cost shows up — requires coordination |
Without a verified domain: 50K object limit. With 1+ verified domain: 300K object limit. Beyond that: contact Microsoft support.
Why This Matters for Agent Users at Scale¶
If each user creates multiple agent sessions (the identity PM reported 7-8 concurrent sessions), a 100K-employee company could need 700K+ Agent User objects — well past default limits.
Pooling Does NOT Work¶
A "connection pool" model (pre-provision Agent Users, check out/return) was considered and rejected:
- OID recycling is a security risk — residual permissions/audit from one session would attach to the next user who gets that OID
- Soft-deleted objects still count against quota — deleted objects persist for 30 days at full weight, then another month at partial. Churning through pooled Agent Users worsens the scale problem.
- Hard deletes take time — total lifecycle of a deleted object is ~2 months before quota is freed
Better Alternatives¶
- IC3/Teams federation (identity architect's proposal) — agent identities live in Teams' IC3 backend, not the Entra directory. Session IDs as external OIDs via native federation tokens. IC3 already scales to billions. No directory objects needed for chat-only scenarios.
- FMIs (Federated Machine Identities) — SPIFFE/SPIRE-like identities that don't require directory objects. Could be hosted in IC3 or a separate identity store.
- Ephemeral Agent Users with TTL — auto-deprovision after session end. Acceptable if the 2-month delete lifecycle is fixed.
Implication¶
For ad-hoc CLI sessions, Agent Users (directory objects) are overkill. Reserve Agent Users for long-running autonomous agents that need persistent identity, governance, and resource access. For ephemeral sessions, use a lighter identity construct (federation, FMI, or OBO with decorated tokens).