All skills
microsoft avatar

/entra-agent-id

@b3c238e
by microsoftmicrosoft/skills3.1k stars
351

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmi_path, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmi_path token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

Use this Skill: https://skilld.dev/gh/microsoft/skills/entra-agent-id

This session only. Nothing lands on disk.

referencesobo-blueprint-setup.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

OBO Blueprint Setup

To use OBO (on-behalf-of) mode — where an agent acts on behalf of a user — the Blueprint must be configured as an OAuth2 API so the user's token can target it as audience.

Configure the Blueprint as an API

Apply once via PATCH /applications/{blueprint_obj_id}:

import uuid

scope_id = str(uuid.uuid4())
patch = {
    "identifierUris": [f"api://{blueprint_app_id}"],
    "api": {
        "requestedAccessTokenVersion": 2,
        "oauth2PermissionScopes": [{
            "id": scope_id,
            "adminConsentDescription": "Allow the app to access the agent API on behalf of the user.",
            "adminConsentDisplayName": "Access agent API",
            "userConsentDescription": "Allow the app to access the agent API on your behalf.",
            "userConsentDisplayName": "Access agent API",
            "value": "access_as_user",
            "type": "User",
            "isEnabled": True,
        }],
        "preAuthorizedApplications": [{
            "appId": client_app_id,   # Your front-end or CLI app's appId
            "permissionIds": [scope_id],
        }],
    },
    "optionalClaims": {
        "accessToken": [{
            "name": "idtyp",
            "source": None,
            "essential": False,
            "additionalProperties": ["include_user_token"],
        }]
    },
}
requests.patch(
    f"{GRAPH}/applications/{blueprint_obj_id}",
    headers=headers, json=patch,
).raise_for_status()

All four pieces are required:

  1. identifierUris — enables api://{appId} as audience.
  2. oauth2PermissionScopes — defines the access_as_user scope users can consent to.
  3. preAuthorizedApplications — authorizes your client app and skips the consent prompt.
  4. optionalClaims — emits the idtyp claim needed for token-type validation.

Grant Delegated Permissions to Each Agent Identity

Each Agent Identity needs oauth2PermissionGrants specifying which Graph delegated permissions it may exercise on behalf of users:

from datetime import datetime, timedelta, timezone

expiry = (datetime.now(timezone.utc) + timedelta(days=3650)).strftime("%Y-%m-%dT%H:%M:%SZ")

requests.post(
    f"{GRAPH}/oauth2PermissionGrants",
    headers=headers,
    json={
        "clientId": agent_sp_id,     # Agent Identity SP object ID
        "consentType": "AllPrincipals",
        "resourceId": graph_sp_id,   # Microsoft Graph SP object ID
        "scope": "User.Read Tasks.ReadWrite",
        "expiryTime": expiry,
    },
).raise_for_status()

Acquire the User Token — Targeting the Blueprint

from azure.identity import InteractiveBrowserCredential

credential = InteractiveBrowserCredential(
    tenant_id=tenant_id,
    client_id=client_app_id,   # Your client app, NOT the Blueprint
    redirect_uri="http://localhost:8400",
)
user_token = credential.get_token(f"api://{blueprint_app_id}/access_as_user")

If the user token targets https://graph.microsoft.com instead of the Blueprint, the OBO exchange returns AADSTS50013: Assertion failed signature validation.

Then feed user_token.token into exchange_obo(...) from runtime-token-exchange.md.

Per-Agent Scoping

Different agents can have different permission boundaries:

AGENT_SCOPES = {
    "it-helpdesk":   "User.Read Tasks.ReadWrite",
    "comms-agent":   "User.Read Mail.Send Calendars.ReadWrite",
    "hr-onboarding": "User.Read User.ReadBasic.All",
}

for agent_name, scopes in AGENT_SCOPES.items():
    grant_delegated(agent_identities[agent_name], scopes)

Key Rules (OBO)

  • User token audience = Blueprint (api://{blueprint_app_id}/access_as_user), not Graph.
  • Use /.default scope on the OBO exchange step.
  • expiryTime is required on oauth2PermissionGrants for Agent Identity grants.
  • Browser-based admin consent URLs do not work for Agent Identities — use oauth2PermissionGrants API for programmatic consent.
  • Group.ReadWrite.All cannot be granted as a delegated permission to Agent Identities. Tasks.ReadWrite alone covers Planner task operations.
  • Not every Graph scope is allowed for Agent Identities — test each new scope.

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill facilitates the management of Microsoft Entra Agent IDs using official Microsoft tools and APIs. It includes important considerations for handling Azure credentials and provides guidance on transitioning from local development secrets to production-grade authentication methods.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer6mo

    4/4 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at b3c238e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 months ago
metadata
{
  "author": "Microsoft",
  "version": "1.1.1"
}

README badge

README badge for microsoft/skills/entra-agent-id