GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

entra-agent-id

Microsoft Entra Agent ID (preview) for creating OAuth2-capable AI agent identities via Microsoft Graph beta API. Covers Agent Identity Blueprints, BlueprintPrincipals, Agent Identities, required permissions, sponsors, and Workload Identity Federation. Includes Microsoft Entra SDK

Ciza · 0 points · 24 views 1 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_skills_entra-agent-id-e58528d.zip · 11 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/skills/entra-agent-id
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Microsoft Entra Agent ID

Create and manage OAuth2-capable identities for AI agents using Microsoft Graph beta API.

Preview API — All Agent Identity endpoints are under /beta only. Not available in /v1.0.

Before You Start

Search microsoft-docs MCP for the latest Agent ID documentation:

  • Query: "Microsoft Entra agent identity setup"
  • Verify: API parameters match current preview behavior

Conceptual Model

Agent Identity Blueprint (application)        ← one per agent type/project
  └── BlueprintPrincipal (service principal)   ← MUST be created explicitly
        ├── Agent Identity (SP): agent-1       ← one per agent instance
        ├── Agent Identity (SP): agent-2
        └── Agent Identity (SP): agent-3

Prerequisites

PowerShell (recommended for interactive setup)

# Requires PowerShell 7+
Install-Module Microsoft.Graph.Beta.Applications -Scope CurrentUser -Force

Python (for programmatic provisioning)

pip install azure-identity requests

Required Entra Roles

One of: Agent Identity Developer, Agent Identity Administrator, or Application Administrator.

Environment Variables

AZURE_TENANT_ID=<your-tenant-id>
AZURE_CLIENT_ID=<app-registration-client-id>
AZURE_CLIENT_SECRET=<app-registration-secret>

Authentication

⚠️ DefaultAzureCredential is NOT supported. Azure CLI tokens contain Directory.AccessAsUser.All, which Agent Identity APIs explicitly reject (403). You MUST use a dedicated app registration with client_credentials flow or connect via Connect-MgGraph with explicit delegated scopes.

PowerShell (delegated permissions)

Connect-MgGraph -Scopes @(
    "AgentIdentityBlueprint.Create",
    "AgentIdentityBlueprint.ReadWrite.All",
    "AgentIdentityBlueprintPrincipal.Create",
    "User.Read"
)
Set-MgRequestContext -ApiVersion beta

$currentUser = (Get-MgContext).Account
$userId = (Get-MgUser -UserId $currentUser).Id

Python (application permissions)

import os
import requests
from azure.identity import ClientSecretCredential

credential = ClientSecretCredential(
    tenant_id=os.environ["AZURE_TENANT_ID"],
    client_id=os.environ["AZURE_CLIENT_ID"],
    client_secret=os.environ["AZURE_CLIENT_SECRET"],
)
token = credential.get_token("https://graph.microsoft.com/.default")

GRAPH = "https://graph.microsoft.com/beta"
headers = {
    "Authorization": f"Bearer {token.token}",
    "Content-Type": "application/json",
    "OData-Version": "4.0",  # Required for all Agent Identity API calls
}

Core Workflow

Step 1: Create Agent Identity Blueprint

Sponsors are required and must be User objects — ServicePrincipals and Groups are rejected.

import subprocess

# Get sponsor user ID (client_credentials has no user context, so use az CLI)
result = subprocess.run(
    ["az", "ad", "signed-in-user", "show", "--query", "id", "-o", "tsv"],
    capture_output=True, text=True, check=True,
)
user_id = result.stdout.strip()

blueprint_body = {
    "@odata.type": "Microsoft.Graph.AgentIdentityBlueprint",
    "displayName": "My Agent Blueprint",
    "sponsors@odata.bind": [
        f"https://graph.microsoft.com/beta/users/{user_id}"
    ],
}
resp = requests.post(f"{GRAPH}/applications", headers=headers, json=blueprint_body)
resp.raise_for_status()

blueprint = resp.json()
app_id = blueprint["appId"]
blueprint_obj_id = blueprint["id"]

Step 2: Create BlueprintPrincipal

This step is mandatory. Creating a Blueprint does NOT auto-create its service principal. Without this, Agent Identity creation fails with: 400: The Agent Blueprint Principal for the Agent Blueprint does not exist.

sp_body = {
    "@odata.type": "Microsoft.Graph.AgentIdentityBlueprintPrincipal",
    "appId": app_id,
}
resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=sp_body)
resp.raise_for_status()

If implementing idempotent scripts, check for and create the BlueprintPrincipal even when the Blueprint already exists (a previous run may have created the Blueprint but crashed before creating the SP).

Step 3: Create Agent Identities

agent_body = {
    "@odata.type": "Microsoft.Graph.AgentIdentity",
    "displayName": "my-agent-instance-1",
    "agentIdentityBlueprintId": app_id,
    "sponsors@odata.bind": [
        f"https://graph.microsoft.com/beta/users/{user_id}"
    ],
}
resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=agent_body)
resp.raise_for_status()
agent = resp.json()

API Reference

Operation Method Endpoint OData Type
Create Blueprint POST /applications Microsoft.Graph.AgentIdentityBlueprint
Create BlueprintPrincipal POST /servicePrincipals Microsoft.Graph.AgentIdentityBlueprintPrincipal
Create Agent Identity POST /servicePrincipals Microsoft.Graph.AgentIdentity
List Agent Identities GET /servicePrincipals?$filter=... —
Delete Agent Identity DELETE /servicePrincipals/{id} —
Delete Blueprint DELETE /applications/{id} —

