Security & Compliance

Azure Entra Agent ID: Identity and Permissions for Agentic AI

By Technspire Team
April 14, 2026
15 views

Classic identity systems were designed for two kinds of actor. Humans, who sign in interactively and carry delegated permissions, and service principals, which are long-lived, usually over-scoped, and essentially headless. Neither model fits AI agents. Agents act on behalf of humans sometimes and autonomously at other times. They may spawn sub-agents. They require least-privilege scoping at the tool level, not the API level. Microsoft Entra Agent ID is Microsoft's answer to that gap, and it is the first ecosystem primitive that treats agent identity as a distinct kind of non-human identity rather than a workaround.

Why a Service Principal Is the Wrong Default

Before Agent ID entered preview, teams routinely gave each agent a service principal. Three things went wrong almost immediately.

  • Over-privileged by default. A service principal designed for a backend service carried Graph and Azure permissions that a narrow agent did not need. Least privilege was optional; convenience pushed scope wider than it should have been.
  • Untraceable. A shared service principal behind every agent meant audit logs showed one actor for dozens of distinct agents. The question "which agent made this decision" was unanswerable from the logs alone.
  • No governance primitives. Access reviews, lifecycle policies, and expiry semantics for human users have no direct analogue for service principals. Agents proliferated without corresponding cleanup workflows.

Agent ID treats each agent as a first-class identity in Entra. It has a unique identifier, a scoped blueprint, and participates in the same governance framework that applies to human identities. The design explicitly prevents the shortcuts that caused the service-principal mess.

The Primitives

  • Agent identity. Each agent gets its own identity in Microsoft Entra. It is neither a user nor a classic service principal. It is a distinct identity type designed for the operational patterns of AI agents.
  • Agent identity blueprint. A reusable template that captures the agent's name, organisation, roles, and Microsoft Graph permissions. Blueprints enable administrators to scale agent deployment without losing the ability to apply consistent policy to every instance.
  • Attended and unattended authentication modes. Agents authenticate in one of two ways: delegated, where the agent acts on behalf of a human user with scoped delegated permissions; or app-assigned, where the agent acts under its own authority via RBAC.
  • Governance primitives. Identity Governance extends to agents — access packages, access reviews, lifecycle policies. The public preview of governance-for-agents landed in April 2026 and became generally available in early May.

Attended: The On-Behalf-Of Flow for Agents

An attended agent acts on behalf of a specific human user. The user's delegated permissions scope what the agent can do. The classic OAuth 2.0 on-behalf-of flow applies, with Entra Agent ID as the client identity and the human user's delegated consent as the scope boundary. The agent cannot escalate beyond what the human could do; if the human lacks a permission, so does the agent.

// Attended agent — OBO flow acquiring a token for a downstream resource
// Using MSAL for Node. The agent's identity authenticates; the user's token scopes the action.

import { ConfidentialClientApplication } from '@azure/msal-node';

const msal = new ConfidentialClientApplication({
  auth: {
    clientId: process.env.AGENT_CLIENT_ID!,      // the agent identity
    authority: `https://login.microsoftonline.com/${process.env.TENANT_ID}`,
    clientCertificate: {
      thumbprint: process.env.CERT_THUMBPRINT!,
      privateKey: process.env.CERT_PRIVATE_KEY!,
    },
  },
});

async function exchangeForUserScopedToken(userAssertion: string, scope: string) {
  return msal.acquireTokenOnBehalfOf({
    oboAssertion: userAssertion,                 // the user's token presented to the agent
    scopes: [scope],                             // narrow, resource-specific
  });
}

The practical consequence is that audit logs show two actors for every action: the user who authorised it, and the agent that performed it. Both are distinct identities. Compliance teams can answer "did the user consent to this action" and "which agent executed it" as separate, verifiable questions.

Unattended: The Agent as Its Own Actor

Some agents operate without a human in the loop. Scheduled batch processors, monitoring agents, research agents running overnight. These agents act under their own authority, with app-assigned permissions granted via Azure RBAC or Microsoft Graph application permissions. The identity is still the agent's, not a shared service principal, so the per-agent audit trail and governance continue to apply.

// Unattended agent — token acquisition for its own operations
async function getUnattendedToken(scope: string) {
  return msal.acquireTokenByClientCredential({
    scopes: [`${scope}/.default`],
  });
}

// The agent's RBAC assignments govern what it can access. Each assignment is narrow.
// Example: role assignment at the resource level, not the subscription level.

What Entra Refuses to Grant Agents

A deliberate design choice in Agent ID is that Entra blocks agents from being granted many high-privilege roles or permissions, even when administrators attempt to consent to them. The platform treats the agent category as inherently requiring least-privilege scoping; powerful roles like Global Administrator or User Administrator are off the table for agent identities. This is a floor, not a ceiling. Administrators can scope agent permissions as narrowly as they like within the remaining surface.

