|
| 1 | +--- |
| 2 | +name: entra-agent-id |
| 3 | +description: | |
| 4 | + Microsoft Entra Agent ID (preview) for creating OAuth2-capable AI agent identities via Microsoft Graph beta API. |
| 5 | + Covers Agent Identity Blueprints, BlueprintPrincipals, Agent Identities, required permissions, sponsors, and Workload Identity Federation. |
| 6 | + Triggers: "agent identity", "agent id", "Agent Identity Blueprint", "BlueprintPrincipal", "entra agent", "agent identity provisioning", "Graph agent identity". |
| 7 | +--- |
| 8 | + |
| 9 | +# Microsoft Entra Agent ID |
| 10 | + |
| 11 | +Create and manage OAuth2-capable identities for AI agents using Microsoft Graph beta API. |
| 12 | + |
| 13 | +> **Preview API** — All Agent Identity endpoints are under `/beta` only. Not available in `/v1.0`. |
| 14 | +
|
| 15 | +## Before You Start |
| 16 | + |
| 17 | +Search `microsoft-docs` MCP for the latest Agent ID documentation: |
| 18 | +- Query: "Microsoft Entra agent identity setup" |
| 19 | +- Verify: API parameters match current preview behavior |
| 20 | + |
| 21 | +## Conceptual Model |
| 22 | + |
| 23 | +``` |
| 24 | +Agent Identity Blueprint (application) ← one per agent type/project |
| 25 | + └── BlueprintPrincipal (service principal) ← MUST be created explicitly |
| 26 | + ├── Agent Identity (SP): agent-1 ← one per agent instance |
| 27 | + ├── Agent Identity (SP): agent-2 |
| 28 | + └── Agent Identity (SP): agent-3 |
| 29 | +``` |
| 30 | + |
| 31 | +## Prerequisites |
| 32 | + |
| 33 | +### PowerShell (recommended for interactive setup) |
| 34 | + |
| 35 | +```powershell |
| 36 | +# Requires PowerShell 7+ |
| 37 | +Install-Module Microsoft.Graph.Beta.Applications -Scope CurrentUser -Force |
| 38 | +``` |
| 39 | + |
| 40 | +### Python (for programmatic provisioning) |
| 41 | + |
| 42 | +```bash |
| 43 | +pip install azure-identity requests |
| 44 | +``` |
| 45 | + |
| 46 | +### Required Entra Roles |
| 47 | + |
| 48 | +One of: **Agent Identity Developer**, **Agent Identity Administrator**, or **Application Administrator**. |
| 49 | + |
| 50 | +## Environment Variables |
| 51 | + |
| 52 | +```bash |
| 53 | +AZURE_TENANT_ID=<your-tenant-id> |
| 54 | +AZURE_CLIENT_ID=<app-registration-client-id> |
| 55 | +AZURE_CLIENT_SECRET=<app-registration-secret> |
| 56 | +``` |
| 57 | + |
| 58 | +## Authentication |
| 59 | + |
| 60 | +> **⚠️ `DefaultAzureCredential` is NOT supported.** Azure CLI tokens contain |
| 61 | +> `Directory.AccessAsUser.All`, which Agent Identity APIs explicitly reject (403). |
| 62 | +> You MUST use a dedicated app registration with `client_credentials` flow or |
| 63 | +> connect via `Connect-MgGraph` with explicit delegated scopes. |
| 64 | +
|
| 65 | +### PowerShell (delegated permissions) |
| 66 | + |
| 67 | +```powershell |
| 68 | +Connect-MgGraph -Scopes @( |
| 69 | + "AgentIdentityBlueprint.Create", |
| 70 | + "AgentIdentityBlueprint.ReadWrite.All", |
| 71 | + "AgentIdentityBlueprintPrincipal.Create", |
| 72 | + "User.Read" |
| 73 | +) |
| 74 | +Set-MgRequestContext -ApiVersion beta |
| 75 | +
|
| 76 | +$currentUser = (Get-MgContext).Account |
| 77 | +$userId = (Get-MgUser -UserId $currentUser).Id |
| 78 | +``` |
| 79 | + |
| 80 | +### Python (application permissions) |
| 81 | + |
| 82 | +```python |
| 83 | +import os |
| 84 | +import requests |
| 85 | +from azure.identity import ClientSecretCredential |
| 86 | + |
| 87 | +credential = ClientSecretCredential( |
| 88 | + tenant_id=os.environ["AZURE_TENANT_ID"], |
| 89 | + client_id=os.environ["AZURE_CLIENT_ID"], |
| 90 | + client_secret=os.environ["AZURE_CLIENT_SECRET"], |
| 91 | +) |
| 92 | +token = credential.get_token("https://graph.microsoft.com/.default") |
| 93 | + |
| 94 | +GRAPH = "https://graph.microsoft.com/beta" |
| 95 | +headers = { |
| 96 | + "Authorization": f"Bearer {token.token}", |
| 97 | + "Content-Type": "application/json", |
| 98 | + "OData-Version": "4.0", # Required for all Agent Identity API calls |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +## Core Workflow |
| 103 | + |
| 104 | +### Step 1: Create Agent Identity Blueprint |
| 105 | + |
| 106 | +Sponsors are required and **must be User objects** — ServicePrincipals and Groups are rejected. |
| 107 | + |
| 108 | +```python |
| 109 | +import subprocess |
| 110 | + |
| 111 | +# Get sponsor user ID (client_credentials has no user context, so use az CLI) |
| 112 | +result = subprocess.run( |
| 113 | + ["az", "ad", "signed-in-user", "show", "--query", "id", "-o", "tsv"], |
| 114 | + capture_output=True, text=True, check=True, |
| 115 | +) |
| 116 | +user_id = result.stdout.strip() |
| 117 | + |
| 118 | +blueprint_body = { |
| 119 | + "@odata.type": "Microsoft.Graph.AgentIdentityBlueprint", |
| 120 | + "displayName": "My Agent Blueprint", |
| 121 | + "sponsors@odata.bind": [ |
| 122 | + f"https://graph.microsoft.com/beta/users/{user_id}" |
| 123 | + ], |
| 124 | +} |
| 125 | +resp = requests.post(f"{GRAPH}/applications", headers=headers, json=blueprint_body) |
| 126 | +resp.raise_for_status() |
| 127 | + |
| 128 | +blueprint = resp.json() |
| 129 | +app_id = blueprint["appId"] |
| 130 | +blueprint_obj_id = blueprint["id"] |
| 131 | +``` |
| 132 | + |
| 133 | +### Step 2: Create BlueprintPrincipal |
| 134 | + |
| 135 | +> **This step is mandatory.** Creating a Blueprint does NOT auto-create its |
| 136 | +> service principal. Without this, Agent Identity creation fails with: |
| 137 | +> `400: The Agent Blueprint Principal for the Agent Blueprint does not exist.` |
| 138 | +
|
| 139 | +```python |
| 140 | +sp_body = { |
| 141 | + "@odata.type": "Microsoft.Graph.AgentIdentityBlueprintPrincipal", |
| 142 | + "appId": app_id, |
| 143 | +} |
| 144 | +resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=sp_body) |
| 145 | +resp.raise_for_status() |
| 146 | +``` |
| 147 | + |
| 148 | +If implementing idempotent scripts, check for and create the BlueprintPrincipal |
| 149 | +even when the Blueprint already exists (a previous run may have created the Blueprint |
| 150 | +but crashed before creating the SP). |
| 151 | + |
| 152 | +### Step 3: Create Agent Identities |
| 153 | + |
| 154 | +```python |
| 155 | +agent_body = { |
| 156 | + "@odata.type": "Microsoft.Graph.AgentIdentity", |
| 157 | + "displayName": "my-agent-instance-1", |
| 158 | + "agentIdentityBlueprintId": app_id, |
| 159 | + "sponsors@odata.bind": [ |
| 160 | + f"https://graph.microsoft.com/beta/users/{user_id}" |
| 161 | + ], |
| 162 | +} |
| 163 | +resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=agent_body) |
| 164 | +resp.raise_for_status() |
| 165 | +agent = resp.json() |
| 166 | +``` |
| 167 | + |
| 168 | +## API Reference |
| 169 | + |
| 170 | +| Operation | Method | Endpoint | OData Type | |
| 171 | +|-----------|--------|----------|------------| |
| 172 | +| Create Blueprint | `POST` | `/applications` | `Microsoft.Graph.AgentIdentityBlueprint` | |
| 173 | +| Create BlueprintPrincipal | `POST` | `/servicePrincipals` | `Microsoft.Graph.AgentIdentityBlueprintPrincipal` | |
| 174 | +| Create Agent Identity | `POST` | `/servicePrincipals` | `Microsoft.Graph.AgentIdentity` | |
| 175 | +| List Agent Identities | `GET` | `/servicePrincipals?$filter=...` | — | |
| 176 | +| Delete Agent Identity | `DELETE` | `/servicePrincipals/{id}` | — | |
| 177 | +| Delete Blueprint | `DELETE` | `/applications/{id}` | — | |
| 178 | + |
| 179 | +All endpoints use base URL: `https://graph.microsoft.com/beta` |
| 180 | + |
| 181 | +## Required Permissions |
| 182 | + |
| 183 | +| Permission | Purpose | |
| 184 | +|-----------|---------| |
| 185 | +| `Application.ReadWrite.All` | Blueprint CRUD (application objects) | |
| 186 | +| `AgentIdentityBlueprint.Create` | Create new Blueprints | |
| 187 | +| `AgentIdentityBlueprint.ReadWrite.All` | Read/update Blueprints | |
| 188 | +| `AgentIdentityBlueprintPrincipal.Create` | Create BlueprintPrincipals | |
| 189 | +| `AgentIdentity.Create.All` | Create Agent Identities | |
| 190 | +| `AgentIdentity.ReadWrite.All` | Read/update Agent Identities | |
| 191 | + |
| 192 | +There are **18 Agent Identity-specific** Graph application permissions. Discover all: |
| 193 | +```bash |
| 194 | +az ad sp show --id 00000003-0000-0000-c000-000000000000 \ |
| 195 | + --query "appRoles[?contains(value, 'AgentIdentity')].{id:id, value:value}" -o json |
| 196 | +``` |
| 197 | + |
| 198 | +Grant admin consent (required for application permissions): |
| 199 | +```bash |
| 200 | +az ad app permission admin-consent --id <client-id> |
| 201 | +``` |
| 202 | + |
| 203 | +> Admin consent may fail with 404 if the service principal hasn't replicated. Retry with 10–40s backoff. |
| 204 | +
|
| 205 | +## Cleanup |
| 206 | + |
| 207 | +```python |
| 208 | +# Delete Agent Identity |
| 209 | +requests.delete(f"{GRAPH}/servicePrincipals/{agent['id']}", headers=headers) |
| 210 | + |
| 211 | +# Delete BlueprintPrincipal (get SP ID first) |
| 212 | +sps = requests.get( |
| 213 | + f"{GRAPH}/servicePrincipals?$filter=appId eq '{app_id}'", |
| 214 | + headers=headers, |
| 215 | +).json() |
| 216 | +for sp in sps.get("value", []): |
| 217 | + requests.delete(f"{GRAPH}/servicePrincipals/{sp['id']}", headers=headers) |
| 218 | + |
| 219 | +# Delete Blueprint |
| 220 | +requests.delete(f"{GRAPH}/applications/{blueprint_obj_id}", headers=headers) |
| 221 | +``` |
| 222 | + |
| 223 | +## Best Practices |
| 224 | + |
| 225 | +1. **Always create BlueprintPrincipal after Blueprint** — not auto-created; implement idempotent checks on both |
| 226 | +2. **Use User objects as sponsors** — ServicePrincipals and Groups are rejected |
| 227 | +3. **Handle permission propagation delays** — after admin consent, wait 30–120s; retry with backoff on 403 |
| 228 | +4. **Include `OData-Version: 4.0` header** on every Graph request |
| 229 | +5. **Use Workload Identity Federation for production auth** — for local dev, use a client secret on the Blueprint (see [references/oauth2-token-flow.md](references/oauth2-token-flow.md)) |
| 230 | +6. **Set `identifierUris` on Blueprint** before using OAuth2 scoping (`api://{app-id}`) |
| 231 | +7. **Never use Azure CLI tokens** for API calls — they contain `Directory.AccessAsUser.All` which is hard-rejected |
| 232 | +8. **Check for existing resources** before creating — implement idempotent provisioning |
| 233 | + |
| 234 | +## References |
| 235 | + |
| 236 | +| File | Contents | |
| 237 | +|------|----------| |
| 238 | +| [references/oauth2-token-flow.md](references/oauth2-token-flow.md) | Production (Managed Identity + WIF) and local dev (client secret) token flows | |
| 239 | +| [references/known-limitations.md](references/known-limitations.md) | 29 known issues organized by category (from official preview known-issues page) | |
| 240 | + |
| 241 | +### External Links |
| 242 | + |
| 243 | +| Resource | URL | |
| 244 | +|----------|-----| |
| 245 | +| Official Setup Guide | https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-setup-instructions | |
| 246 | +| AI-Guided Setup | https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-ai-guided-setup | |
0 commit comments