All endpoints use base URL: https://graph.microsoft.com/beta

Required Permissions

Permission Purpose
Application.ReadWrite.All Blueprint CRUD (application objects)
AgentIdentityBlueprint.Create Create new Blueprints
AgentIdentityBlueprint.ReadWrite.All Read/update Blueprints
AgentIdentityBlueprintPrincipal.Create Create BlueprintPrincipals
AgentIdentity.Create.All Create Agent Identities
AgentIdentity.ReadWrite.All Read/update Agent Identities

There are 18 Agent Identity-specific Graph application permissions. Discover all:

az ad sp show --id 00000003-0000-0000-c000-000000000000 \
  --query "appRoles[?contains(value, 'AgentIdentity')].{id:id, value:value}" -o json

Grant admin consent (required for application permissions):

az ad app permission admin-consent --id <client-id>

Admin consent may fail with 404 if the service principal hasn't replicated. Retry with 10–40s backoff.

Cleanup

# Delete Agent Identity
requests.delete(f"{GRAPH}/servicePrincipals/{agent['id']}", headers=headers)

# Delete BlueprintPrincipal (get SP ID first)
sps = requests.get(
    f"{GRAPH}/servicePrincipals?$filter=appId eq '{app_id}'",
    headers=headers,
).json()
for sp in sps.get("value", []):
    requests.delete(f"{GRAPH}/servicePrincipals/{sp['id']}", headers=headers)

# Delete Blueprint
requests.delete(f"{GRAPH}/applications/{blueprint_obj_id}", headers=headers)