The practical consequence is that certain patterns common with service principals (an agent that manages other users' access, for instance) require a different architecture. An agent cannot directly grant Global Administrator rights; an explicit human-approval step, routed through a privileged-identity-management workflow, has to be designed in.

Registering an Agent Identity

# Register an agent identity using Microsoft Graph (preview endpoint)
# The exact surface evolves through preview; check current docs before productionising

az rest --method POST \
  --uri "https://graph.microsoft.com/beta/agentIdentities" \
  --body '{
    "displayName": "Customer-Support-Triage-Agent",
    "description": "Triages inbound support tickets, creates work items, answers FAQs",
    "blueprint": "blueprint-id-for-customer-support",
    "permissions": {
      "delegated": ["SupportTicket.ReadWrite", "Chat.Read"],
      "application": []
    },
    "tags": ["team:customer-experience", "environment:production"]
  }'

Tagging agents from the point of registration makes lifecycle policies tractable. A lifecycle rule can target "all agents tagged environment:development older than 90 days" for quarterly cleanup, without manual enumeration.

Tool-Level RBAC Instead of API-Level

A common mistake is scoping the agent's permissions at the API level. For example, giving an agent Microsoft Graph Mail.ReadWrite means the agent can read and write all mail it has visibility to. That is rarely what the business requires. The agent's actual job might be narrower: respond to specific queues, draft replies, forward to a human for approval.

Scope permissions at the tool boundary. Each tool the agent can invoke becomes its own RBAC-controlled action. The agent's identity gains exactly the role assignments needed to invoke the tools in its configuration, nothing broader. When the agent definition grows new tools, the role assignments grow with it. When tools are removed, the permissions are removed.

// Tool-level permission model — the agent's tools each have their own role assignment
type ToolDefinition = {
  name: string;
  requiresRole: string;     // e.g. 'Support.TicketTriage.Executor'
};

const TOOLS: ToolDefinition[] = [
  { name: 'read_customer_profile', requiresRole: 'CRM.Reader' },
  { name: 'draft_support_reply',   requiresRole: 'Support.TicketTriage.Drafter' },
  { name: 'escalate_to_human',     requiresRole: 'Support.Escalation.Invoker' },
];

// The agent's identity has exactly these three role assignments. Not "all CRM access".
// Adding a fourth tool adds a fourth assignment; removing a tool removes an assignment.

Conditional Access for Agents

Entra's Conditional Access engine extends to agent identities. Policies can require specific conditions for agent authentication or action: geographic constraints on where the agent may run, risk-signal thresholds that trigger additional friction, time-of-day boundaries that confine the agent to specific operating windows.

// Conceptual Conditional Access policy targeting an agent identity
{
  "displayName": "Agent-Support-Triage-Business-Hours-Only",
  "conditions": {
    "identities": { "includeAgents": ["agent-id-customer-support"] },
    "applications": { "includeApplications": ["ticket-api-client-id"] },
    "times": { "includeWindows": ["weekdays-08-18-stockholm"] },
    "locations": { "includeLocations": ["sweden-central-vnet"] }
  },
  "grantControls": { "operator": "AND", "builtInControls": ["block"] },
  "sessionControls": { "applicationEnforcedRestrictions": true }
}

Multi-Agent Systems and Identity Propagation

An agentic system in which Agent A calls Agent B raises a sharper question. Whose identity performs the action at Agent B? If A acts on behalf of User U, does B act on behalf of U as well, or under its own authority? The wrong answer is "whichever happened to be in the token store when B ran." The right answer is deliberate: the call from A to B propagates identity through the standard OAuth 2.0 OBO flow, with A exchanging its user token for a token scoped to B, and B carrying that scope into any further calls it makes.

The operational consequence is that audit logs can reconstruct the full chain: user U authorised an action; agent A performed it; agent A delegated a subtask to agent B; agent B, still scoped to U's permissions, invoked tool T. Any link can be broken for a specific user, and the break propagates through the chain. This is the kind of discipline that turns "we have multi-agent" from a governance headache into a defensible architecture.

Preventing Confused-Deputy Attacks

A confused-deputy attack occurs when an agent with broad permissions is tricked into performing an action on behalf of an entity that should not have had access. The classic example: user X convinces an agent with administrative permissions to perform an action X could not perform directly. The defence is twofold. First, scope agent permissions as narrowly as the specific task requires, so that even if confused, the agent cannot escalate beyond the task's own permissions envelope. Second, propagate user identity into every action, so the downstream system can re-check authorisation against the user, not the agent. Agent ID's OBO flow and tool-level RBAC together enforce this pattern.

Audit Logging: Two Streams

