Nitin Kumar SinghSolutions Architect

Type to search. ↑↓ to move, Enter to open.

    ↑↓ move ↵ open esc close
    Deep DiveAzure

    Choosing the Right Agent Identity: Managed Identity, Entra Agent ID, OBO, or Service Principal

    The first design decision for any Azure AI agent is which identity it uses — a decision matrix across managed identity, Entra Agent ID, and OBO.

    The first design decision

    A regional insurer stands up a shared claims agent so adjusters can ask plain-English questions about loss history against the claims data in Snowflake. Think show me the open first-notice-of-loss claims over $50,000 filed in the Northeast this quarter.

    A newly hired adjuster, deliberately scoped to a single line of business, asks it for a fraud-pattern summary. The agent hands back claim details and policyholder data the adjuster could never have opened directly. No misconfiguration, no policy violation.

    The root cause was one decision made months earlier. The agent runs under its own application identity, so the adjuster’s restrictions never applied, and the audit trail blames the agent, not the person who asked.

    That is the failure mode the identity decision exists to prevent, and it is not hypothetical. A documented 2026 incident1 at another firm unfolded exactly this way: a shared agent returning data a limited-permission employee could never have reached on their own.

    It is the first decision you make about an agent, before a line of orchestration code. Get it right and least privilege, attribution, and revocation come almost for free; get it wrong and you build a confused deputy into the foundation.

    Azure gives you four identities to choose from: a managed identity, a Microsoft Entra Agent ID, an on-behalf-of flow, or a classic service principal. This piece is about how to choose, not how to code all four. It builds on the Zero-Secrets Azure series, which established keyless as the credential foundation. Here we answer which identity sits on top.

    Two questions decide it

    Almost every agent resolves to one of the four on two axes, and Microsoft’s own guidance is organized around exactly these:

    1. Is the agent acting as itself, or on behalf of a user? A background summarizer acts as itself. An agent reading your mailbox acts as you.
    2. What is it reaching: Azure resources (governed by RBAC) or Microsoft Graph / M365 data (governed by delegated or application permissions)?
    as itselfyesyesfor a userOn-behalf-ofdelegated permissionsno, or anexternal IdPService principalfederated credential firstresourceaccess onlyManaged identityuser-assignedActing as itself, or for a specificuser?Runs on Azure compute?Needs agent governance?sponsorship, Conditional Access, kill-switchEntra Agent IDblueprint + agent identity
    Three questions, and each one you answer early removes an identity type from consideration. The last question is the only one about governance rather than plumbing, which is why it is last: everything above it you can answer from the deployment diagram.

    Two questions, four answers. “For a user” branches to on-behalf-of; “as itself” splits on whether the workload runs on Azure and whether it needs agent-specific governance.

    The decision matrix

    Read this first; the sections below are the detail behind each row.

    The agent…UseWhy
    reaches Azure resources as itself (Blob, Cosmos, AI Search, Key Vault)Managed identity (user-assigned)Keyless, RBAC-scoped, Azure-native: the everyday default
    needs governance: sponsorship, Conditional Access, a kill switch, agent-aware auditEntra Agent ID (blueprint + agent identity)A first-class agent identity; use a federated managed identity as its credential
    acts on a specific user’s mail, files, or calendarOn-behalf-of (delegated permissions)The agent inherits the user’s permission boundary and cannot exceed it
    runs outside Azure, uses an external IdP, or a legacy tool needs a client ID + secretService principal (federated credential → certificate → secret, in that order)The fallback when managed-identity or Agent-ID federation isn’t possible

    There is no single Microsoft page that compares all four. This matrix is assembled from the agent-identity architecture2 and authorization guidance, not copied from one table.

    Managed identity: the everyday default

    When the agent acts as itself against Azure resources, a managed identity is the answer. There is no secret to store, the platform rotates the credential, and access is scoped by RBAC. Microsoft’s guidance is blunt: for Azure-to-Azure authentication, “managed identities and the DefaultAzureCredential class are the recommended option.”3

    Prefer user-assigned. A system-assigned identity is bound one-to-one to a resource. A user-assigned identity is created once and shared across the compute that needs it, and its roles can exist before the compute does, which is what an autoscaling agent fleet needs. It also sidesteps the Entra object-creation rate limit that rapid system-assigned creation can hit. Microsoft calls user-assigned the recommended type for most scenarios.

    // The current, documented pattern for pinning a user-assigned identity.
    var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
    {
    ManagedIdentityClientId = "<user-assigned-client-id>"
    });

    The per-resource RBAC mechanics (which role for Blob, Cosmos, AI Search, and the rest) are the whole subject of the keyless cookbook.

    Entra Agent ID: governance, not just a token

    A managed identity gets an agent a token. It does not, on its own, give you an accountable owner, a Conditional Access boundary, agent-aware audit entries, or a single switch to shut a misbehaving agent off. That is what Microsoft Entra Agent ID (GA in 2026) adds: a purpose-built identity model for agents.

    Its object model has four parts:

    • Agent identity blueprint: the template that holds credentials and applies policy.
    • Blueprint principal: the runtime service principal that acquires tokens on the blueprint’s behalf.
    • Agent identity: a service-principal subtype with no credentials of its own.
    • Agent user account (optional): a 1:1 paired user object, used only when a resource strictly requires one, like a mailbox or a Teams channel.

    Microsoft is explicit that classic service principals are “not recommended for agent workloads”2 precisely because they lack this governance layer.

    What you get over a plain managed identity:

    • Enforced sponsorship: every blueprint has an accountable human or group owner, assigned at creation.
    • Conditional Access for agents: agents can’t satisfy MFA, so they’re targeted by agent-specific policies, not human ones.
    • Identity Protection: risky-agent detection for unfamiliar resource access, sign-in spikes, and suspicious credential use.
    • A kill switch: disabling a blueprint instantly blocks every agent identity minted from it.

    The credential lives on the blueprint, never on the agent identity. Trying to add a secret to an agent identity fails outright. In production the blueprint’s credential should be a federated managed identity4, so there is no stored secret anywhere in the chain.

    A note for your code: Entra Agent ID is not a new TokenCredential class you new up. It’s a configuration and governance layer. The runtime uses the Microsoft Entra Auth SDK (a sidecar HTTP surface) or Microsoft.Identity.Web config with a managed-identity-backed assertion. Don’t go looking for an AgentIdentityCredential; there isn’t one.

    Use Agent ID when agents are becoming an estate you must govern, not a single script. Practitioners are candid that it takes real setup (inventory, a blueprint strategy, baseline policy) before it pays off. Several of its adjacent controls are still preview or licensing-gated, so check what’s current before you commit hard to a preview feature.

    On-behalf-of: when the agent acts as a user

    The moment an agent touches a specific person’s data (their mail, files, calendar) it must act with that person’s delegated permission, not its own. That is the on-behalf-of flow: the user signs in, the app passes their token, and it’s exchanged for a downstream token carrying the user’s own scope. The agent can now only reach what the user already could.

    The distinction is the whole point of the claims-agent scenario above. A delegated Mail.Read grant lets an agent read only the signed-in user’s mailbox. An application Mail.Read grant lets it (or anyone holding its credential) read every mailbox in the tenant. Microsoft’s rule is one line worth pinning up: “avoid granting app permissions when delegated permissions would suffice.”4

    OBO carries a governance bonus too: risky activity is attributed to the user, so remediation targets that session rather than disabling the agent for everyone.

    // Attended agent: exchange the signed-in user's token for a downstream one
    // that carries the user's own delegated permissions.
    var credential = new OnBehalfOfCredential(
    tenantId, clientId, clientSecretOrCert, userAssertion);

    Use OBO for interactive, user-facing agents; use an app identity (a managed identity where possible) for autonomous, background work. Some agents do both and pick the token per operation: a nightly sync under their own identity, user chats on behalf of the user.

    Service principal: the last resort

    A classic app registration is the option to reach for last. Microsoft’s app-registration best practices rank credentials plainly: use a managed identity if you can; if the workload runs off-Azure on a platform that supports it, use a federated credential; if not, a certificate; and only as a last resort, a client secret.

    That means a service principal still has real uses: a workload running outside Azure with no federation option, an external-IdP integration, or a legacy tool or SaaS connector that only understands a client ID and secret. When you do need one, you can still make it keyless. Configure a federated credential on the app registration itself, trusting a managed identity, so there’s no stored secret.

    The four, side by side

    One caveat before the table, because it prevents a category error. The four don’t sit at the same level:

    • Managed identity and service principal are credential-bearing identities: objects that mint tokens in their own name.
    • On-behalf-of is a runtime flow, not an identity: it borrows whatever credential its host already holds to produce a token that represents the user. There is no “OBO object” to point at, disable, or audit on its own.
    • Entra Agent ID is a governance model: layered on a service-principal-shaped object that natively uses both of the other patterns.

    Read the table as how they differ in practice, not four interchangeable options.

    Managed identityEntra Agent IDOn-behalf-ofService principal
    What it isCredential-bearing identityGoverned identity model (blueprint + agent identity)A runtime token-exchange flowCredential-bearing identity
    Acts asItselfItself or the user (dual-mode)The user (agent is the actor)Itself
    CredentialPlatform-managed, auto-rotated, never exposedOn the blueprint only; prefer a federated managed identityBorrows the host’s credentialDev-managed: federated → certificate → secret
    GovernanceRBAC scope only; not covered by Conditional Access for workload identitiesSponsorship, agent-specific Conditional Access, risky-agent detection, blueprint kill switchBound to the user’s CA and consent, evaluated at the downstream callCA for workload identities only if single-tenant + Workload ID Premium; no agent-aware audit
    RunsAzure onlyAzure or external (federated)Wherever the host runsAzure or non-Azure
    WhenAs itself against Azure resourcesAn estate of agents you must governStrictly within one user’s own accessOff-Azure, external IdP, or legacy tooling

    How an agent actually gets a token

    Which identity you pick decides who the agent is. A second question decides how it authenticates and whose access it carries, and this is where “the agent can only reach what the user can” is won or lost. There are two operating modes, and one of them has two steps:

    • Unattended, no user present. The agent authenticates as itself with the client-credentials flow. The token represents the agent, carries application permissions or RBAC, and reaches whatever the agent was granted. Background jobs, scheduled scoring, batch work.
    • Attended, a user is present. The user first signs in through an interactive front door, a separate client app, because an agent identity can’t perform the sign-in leg itself. That produces the user’s token, which the agent then exchanges via on-behalf-of for a downstream token carrying the user’s delegated permissions. “Interactive” is the front door; “on-behalf-of” is the exchange behind it: two hops of one attended flow, not two competing choices. Foundry just calls the pair attended.
    Who is callingWhat it reachesUnattended — no user presentAttended — a user is presentAgentits own identityUser1 · signs in at the front-door clientappClient app2 · passes the user tokenAgent3 · exchanges it on-behalf-ofResourceapp permissions and RBACResourceonly what the user can accessclient credentialsdelegated permissions
    The same agent, two ceilings. Unattended, it reaches whatever its own app permissions allow. Attended, a user signs in at the front door first and the agent exchanges that token — so it cannot reach anything the user could not reach without it.

    Unattended is one hop: the agent as itself. Attended is two: an interactive sign-in that establishes who the user is, then an on-behalf-of exchange that binds every downstream call to that user’s own access.

    WorkflowToken representsPermissionsWho consentsBlast radius
    Client credentials (unattended)The agentApplication / RBACAdminWhatever the agent holds, potentially broad
    Interactive front door (attended, step 1)The userEstablishes who the user isUser or adminn/a
    On-behalf-of (attended, step 2)The user, agent as actorDelegated, per the userUser or adminOnly what that user can already reach

    The practical payoff is the one the opening turned on: put the claims agent on the attended path, and the on-behalf-of exchange binds every query to the requesting adjuster’s own access. The newcomer sees their book of business and nothing more, and the audit trail names the adjuster, not the agent.

    How Foundry chooses for you

    If you build on Azure AI Foundry Agent Service, much of this is provisioned automatically. The automatic behavior has one sharp edge worth knowing.

    Every Foundry project gets a system-assigned managed identity plus a default agent identity blueprint. All unpublished, in-development agents in a project share one common agent identity, convenient for iterating without repeated permission setup. But publishing an agent mints a new, dedicated blueprint and agent identity, and the shared project identity’s role assignments do not carry over. You have to re-grant them to the published agent’s identity.

    The projectBefore publishingAfter publishingDefault blueprint — one sharedagent identityFoundry projectsystem-assigned managedidentityUnpublished agent AUnpublished agent BDedicated blueprint + agentidentityre-grant its roles herepublish
    Before publishing, every agent in a project shares one identity — so a role granted to reach a mailbox is granted to all of them. Publishing is what splits that apart, and the roles do not come with it.

    Foundry shares one identity across a project’s unpublished agents, then splits off a dedicated identity on publish. The blast-radius win comes with a chore: role assignments don’t follow, so re-check them after every publish.

    The whole chain stays keyless: the blueprint federates against the project’s managed identity, so no client secret is ever stored. The same principle the Zero-Secrets series applies everywhere else.

    Rank your credentials

    Whichever identity you pick, the credential under it should be as high on this list as your hosting allows:

    This is not a style preference. Over-privileged, statically-credentialed agents are a measured risk: one 2026 survey found organizations that grant agents excessive access see roughly 4.5× higher incident rates. The identity you choose sets the ceiling on how much damage a compromised or confused agent can do.

    Where to start

    Come back to the two questions. Is the agent acting as itself or for a user? Is it reaching Azure resources or Graph/M365? Those answers put almost any agent onto one of the four identities: a managed identity for the everyday as-itself case, Entra Agent ID when you need to govern an estate of them, on-behalf-of whenever a specific user’s data is in play, and a service principal only when nothing else fits, kept keyless with a federated credential.

    Two threads continue from here. The credential foundation under all of this is the Zero-Secrets Azure series (the cookbook has the per-resource RBAC), and when these agents call models and tools through a gateway, the AI gateway in Azure API Management is where the same managed-identity principle governs the ingress. Federating an agent’s identity on AKS, and scoping Conditional Access through the on-behalf-of chain, are each their own piece for a later day.

    References

    1. documented 2026 incident — thehackernews.com ↩

    2. agent-identity architecture — learn.microsoft.com ↩ ↩2

    3. “managed identities and the DefaultAzureCredential class are the recommended option.” — learn.microsoft.com ↩

    4. federated managed identity — learn.microsoft.com ↩ ↩2

    5. Conditional Access does not apply to service-principal sign-ins — marcogerber.ch ↩

    Comments

    Comments are GitHub discussions. Sign in with GitHub to post; reactions need no account.