Best Practices

  1. Always create BlueprintPrincipal after Blueprint — not auto-created; implement idempotent checks on both
  2. Use User objects as sponsors — ServicePrincipals and Groups are rejected
  3. Handle permission propagation delays — after admin consent, wait 30–120s; retry with backoff on 403
  4. Include OData-Version: 4.0 header on every Graph request
  5. Use Workload Identity Federation for production auth — for local dev, use a client secret on the Blueprint (see references/oauth2-token-flow.md)
  6. Set identifierUris on Blueprint before using OAuth2 scoping (api://{app-id})
  7. Never use Azure CLI tokens for API calls — they contain Directory.AccessAsUser.All which is hard-rejected
  8. Check for existing resources before creating — implement idempotent provisioning

References

File Contents
references/oauth2-token-flow.md Production (Managed Identity + WIF) and local dev (client secret) token flows
references/known-limitations.md 29 known issues organized by category (from official preview known-issues page)
references/sdk-sidecar.md Microsoft Entra SDK for AgentID — endpoints, 3P agent patterns, Docker/K8s deployment, security

External Links

Resource URL
Official Setup Guide https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-setup-instructions
AI-Guided Setup https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-ai-guided-setup
Microsoft Entra SDK for AgentID — Overview https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/overview
Microsoft Entra SDK for AgentID — Endpoints https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints
Files (skills)
  • references
    • known-limitations.md 4.8 KB
      # Known Limitations (Preview)
      
      Source: [Microsoft Entra Agent ID preview: Known issues and gaps](https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/preview-known-issues)
      
      ## API & Object Model
      
      1. **Preview API only** — all endpoints are under `/beta`, not `/v1.0`
      2. **Sponsors must be Users** — ServicePrincipals and Groups are not accepted as sponsors
      3. **BlueprintPrincipal not auto-created** — requires explicit `POST /servicePrincipals` after Blueprint creation
      4. **Agent Identities cannot have password credentials** — credentials belong on the Blueprint only (`PropertyNotCompatibleWithAgentIdentity` error)
      5. **Agent Identities have no backing application object** — they are service-principal-only entities
      6. **Blueprint needs explicit `identifierUris`** — not set by default, required for OAuth2 scope resolution (`api://{app-id}/.default`)
      7. **No Graph relationship filtering for Agent IDs** — `/ownedObjects`, `/deletedItems`, `/owners` etc. return all types; must client-side filter by `odata.type`
      8. **Orphaned agent users after deletion** — deleting a blueprint or identity does NOT auto-delete its agent users; clean up manually via admin center or Graph API
      
      ## Roles & Permissions
      
      9. **`Directory.AccessAsUser.All` hard rejection** — if present on the client, all other Agent ID delegated permissions are ignored → 403 Forbidden
      10. **No viable delegated permission for creating agent identities** — must use application permissions
      11. **No quick-start permission bundle** — must discover and grant 18+ individual Agent Identity permissions
      12. **Permission propagation delay** — 30–120+ seconds after admin consent before tokens include new claims; use delegated permissions where possible and add retry with exponential backoff
      13. **Global Reader cannot list agent identities** — `GET /servicePrincipals/graph.agentIdentity` returns 403; use `GET /servicePrincipals` instead
      14. **Custom roles cannot include Agent ID actions** — use built-in roles (Agent ID Administrator, Agent ID Developer)
      15. **Administrative units not supported** — cannot add agent identities, blueprints, or blueprint principals to admin units; use `owners` property instead
      16. **Agent ID Admin cannot update agent user photos** — use User Administrator role
      
      ## Admin Center & Management
      
      17. **No blueprint management in Entra admin center** — must use Microsoft Graph APIs / PowerShell to create and edit blueprints
      18. **`/me` endpoint unavailable** in `client_credentials` flow — use `az ad signed-in-user show` or Graph delegated permissions for user context
      
      ## Authentication & Consent
      
      19. **No SSO to web apps** — Agent IDs cannot sign in via Microsoft Entra ID sign-in pages (no OpenID Connect or SAML); use web APIs instead
      20. **Admin consent workflow (ACW) broken** — does not work properly for permissions requested by Agent IDs; contact tenant admin directly
      21. **Cannot grant app permissions to blueprint principals** — grant application permissions to individual agent identities instead
      22. **Cannot assign app roles where target resource is an agent identity** — use blueprint principal as the target resource
      23. **Risk-based step-up blocks consent silently** — no "risky" indication in the UX
      
      ## Groups, Logs & Monitoring
      
      24. **No dynamic group membership** — agent identities and agent users cannot be added to dynamic groups; use security groups with fixed membership
      25. **Audit logs do not distinguish Agent IDs** — operations on blueprints/identities logged as `ApplicationManagement`, agent users as `User Management`; cross-reference object IDs via Graph to determine entity type
      26. **Graph activity logs do not distinguish Agent IDs** — agent identity requests logged as applications, agent user requests as users; join with sign-in logs
      
      ## Performance & Scale
      
      27. **Sequential creation requests may fail** — creating multiple entities in quick succession (e.g., blueprint → principal → identity) can return `400 Bad Request: Object with id {id} not found`; especially with application permissions. Use delegated permissions where possible and add exponential backoff retry.
      
      ## Product Integrations
      
      28. **Copilot Studio** — only custom engine agents are supported; Agent IDs are used for channel auth only (not connectors or tools)
      29. **MSAL complexity** — Agent ID scenarios require managing Federated Identity Credentials manually. For .NET use [Microsoft.Identity.Web.AgentIdentities](https://github.com/AzureAD/microsoft-identity-web/blob/master/src/Microsoft.Identity.Web.AgentIdentities/README.AgentIdentities.md). For other languages use the [Microsoft Entra SDK for Agent ID](https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/overview).
      
      ## Reporting Issues
      
      Report unlisted issues via [aka.ms/agentidfeedback](https://aka.ms/agentidfeedback).
      
    • oauth2-token-flow.md 4.9 KB
      # OAuth2 Token Flow
      
      Source: [Agent ID Setup Instructions](https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-setup-instructions)
      
      Agent Identities authenticate at runtime using credentials configured on the **Blueprint** (not the Agent Identity itself). Two options are available:
      
      | Option | Use case | Credential type |
      |--------|----------|-----------------|
      | **Managed Identity + WIF** | Production (Azure-hosted) | Federated Identity Credential |
      | **Client secret** | Local development / testing | Password credential on Blueprint |
      
      ---
      
      ## Option A: Managed Identity + Workload Identity Federation (Production)
      
      ### Architecture
      
      ```
      Container App (user-assigned MI)
        -> ManagedIdentityCredential.get_token("api://{blueprint-app-id}/.default")
          -> Azure AD token exchange (MI token -> Agent ID token)
            -> JWT with oid = MI principal, aud = api://{blueprint-app-id}
              -> Backend validates JWT signature + claims
      ```
      
      ### 1. Set Application ID URI on Blueprint
      
      Required for OAuth2 scope resolution:
      
      ```python
      requests.patch(
          f"{GRAPH}/applications/{blueprint_obj_id}",
          headers=headers,
          json={"identifierUris": [f"api://{app_id}"]},
      )
      ```
      
      ### 2. Create Federated Identity Credential
      
      Create on the Blueprint (not the Agent Identity):
      
      ```python
      fic_body = {
          "name": "my-fic-name",
          "issuer": f"https://login.microsoftonline.com/{tenant_id}/v2.0",
          "subject": "{mi-principal-id}",  # The MI's object ID (principalId), NOT client ID
          "audiences": ["api://AzureADTokenExchange"],
      }
      requests.post(
          f"{GRAPH}/applications/{blueprint_obj_id}/microsoft.graph.agentIdentityBlueprint/federatedIdentityCredentials",
          headers=headers,
          json=fic_body,
      )
      ```
      
      ### 3. Acquire Token (Caller Side)
      
      ```python
      from azure.identity import ManagedIdentityCredential
      
      cred = ManagedIdentityCredential(client_id=mi_client_id)
      token = cred.get_token(f"api://{blueprint_app_id}/.default")
      # Include in requests: Authorization: Bearer {token.token}
      ```
      
      ### 4. Validate Token (Backend)
      
      ```python
      import jwt
      from jwt import PyJWKClient
      
      jwks_uri = f"https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys"
      jwks_client = PyJWKClient(jwks_uri)
      signing_key = jwks_client.get_signing_key_from_jwt(token_str)
      
      claims = jwt.decode(
          token_str,
          signing_key.key,
          algorithms=["RS256"],
          audience=f"api://{blueprint_app_id}",
          issuer=f"https://sts.windows.net/{tenant_id}/",
      )
      ```
      
      ### Key Rules (WIF)
      
      - **Federated credentials go on the Blueprint**, not the Agent Identity SP. Use the `.../microsoft.graph.agentIdentityBlueprint/federatedIdentityCredentials` path.
      - **`subject` is the MI's principalId (object ID)**, not its client ID.
      - **`audiences` must be `["api://AzureADTokenExchange"]`**, not your API audience.
      - **Issuer format**: `https://login.microsoftonline.com/{tenant}/v2.0`
      - **Token issuer** (for validation): `https://sts.windows.net/{tenant}/` (note the trailing slash and different domain)
      
      ---
      
      ## Option B: Client Secret (Local Development / Testing Only)
      
      For local development where no Managed Identity is available.
      
      ### 1. Add a Password Credential to the Blueprint
      
      Via PowerShell:
      
      ```powershell
      $secretBody = @{
          "passwordCredential" = @{
              "displayName" = "Dev Secret"
              "endDateTime" = "2027-01-01T00:00:00Z"
          }
      }
      
      $credential = Invoke-MgGraphRequest -Method POST `
          -Uri "https://graph.microsoft.com/beta/applications/<BLUEPRINT_OBJECT_ID>/addPassword" `
          -Headers @{"OData-Version"="4.0"; "Content-Type"="application/json"} `
          -Body ($secretBody | ConvertTo-Json -Depth 5) -OutputType PSObject
      
      $credential.secretText  # Save NOW — cannot be retrieved later
      ```
      
      Or via Python (with an existing token):
      
      ```python
      secret_body = {
          "passwordCredential": {
              "displayName": "Dev Secret",
              "endDateTime": "2027-01-01T00:00:00Z",
          }
      }
      resp = requests.post(
          f"{GRAPH}/applications/{blueprint_obj_id}/addPassword",
          headers=headers,
          json=secret_body,
      )
      secret_text = resp.json()["secretText"]  # Save NOW
      ```
      
      ### 2. Acquire Token Locally
      
      ```python
      from azure.identity import ClientSecretCredential
      
      credential = ClientSecretCredential(
          tenant_id=TENANT_ID,
          client_id=BLUEPRINT_APP_ID,       # Blueprint's appId
          client_secret=SECRET_TEXT,         # From step 1
      )
      token = credential.get_token(f"api://{BLUEPRINT_APP_ID}/.default")
      ```
      
      ### Key Rules (Client Secret)
      
      - **Save `secretText` immediately** — it cannot be retrieved after creation.
      - **Secrets belong on the Blueprint only** — agent identities cannot have password credentials (`PropertyNotCompatibleWithAgentIdentity`).
      - **NOT for production** — use Managed Identity + WIF in production.
      - **Respect org policy** — if `endDateTime` exceeds your tenant's credential lifetime policy, reduce it.
      - **Use `ClientSecretCredential`**, not `DefaultAzureCredential`. Azure CLI tokens contain `Directory.AccessAsUser.All` which is rejected by Agent ID APIs.
      
    • sdk-sidecar.md 13 KB
      # Microsoft Entra SDK for AgentID: Polyglot Agent Authentication
      
      Containerized companion service that handles token management for AI agents via HTTP — any language, any framework.
      
      > **Preview** — Image: `mcr.microsoft.com/entra-sdk/auth-sidecar:<tag>`. Check [GitHub releases](https://github.com/AzureAD/microsoft-identity-web/releases) for tags.
      
      ## Architecture
      
      ```
      Client App → Your Agent (Python/Node/Go/Java) → Microsoft Entra SDK for AgentID (localhost:5000) → Microsoft Entra ID
                                                                          ↓
                                                                    Downstream APIs
      ```
      
      The Microsoft Entra SDK for AgentID runs as a companion container in the same pod or Docker network. Your agent calls it over HTTP — no SDK embedding required.
      
      ### Agent Integration (3P and Custom Agents)
      
      Third-party and custom agents authenticate using the Blueprint → BlueprintPrincipal → AgentIdentity hierarchy. The Microsoft Entra SDK for AgentID acquires tokens for these agent identities — whether you are building your own custom agent or integrating a third-party agent:
      
      ```
                              GET /AuthorizationHeaderUnauthenticated/graph
                                    ?AgentIdentity={agent-app-id}
      ┌──────────────────┐   ─────────────────────────────────▶  ┌─────────────────────────────┐
      │  Agent           │                                       │  Microsoft Entra SDK        │
      │  (any language)  │   ◀─────────────────────────────────  │  for AgentID (:5000)        │
      │                  │    { authorizationHeader:             │                             │
      └────────┬─────────┘      "Bearer eyJ..." }                │  · AzureAd Config (Tenant,  │
               │                                                 │    ClientId, FIC)           │
               │                                                 │  · Agent Identity Params    │
               │                                                 │  · Downstream API Scopes    │
               │                                                 │  · Token Cache              │
               │                                                 └──────────────┬──────────────┘
               │                                                                │
               │ Authorization: Bearer <JWT>                                    │ OAuth 2.0
               ▼                                                                ▼
      ┌──────────────────────┐                                   ┌──────────────────────────┐
      │  Downstream APIs     │                                   │  Microsoft Entra ID      │
      │  · Microsoft Graph   │                                   │  · Blueprint             │
      │  · Custom APIs       │                                   │  · AgentIdentity         │
      │  · Azure Services    │                                   │                          │
      └──────────────────────┘                                   └──────────────────────────┘
      ```
      
      ## Microsoft Entra SDK for AgentID Configuration
      
      ### Core Settings
      
      ```yaml
      env:
      - name: AzureAd__Instance
        value: "https://login.microsoftonline.com/"
      - name: AzureAd__TenantId
        value: "<your-tenant-id>"
      - name: AzureAd__ClientId
        value: "<blueprint-app-id>"
      ```
      
      ### Client Credentials
      
      > **⚠️ Client secrets are for development only.** Production deployments must use Federated Identity Credentials (FIC) via Workload Identity (`SignedAssertionFilePath`) or Managed Identity.
      
      ```yaml
      # Dev ONLY: Client Secret (do NOT use in production)
      - name: AzureAd__ClientCredentials__0__SourceType
        value: "ClientSecret"
      - name: AzureAd__ClientCredentials__0__ClientSecret
        value: "<secret>"
      
      # Prod (AKS): Federated Identity Credentials via Workload Identity — RECOMMENDED
      - name: AzureAd__ClientCredentials__0__SourceType
        value: "SignedAssertionFilePath"
      
      # Prod (VM/App Service): Managed Identity
      - name: AzureAd__ClientCredentials__0__SourceType
        value: "SignedAssertionFromManagedIdentity"
      - name: AzureAd__ClientCredentials__0__ManagedIdentityClientId
        value: "<managed-identity-client-id>"
      ```
      
      ### Downstream API
      
      ```yaml
      - name: DownstreamApis__Graph__BaseUrl
        value: "https://graph.microsoft.com/v1.0/"
      - name: DownstreamApis__Graph__Scopes__0
        value: "https://graph.microsoft.com/.default"
      - name: DownstreamApis__Graph__RequestAppToken
        value: "true"
      ```
      
      ## Endpoint Reference
      
      | Endpoint | Method | Auth Required | Purpose |
      |----------|--------|---------------|---------|
      | `/Validate` | GET | Yes | Validate inbound bearer token, return claims |
      | `/AuthorizationHeader/{name}` | GET | Yes | Validate inbound token + acquire downstream token (OBO) |
      | `/AuthorizationHeaderUnauthenticated/{name}` | GET | No | Acquire app/agent token without inbound user token |
      | `/DownstreamApi/{name}` | ANY | Yes | Validate + call downstream API with auto token |
      | `/DownstreamApiUnauthenticated/{name}` | ANY | No | Call downstream API with app/agent token |
      | `/healthz` | GET | No | Health probe |
      
      ### Agent Identity Query Parameters
      
      | Parameter | Purpose | Example |
      |-----------|---------|---------|
      | `AgentIdentity` | Agent app (client) ID — autonomous mode | `?AgentIdentity=<agent-client-id>` |
      | `AgentIdentity` + `AgentUsername` | Interactive mode by UPN | `?AgentIdentity=<id>&AgentUsername=user@contoso.com` |
      | `AgentIdentity` + `AgentUserId` | Interactive mode by Object ID | `?AgentIdentity=<id>&AgentUserId=<oid>` |
      
      Rules:
      - `AgentUsername`/`AgentUserId` require `AgentIdentity`
      - `AgentUsername` and `AgentUserId` are mutually exclusive
      - `AgentIdentity` alone = autonomous agent
      - `AgentIdentity` + inbound bearer = interactive (OBO) agent
      
      ## Code Patterns
      
      ### Autonomous 3P Agent (Python)
      
      ```python
      import os
      import requests
      
      SIDECAR_URL = os.environ.get("SIDECAR_URL", "http://localhost:5000")
      AGENT_APP_ID = os.environ["AGENT_CLIENT_ID"]
      
      def get_agent_token(downstream_api: str = "Graph") -> str:
          """Acquire autonomous agent token via Microsoft Entra SDK for AgentID."""
          url = f"{SIDECAR_URL}/AuthorizationHeaderUnauthenticated/{downstream_api}"
          resp = requests.get(url, params={"AgentIdentity": AGENT_APP_ID}, timeout=30)
          resp.raise_for_status()
          return resp.json()["authorizationHeader"]
      
      def call_downstream_api(endpoint: str) -> dict:
          """Call a downstream API using agent identity token."""
          token = get_agent_token()
          resp = requests.get(endpoint, headers={"Authorization": token}, timeout=10)
          resp.raise_for_status()
          return resp.json()
      ```
      
      ### Interactive Agent with User Delegation (Python)
      
      ```python
      def get_delegated_token(user_token: str, downstream_api: str = "Graph") -> str:
          """Acquire delegated token via OBO flow."""
          url = f"{SIDECAR_URL}/AuthorizationHeader/{downstream_api}"
          resp = requests.get(
              url,
              headers={"Authorization": f"Bearer {user_token}"},
              timeout=30,
          )
          resp.raise_for_status()
          return resp.json()["authorizationHeader"]
      ```
      
      ### Autonomous Agent (TypeScript)
      
      ```typescript
      const SIDECAR_URL = process.env.SIDECAR_URL ?? "http://localhost:5000";
      const AGENT_APP_ID = process.env.AGENT_CLIENT_ID!;
      
      async function getAgentToken(downstreamApi = "Graph"): Promise<string> {
        const url = `${SIDECAR_URL}/AuthorizationHeaderUnauthenticated/${downstreamApi}`;
        const res = await fetch(url + `?AgentIdentity=${AGENT_APP_ID}`);
        if (!res.ok) throw new Error(`Microsoft Entra SDK for AgentID error: ${res.status}`);
        const data = await res.json();
        return data.authorizationHeader;
      }
      ```
      
      ### Token Validation Middleware
      
      ```python
      def validate_incoming_token(bearer_token: str) -> dict:
          """Validate an incoming bearer token and extract claims."""
          resp = requests.get(
              f"{SIDECAR_URL}/Validate",
              headers={"Authorization": f"Bearer {bearer_token}"},
              timeout=10,
          )
          resp.raise_for_status()
          return resp.json()["claims"]
      ```
      
      ### Direct Downstream Call via Microsoft Entra SDK for AgentID
      
      ```python
      def call_graph_me(user_token: str) -> dict:
          """Call Microsoft Graph /me via Microsoft Entra SDK for AgentID proxy."""
          resp = requests.get(
              f"{SIDECAR_URL}/DownstreamApi/Graph",
              params={"optionsOverride.RelativePath": "me"},
              headers={"Authorization": f"Bearer {user_token}"},
              timeout=10,
          )
          resp.raise_for_status()
          return resp.json()["content"]
      ```
      
      ## Deployment
      
      ### Docker Compose (Development)
      
      ```yaml
      version: '3.8'
      services:
        sidecar:
          image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0-azurelinux3.0-distroless
          ports:
            - "5001:5000"
          environment:
            - AzureAd__Instance=https://login.microsoftonline.com/
            - AzureAd__TenantId=${TENANT_ID}
            - AzureAd__ClientId=${BLUEPRINT_APP_ID}
            - AzureAd__ClientCredentials__0__SourceType=ClientSecret
            - AzureAd__ClientCredentials__0__ClientSecret=${BLUEPRINT_CLIENT_SECRET}
            - DownstreamApis__Graph__BaseUrl=https://graph.microsoft.com/v1.0/
            - DownstreamApis__Graph__Scopes__0=https://graph.microsoft.com/.default
            - DownstreamApis__Graph__RequestAppToken=true
            - ASPNETCORE_URLS=http://+:5000
      
        agent:
          build: ./agent
          ports:
            - "3000:3000"
          environment:
            - SIDECAR_URL=http://sidecar:5000
            - AGENT_CLIENT_ID=${AGENT_CLIENT_ID}
          depends_on:
            - sidecar
      ```
      
      ### Kubernetes (Production)
      
      ```yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: agent-deployment
      spec:
        replicas: 3
        template:
          metadata:
            labels:
              app: agent
              azure.workload.identity/use: "true"
          spec:
            serviceAccountName: agent-sa
            containers:
            - name: agent
              image: myregistry/agent:latest
              env:
              - name: SIDECAR_URL
                value: "http://localhost:5000"
            - name: sidecar
              image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0
              ports:
              - containerPort: 5000
              env:
              - name: AzureAd__TenantId
                valueFrom:
                  configMapKeyRef:
                    name: agent-config
                    key: tenant-id
              - name: AzureAd__ClientId
                valueFrom:
                  configMapKeyRef:
                    name: agent-config
                    key: client-id
              - name: AzureAd__ClientCredentials__0__SourceType
                value: "SignedAssertionFilePath"
              - name: Kestrel__Endpoints__Http__Url
                value: "http://127.0.0.1:5000"
              resources:
                requests: { memory: "128Mi", cpu: "100m" }
                limits: { memory: "256Mi", cpu: "250m" }
              livenessProbe:
                httpGet: { path: /healthz, port: 5000 }
                initialDelaySeconds: 10
              readinessProbe:
                httpGet: { path: /healthz, port: 5000 }
                initialDelaySeconds: 5
      ```
      
      ## Security
      
      > **⚠️ The Microsoft Entra SDK for AgentID API must NOT be publicly accessible.** Pod-local or same Docker network only.
      
      1. **Bind to localhost** — `Kestrel__Endpoints__Http__Url=http://127.0.0.1:5000`
      2. **Never expose via LoadBalancer/Ingress**
      3. **Use Workload Identity in AKS** — `SignedAssertionFilePath` over client secrets
      4. **Use Key Vault for certificates** — `SourceType=KeyVault` in production
      5. **Separate ConfigMap from Secrets** in Kubernetes
      
      ## Troubleshooting
      
      | Symptom | Cause | Fix |
      |---------|-------|-----|
      | 404 on `/AuthorizationHeader/{name}` | `{name}` not in config | Add `DownstreamApis__{name}__BaseUrl` env var |
      | 400 `AgentUsername requires AgentIdentity` | Missing `AgentIdentity` param | Always pair user params with `AgentIdentity` |
      | 400 `mutually exclusive` | Both `AgentUsername` and `AgentUserId` | Use one or the other |
      | 401 on `/Validate` | Invalid/expired inbound token | Check token audience matches `AzureAd__ClientId` |
      | 500 token acquisition failure | Wrong creds or missing admin consent | `kubectl logs <pod> -c sidecar` |
      | Connection refused | SDK not ready or wrong URL | Verify `SIDECAR_URL` and `/healthz` |
      
      ## External Links
      
      | Resource | URL |
      |----------|-----|
      | SDK Overview | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/overview |
      | Installation | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/installation |
      | Configuration | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/configuration |
      | Endpoints | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints |
      | Agent Identities | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/agent-identities |
      | Security | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/security |
      | OpenAPI Spec | https://github.com/AzureAD/microsoft-identity-web/blob/master/src/Microsoft.Identity.Web.Sidecar/OpenAPI/Microsoft.Identity.Web.AgentID.json |
      
  • SKILL.md 9.2 KB
    ---
    name: entra-agent-id
    description: |
      Microsoft Entra Agent ID (preview) for creating OAuth2-capable AI agent identities via Microsoft Graph beta API.
      Covers Agent Identity Blueprints, BlueprintPrincipals, Agent Identities, required permissions, sponsors, and Workload Identity Federation.
      Includes Microsoft Entra SDK for AgentID (containerized sidecar) for polyglot agent authentication (Docker/Kubernetes), 3P agent integration, autonomous and interactive agent patterns.
      Triggers: "agent identity", "agent id", "Agent Identity Blueprint", "BlueprintPrincipal", "entra agent", "agent identity provisioning", "Graph agent identity", "entra sidecar", "agent id sidecar", "auth sidecar", "3P agent", "third-party agent identity", "polyglot agent auth".
    ---
    
    # Microsoft Entra Agent ID
    
    Create and manage OAuth2-capable identities for AI agents using Microsoft Graph beta API.
    
    > **Preview API** — All Agent Identity endpoints are under `/beta` only. Not available in `/v1.0`.
    
    ## Before You Start
    
    Search `microsoft-docs` MCP for the latest Agent ID documentation:
    - Query: "Microsoft Entra agent identity setup"
    - Verify: API parameters match current preview behavior
    
    ## Conceptual Model
    
    ```
    Agent Identity Blueprint (application)        ← one per agent type/project
      └── BlueprintPrincipal (service principal)   ← MUST be created explicitly
            ├── Agent Identity (SP): agent-1       ← one per agent instance
            ├── Agent Identity (SP): agent-2
            └── Agent Identity (SP): agent-3
    ```
    
    ## Prerequisites
    
    ### PowerShell (recommended for interactive setup)
    
    ```powershell
    # Requires PowerShell 7+
    Install-Module Microsoft.Graph.Beta.Applications -Scope CurrentUser -Force
    ```
    
    ### Python (for programmatic provisioning)
    
    ```bash
    pip install azure-identity requests
    ```
    
    ### Required Entra Roles
    
    One of: **Agent Identity Developer**, **Agent Identity Administrator**, or **Application Administrator**.
    
    ## Environment Variables
    
    ```bash
    AZURE_TENANT_ID=<your-tenant-id>
    AZURE_CLIENT_ID=<app-registration-client-id>
    AZURE_CLIENT_SECRET=<app-registration-secret>
    ```
    
    ## Authentication
    
    > **⚠️ `DefaultAzureCredential` is NOT supported.** Azure CLI tokens contain
    > `Directory.AccessAsUser.All`, which Agent Identity APIs explicitly reject (403).
    > You MUST use a dedicated app registration with `client_credentials` flow or
    > connect via `Connect-MgGraph` with explicit delegated scopes.
    
    ### PowerShell (delegated permissions)
    
    ```powershell
    Connect-MgGraph -Scopes @(
        "AgentIdentityBlueprint.Create",
        "AgentIdentityBlueprint.ReadWrite.All",
        "AgentIdentityBlueprintPrincipal.Create",
        "User.Read"
    )
    Set-MgRequestContext -ApiVersion beta
    
    $currentUser = (Get-MgContext).Account
    $userId = (Get-MgUser -UserId $currentUser).Id
    ```
    
    ### Python (application permissions)
    
    ```python
    import os
    import requests
    from azure.identity import ClientSecretCredential
    
    credential = ClientSecretCredential(
        tenant_id=os.environ["AZURE_TENANT_ID"],
        client_id=os.environ["AZURE_CLIENT_ID"],
        client_secret=os.environ["AZURE_CLIENT_SECRET"],
    )
    token = credential.get_token("https://graph.microsoft.com/.default")
    
    GRAPH = "https://graph.microsoft.com/beta"
    headers = {
        "Authorization": f"Bearer {token.token}",
        "Content-Type": "application/json",
        "OData-Version": "4.0",  # Required for all Agent Identity API calls
    }
    ```
    
    ## Core Workflow
    
    ### Step 1: Create Agent Identity Blueprint
    
    Sponsors are required and **must be User objects** — ServicePrincipals and Groups are rejected.
    
    ```python
    import subprocess
    
    # Get sponsor user ID (client_credentials has no user context, so use az CLI)
    result = subprocess.run(
        ["az", "ad", "signed-in-user", "show", "--query", "id", "-o", "tsv"],
        capture_output=True, text=True, check=True,
    )
    user_id = result.stdout.strip()
    
    blueprint_body = {
        "@odata.type": "Microsoft.Graph.AgentIdentityBlueprint",
        "displayName": "My Agent Blueprint",
        "sponsors@odata.bind": [
            f"https://graph.microsoft.com/beta/users/{user_id}"
        ],
    }
    resp = requests.post(f"{GRAPH}/applications", headers=headers, json=blueprint_body)
    resp.raise_for_status()
    
    blueprint = resp.json()
    app_id = blueprint["appId"]
    blueprint_obj_id = blueprint["id"]
    ```
    
    ### Step 2: Create BlueprintPrincipal
    
    > **This step is mandatory.** Creating a Blueprint does NOT auto-create its
    > service principal. Without this, Agent Identity creation fails with:
    > `400: The Agent Blueprint Principal for the Agent Blueprint does not exist.`
    
    ```python
    sp_body = {
        "@odata.type": "Microsoft.Graph.AgentIdentityBlueprintPrincipal",
        "appId": app_id,
    }
    resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=sp_body)
    resp.raise_for_status()
    ```
    
    If implementing idempotent scripts, check for and create the BlueprintPrincipal
    even when the Blueprint already exists (a previous run may have created the Blueprint
    but crashed before creating the SP).
    
    ### Step 3: Create Agent Identities
    
    ```python
    agent_body = {
        "@odata.type": "Microsoft.Graph.AgentIdentity",
        "displayName": "my-agent-instance-1",
        "agentIdentityBlueprintId": app_id,
        "sponsors@odata.bind": [
            f"https://graph.microsoft.com/beta/users/{user_id}"
        ],
    }
    resp = requests.post(f"{GRAPH}/servicePrincipals", headers=headers, json=agent_body)
    resp.raise_for_status()
    agent = resp.json()
    ```
    
    ## API Reference
    
    | Operation | Method | Endpoint | OData Type |
    |-----------|--------|----------|------------|
    | Create Blueprint | `POST` | `/applications` | `Microsoft.Graph.AgentIdentityBlueprint` |
    | Create BlueprintPrincipal | `POST` | `/servicePrincipals` | `Microsoft.Graph.AgentIdentityBlueprintPrincipal` |
    | Create Agent Identity | `POST` | `/servicePrincipals` | `Microsoft.Graph.AgentIdentity` |
    | List Agent Identities | `GET` | `/servicePrincipals?$filter=...` | — |
    | Delete Agent Identity | `DELETE` | `/servicePrincipals/{id}` | — |
    | Delete Blueprint | `DELETE` | `/applications/{id}` | — |
    
    All endpoints use base URL: `https://graph.microsoft.com/beta`
    
    ## Required Permissions
    
    | Permission | Purpose |
    |-----------|---------|
    | `Application.ReadWrite.All` | Blueprint CRUD (application objects) |
    | `AgentIdentityBlueprint.Create` | Create new Blueprints |
    | `AgentIdentityBlueprint.ReadWrite.All` | Read/update Blueprints |
    | `AgentIdentityBlueprintPrincipal.Create` | Create BlueprintPrincipals |
    | `AgentIdentity.Create.All` | Create Agent Identities |
    | `AgentIdentity.ReadWrite.All` | Read/update Agent Identities |
    
    There are **18 Agent Identity-specific** Graph application permissions. Discover all:
    ```bash
    az ad sp show --id 00000003-0000-0000-c000-000000000000 \
      --query "appRoles[?contains(value, 'AgentIdentity')].{id:id, value:value}" -o json
    ```
    
    Grant admin consent (required for application permissions):
    ```bash
    az ad app permission admin-consent --id <client-id>
    ```
    
    > Admin consent may fail with 404 if the service principal hasn't replicated. Retry with 10–40s backoff.
    
    ## Cleanup
    
    ```python
    # Delete Agent Identity
    requests.delete(f"{GRAPH}/servicePrincipals/{agent['id']}", headers=headers)
    
    # Delete BlueprintPrincipal (get SP ID first)
    sps = requests.get(
        f"{GRAPH}/servicePrincipals?$filter=appId eq '{app_id}'",
        headers=headers,
    ).json()
    for sp in sps.get("value", []):
        requests.delete(f"{GRAPH}/servicePrincipals/{sp['id']}", headers=headers)
    
    # Delete Blueprint
    requests.delete(f"{GRAPH}/applications/{blueprint_obj_id}", headers=headers)
    ```
    
    ## Best Practices
    
    1. **Always create BlueprintPrincipal after Blueprint** — not auto-created; implement idempotent checks on both
    2. **Use User objects as sponsors** — ServicePrincipals and Groups are rejected
    3. **Handle permission propagation delays** — after admin consent, wait 30–120s; retry with backoff on 403
    4. **Include `OData-Version: 4.0` header** on every Graph request
    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))
    6. **Set `identifierUris` on Blueprint** before using OAuth2 scoping (`api://{app-id}`)
    7. **Never use Azure CLI tokens** for API calls — they contain `Directory.AccessAsUser.All` which is hard-rejected
    8. **Check for existing resources** before creating — implement idempotent provisioning
    
    ## References
    
    | File | Contents |
    |------|----------|
    | [references/oauth2-token-flow.md](references/oauth2-token-flow.md) | Production (Managed Identity + WIF) and local dev (client secret) token flows |
    | [references/known-limitations.md](references/known-limitations.md) | 29 known issues organized by category (from official preview known-issues page) |
    | [references/sdk-sidecar.md](references/sdk-sidecar.md) | Microsoft Entra SDK for AgentID — endpoints, 3P agent patterns, Docker/K8s deployment, security |
    
    ### External Links
    
    | Resource | URL |
    |----------|-----|
    | Official Setup Guide | https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-setup-instructions |
    | AI-Guided Setup | https://learn.microsoft.com/en-us/entra/agent-id/identity-platform/agent-id-ai-guided-setup |
    | Microsoft Entra SDK for AgentID — Overview | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/overview |
    | Microsoft Entra SDK for AgentID — Endpoints | https://learn.microsoft.com/en-us/entra/msidweb/agent-id-sdk/endpoints |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related