Compliance frameworks increasingly expect two distinct audit streams for agentic systems. The first is agent decisions: what did the agent choose to do, why, with what inputs, and against what policy. The second is tool invocations: which tools were called, by which agent, with what arguments, with what outcome. Agent ID provides the identity substrate for the second stream by ensuring every tool invocation carries the agent's distinct identity. The first stream is application-level logging that sits above Agent ID and integrates with it.

// KQL — audit trail of agent tool invocations over the last 24 hours
SigninLogs
| where TimeGenerated > ago(24h)
| where UserType == "AgentIdentity"                      // filter to agent identities
| extend onBehalfOfUser = tostring(parse_json(tostring(AdditionalDetails))["onBehalfOf"])
| project TimeGenerated, AgentName=UserDisplayName, AgentId=UserId, onBehalfOfUser,
          ResourceDisplayName, Status=ConditionalAccessStatus
| order by TimeGenerated desc

Token Lifetimes

Agent tokens should be short-lived. A one-hour default is reasonable; shorter for sensitive operations. Longer-lived refresh tokens let the agent re-authenticate without user interaction when appropriate, under the same delegated or application permissions. Never mint a long-lived access token for an agent to use for weeks. The point of the identity model is that revocation is meaningful; if tokens survive revocation, the identity model is decoration.

Governance and Lifecycle

  • Access packages for agents. An access package bundles the entitlements an agent needs for a specific purpose. Provisioning an agent becomes a one-step action; revoking it is equally clean.
  • Access reviews. Quarterly reviews of agent identities and their permissions. Agents whose permissions are no longer in use surface for deprovisioning.
  • Expiry policies. Agents created for experiments or pilots expire automatically. A tagged "environment:development" agent that is 90 days old is deactivated unless explicitly renewed.
  • Attestation workflows. An agent's owner team periodically confirms the agent is still in active use, still scoped appropriately, and still compliant with policy.

Integration With Microsoft Foundry

Microsoft Foundry's agent runtime integrates with Entra Agent ID out of the box. Agents deployed on Foundry are created with an Entra agent identity by default; the blueprint is applied at creation time; RBAC assignments propagate to the resources the agent needs. For teams already standardising on Foundry, the identity plumbing is largely handled.

Operational Considerations

  • Agent sprawl is real. The ease of creating agents via blueprints can lead to hundreds of agent identities across an organisation. Lifecycle rules and tagging become essential from day one.
  • Blueprint design is security-critical. A poorly designed blueprint grants too much to every agent that uses it. Treat blueprint authorship as a privileged activity.
  • Cross-tenant agents raise hard questions. An agent that must operate across Entra tenants (partner integrations, for instance) needs explicit cross-tenant access policies. Keep the number of such agents small; each is an elevated-trust boundary.
  • Cost of the preview is mostly operational. Agent ID's core primitives sit under Entra's existing licensing for most feature combinations. The cost is the engineering and process work, not the licence line.

Regulatory Alignment

  • GDPR. When an agent acts on behalf of a user, the user remains the data subject; the agent is an additional processor. Documentation must be clear about who the controller and processor are at each step.
  • DORA. ICT third-party register includes the agent runtime, not just the LLM provider. Scope registers to reflect the actual topology, including Entra agent identities as part of the ICT services inventory.
  • NIS2. Identity governance and least-privilege requirements extend naturally to agent identities. Access reviews and lifecycle management for agents are part of the expected control set.
  • EU AI Act. Audit logging (Article 12) is materially easier when each agent has its own identity and each tool invocation carries that identity into the log. The Annex IV documentation that describes human oversight and access controls has concrete primitives to reference.

Practical Checklist

  • One Entra agent identity per deployed agent. No shared service principals behind multiple agents.
  • Blueprint authorship restricted to a small, accountable group. Treat the blueprint as part of the permissioned surface.
  • Tool-level RBAC instead of API-level permissions. Each tool maps to a narrow role.
  • Attended flows use OBO properly. User identity propagates into every downstream call.
  • Token lifetimes short by default. Refresh, do not persist access tokens for extended periods.
  • Conditional Access policies cover the risk dimensions that matter — geography, time, data sensitivity.
  • Audit log two streams: agent decisions and tool invocations. Correlate via trace IDs.
  • Lifecycle and access reviews on a quarterly cadence at minimum.
  • Cross-tenant agent use is rare, documented, and governed as a privileged access boundary.

Agent ID is not a drop-in solution that makes identity for agents trivial. It is the primitive that lets a team build the right model without heroics. The remaining work is the same kind of discipline that human identity demands: scoped permissions, reviewable audit, short-lived tokens, clear ownership. Teams that adopt it with that seriousness will run agents they can defend in any audit. Teams that treat it as a box-check will reproduce the service-principal mess with shinier terminology.

Ready to Transform Your Business?

Let's discuss how we can help you implement these solutions and achieve your goals with AI, cloud, and modern development practices.

No commitment required • Expert guidance • Tailored solutions