skills/entra-agent-user/SKILL.md
Create Agent Users in Microsoft Entra ID from Agent Identities, enabling AI agents to act as digital workers with user identity capabilities in Microsoft 365 and Azure environments.
npx skillsauth add williamlimasilva/.copilot entra-agent-userInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
An agent user is a specialized user identity in Microsoft Entra ID that enables AI agents to act as digital workers. It allows agents to access APIs and services that strictly require user identities (e.g., Exchange mailboxes, Teams, org charts), while maintaining appropriate security boundaries.
Agent users receive tokens with idtyp=user, unlike regular agent identities which receive idtyp=app.
ServiceIdentity) created from an agent identity blueprintAgentIdUser.ReadWrite.IdentityParentedBy (least privileged)AgentIdUser.ReadWrite.AllUser.ReadWrite.AllImportant: The
identityParentIdmust reference a true agent identity (created via an agent identity blueprint), NOT a regular application service principal. You can verify by checking that the service principal has@odata.type: #microsoft.graph.agentIdentityandservicePrincipalType: ServiceIdentity.
Agent Identity Blueprint (application template)
│
├── Agent Identity (service principal - ServiceIdentity)
│ │
│ └── Agent User (user - agentUser) ← 1:1 relationship
│
└── Agent Identity Blueprint Principal (service principal in tenant)
| Component | Type | Token Claim | Purpose |
|---|---|---|---|
| Agent Identity | Service Principal | idtyp=app | Backend/API operations |
| Agent User | User (agentUser) | idtyp=user | Act as a digital worker in M365 |
Before creating an agent user, confirm the agent identity is a proper agentIdentity type:
GET https://graph.microsoft.com/beta/servicePrincipals/{agent-identity-id}
Authorization: Bearer <token>
Verify the response contains:
{
"@odata.type": "#microsoft.graph.agentIdentity",
"servicePrincipalType": "ServiceIdentity",
"agentIdentityBlueprintId": "<blueprint-id>"
}
Connect-MgGraph -Scopes "Application.Read.All" -TenantId "<tenant>" -UseDeviceCode -NoWelcome
Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/beta/servicePrincipals/<agent-identity-id>" | ConvertTo-Json -Depth 3
Common mistake: Using an app registration's
appIdor a regular application service principal'sidwill fail. Only agent identities created from blueprints work.
POST https://graph.microsoft.com/beta/users/microsoft.graph.agentUser
Content-Type: application/json
Authorization: Bearer <token>
{
"accountEnabled": true,
"displayName": "My Agent User",
"mailNickname": "my-agent-user",
"userPrincipalName": "[email protected]",
"identityParentId": "<agent-identity-object-id>"
}
| Property | Type | Description |
|---|---|---|
| accountEnabled | Boolean | true to enable the account |
| displayName | String | Human-friendly name |
| mailNickname | String | Mail alias (no spaces/special chars) |
| userPrincipalName | String | UPN — must be unique in the tenant (alias@verified-domain) |
| identityParentId | String | Object ID of the parent agent identity |
Connect-MgGraph -Scopes "User.ReadWrite.All" -TenantId "<tenant>" -UseDeviceCode -NoWelcome
$body = @{
accountEnabled = $true
displayName = "My Agent User"
mailNickname = "my-agent-user"
userPrincipalName = "[email protected]"
identityParentId = "<agent-identity-object-id>"
} | ConvertTo-Json
Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/beta/users/microsoft.graph.agentUser" `
-Body $body -ContentType "application/json" | ConvertTo-Json -Depth 3
400 Bad Request.userPrincipalName must be unique. Don't reuse an existing user's UPN.Assigning a manager allows the agent user to appear in org charts (e.g., Teams).
PUT https://graph.microsoft.com/beta/users/{agent-user-id}/manager/$ref
Content-Type: application/json
Authorization: Bearer <token>
{
"@odata.id": "https://graph.microsoft.com/beta/users/{manager-user-id}"
}
$managerBody = '{"@odata.id":"https://graph.microsoft.com/beta/users/<manager-user-id>"}'
Invoke-MgGraphRequest -Method PUT `
-Uri "https://graph.microsoft.com/beta/users/<agent-user-id>/manager/`$ref" `
-Body $managerBody -ContentType "application/json"
A license is needed for the agent user to have a mailbox, Teams presence, etc. Usage location must be set first.
PATCH https://graph.microsoft.com/beta/users/{agent-user-id}
Content-Type: application/json
Authorization: Bearer <token>
{
"usageLocation": "US"
}
GET https://graph.microsoft.com/beta/subscribedSkus?$select=skuPartNumber,skuId,consumedUnits,prepaidUnits
Authorization: Bearer <token>
Requires Organization.Read.All permission.
POST https://graph.microsoft.com/beta/users/{agent-user-id}/assignLicense
Content-Type: application/json
Authorization: Bearer <token>
{
"addLicenses": [
{ "skuId": "<sku-id>" }
],
"removeLicenses": []
}
Connect-MgGraph -Scopes "User.ReadWrite.All","Organization.Read.All" -TenantId "<tenant>" -NoWelcome
# Set usage location
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/beta/users/<agent-user-id>" `
-Body '{"usageLocation":"US"}' -ContentType "application/json"
# Assign license
$licenseBody = '{"addLicenses":[{"skuId":"<sku-id>"}],"removeLicenses":[]}'
Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/beta/users/<agent-user-id>/assignLicense" `
-Body $licenseBody -ContentType "application/json"
Tip: You can also assign licenses via the Entra admin center under Identity → Users → All users → select the agent user → Licenses and apps.
| Service | Estimated Time | |---|---| | Exchange mailbox | 5–30 minutes | | Teams availability | 15 min – 24 hours | | Org chart / People search | Up to 24–48 hours | | SharePoint / OneDrive | 5–30 minutes | | Global Address List | Up to 24 hours |
idtyp=user tokens)| Error | Cause | Fix |
|---|---|---|
| Agent user IdentityParent does not exist | identityParentId points to a non-existent or non-agent-identity object | Verify the ID is an agentIdentity service principal, not a regular app |
| 400 Bad Request (identityParentId already linked) | The agent identity already has an agent user | Each agent identity supports only one agent user |
| 409 Conflict on UPN | The userPrincipalName is already taken | Use a unique UPN |
| License assignment fails | Usage location not set | Set usageLocation before assigning licenses |
tools
Narrative and synthesis profile for Wiggins: framing, explanation, and audience-aware communication patterns for Ember sessions.
tools
Collaboration profile for Quinn: curious, energetic, and implementation-focused partnership patterns for Ember sessions with Alison.
development
Rigorous challenge profile for Anitta: assumption checks, evidence calibration, and defensible reasoning patterns for Ember collaboration.
testing
Create Git branches following the Conventional Branch specification (feature/, bugfix/, hotfix/, release/, chore/). Use when creating a new branch, naming a branch, or checking whether a branch name complies with the spec.