Home/Blog

AI Agent Identity on AWS, Azure and GCP: What to Use

Entra Agent ID, Google Cloud Agent Identity and AgentCore Identity compared: credentials, on-behalf-of flows, sponsors, and when a service account fits.

AI Agent Identity on AWS, Azure and GCP: What to Use

Give every AI agent its own identity, and use the agent identity each cloud now provides instead of a shared service account. On Azure that is Microsoft Entra Agent ID: a blueprint holds the credentials, each agent gets an agent identity, and every agent has a human sponsor. On Google Cloud it is Agent Identity: a per-agent SPIFFE principal with no keys to leak. On AWS it is Amazon Bedrock AgentCore Identity: a workload identity plus a token vault for third-party OAuth tokens and API keys, used alongside the IAM role that governs AWS calls.

Key takeaways

  • A service account answers "which workload is this?" An agent also needs answers to "which agent, acting for whom, and which human is accountable for it?" The new agent principals add those answers.
  • Entra Agent ID splits credentials (on the blueprint) from identities (one per agent), requires a sponsor on both, and lets Conditional Access target a whole blueprint at once.
  • Google Cloud Agent Identity gives each deployed agent its own principal:// identifier, tokens bound to a certificate, and no service account keys to create.
  • AgentCore Identity does not replace IAM roles. It adds a workload identity and a token vault so the agent can reach GitHub, Slack or Salesforce without holding long-lived secrets.
  • For acting on behalf of a user, exchange the token. Never hand the user's original token to the model or to a tool.
  • Agents that run outside the cloud they call still need workload identity federation. No single provider authorizes resources in all three clouds.

Why a service account is the wrong default for an agent

A service account was designed for deterministic workloads: a job that does the same thing every run. An agent decides what to do at run time, based on input that may come from an attacker. Three things follow.

You need one identity per agent, not per application. A support agent that reads tickets and a billing agent that issues credits must not share credentials. If they do, an injection that steers the first agent gets the second agent's permissions, and your audit logs cannot say which agent acted.

You need to know who the agent is acting for. An agent often works on behalf of a signed-in user. Your logs and your authorization checks need both identities: the agent and the user. A service account carries only one.

You need a human who answers for it. Agents multiply, and their builders change teams. Service accounts have no built-in concept of a business owner who must confirm the agent is still needed.

Long-lived keys make all three worse. A service account key in an agent's environment is a credential the model can be tricked into printing, which is why the first rule of AI agent design for production is that the agent never holds a secret.

A service account is still the right call in one case: a fixed pipeline that calls a model as one step, where your code decides every action and the model only classifies or drafts. That is an ordinary workload. Treat it as one. For a refresher on workload identities and least privilege in general, see our IAM strategy guide.

Azure: Entra Agent ID (blueprints, sponsors, Conditional Access)

Microsoft Entra Agent ID is generally available, and since 1 May 2026 it ships as part of Microsoft Agent 365: users need a Microsoft Agent 365 or Microsoft 365 E7 license, agents acting on behalf of a licensed user are covered by that user's license, and agents do not need licenses of their own. Some protections have separate requirements: Conditional Access for agents needs Microsoft Entra ID P1 or Microsoft 365 E3, and ID Protection for agents, still in preview, needs Entra ID P2, Microsoft 365 E5 or Microsoft Entra Suite.

The object model

Four objects matter:

ObjectWhat it isHolds credentials?
Agent identity blueprintTemplate and authentication foundation for one or more agents. Policies on the blueprint apply to every agent created from itYes
Agent identity blueprint principalRecords the blueprint's presence in a tenant so it can get tokens and appear in logsNo
Agent identityThe identity one agent uses to authenticate and access resourcesNo, it gets tokens through its blueprint
Agent's user accountOptional, paired one to one with an agent identity, for systems that require a user object such as a mailboxNo

The split is the point. Credentials live in one place, the blueprint, while each agent has a distinct identity for permissions, logs and policy. A blueprint can only act for its own child agent identities, and an agent identity belongs to exactly one blueprint.

Microsoft's guidance on credentials is direct: use a managed identity as a federated identity credential on the blueprint, and do not use client secrets in production. Certificates are supported where managed identities cannot work.

Sponsors and owners

Every blueprint and every agent identity must have at least one sponsor. A sponsor is the business person or group accountable for the agent: they decide whether it is still needed, request access for it, and can disable it during an incident. Sponsors cannot change technical settings. Owners are the technical administrators. Sponsors can be users, dynamic membership groups or Microsoft 365 groups. Security groups and role-assignable groups are not supported as sponsors.

Two directory roles cover the builder side. Agent ID Developer can create blueprints and configure federated identity credentials on them. Agent ID Administrator can do the same and is required to add a secret or certificate.

Creating a blueprint and an agent identity

You can use the Entra admin center wizard, but you will want this in code. Create the blueprint through Microsoft Graph with a sponsor:

POST https://graph.microsoft.com/v1.0/applications/microsoft.graph.agentIdentityBlueprint
OData-Version: 4.0
Content-Type: application/json
Authorization: Bearer <token with AgentIdentityBlueprint.Create>
 
{
  "displayName": "support-agents",
  "sponsors@odata.bind": ["https://graph.microsoft.com/v1.0/users/<sponsor-id>"],
  "owners@odata.bind": ["https://graph.microsoft.com/v1.0/users/<owner-id>"]
}

Then give the blueprint a managed identity as its credential:

POST https://graph.microsoft.com/v1.0/applications/<blueprint-id>/federatedIdentityCredentials
OData-Version: 4.0
Content-Type: application/json
Authorization: Bearer <token with AgentIdentityBlueprint.AddRemoveCreds.All>
 
{
  "name": "support-agents-mi",
  "issuer": "https://login.microsoftonline.com/<tenant-id>/v2.0",
  "subject": "<managed-identity-principal-id>",
  "audiences": ["api://AzureADTokenExchange"]
}

Create the blueprint principal in the tenant (POST /v1.0/serviceprincipals/microsoft.graph.agentIdentityBlueprintPrincipal with the blueprint's appId). Then the blueprint itself, using a token it acquired with its own credential, creates one agent identity per agent. That call uses the beta endpoint:

POST https://graph.microsoft.com/beta/serviceprincipals/Microsoft.Graph.AgentIdentity
OData-Version: 4.0
Content-Type: application/json
Authorization: Bearer <blueprint token>
 
{
  "displayName": "support-agent-eu",
  "agentIdentityBlueprintId": "<blueprint-app-id>",
  "sponsors@odata.bind": ["https://graph.microsoft.com/v1.0/users/<sponsor-id>"]
}

How an agent gets a token

Agents are confidential clients only. No interactive sign-in, no redirect URIs, no public clients. Token acquisition is a two-step exchange. The blueprint presents its credential and asks for an exchange token for a specific agent identity (the fmi_path parameter). The agent identity then uses that token as its client assertion:

POST /<tenant-id>/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
 
client_id=<agent-identity-id>
&scope=https://graph.microsoft.com/.default
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<exchange token from the blueprint>
&grant_type=client_credentials

That is the autonomous flow. The on-behalf-of flow uses the same exchange token plus the user's token as a jwt-bearer assertion with requested_token_use=on_behalf_of, and the user's token must be addressed to the blueprint. Microsoft recommends its SDKs, including a sidecar container (the Microsoft Entra SDK for Agent ID), rather than hand-rolling these requests. We agree. The wire format matters for one reason: the agent identity has no secret of its own, so everything traces back to the blueprint's credential, which should be a managed identity your code never sees.

Conditional Access for agents

Conditional Access policies can target agent identities. Two patterns scale. Target the blueprint, and the policy covers every agent created from it, including future ones. Or assign custom security attributes to agents (for example a data sensitivity level) and filter on those. Policies are evaluated when a token is requested, so a block takes effect at the agent's next token request.

GCP: Agent Identity (SPIFFE principals, no keys)

Google Cloud made Agent Identity generally available on 22 April 2026, the same day Vertex AI became part of Gemini Enterprise Agent Platform and Agent Engine was renamed Agent Runtime. Agent Runtime is the main supported host. Gemini Enterprise support is in preview.

Each agent gets a SPIFFE ID tied to the lifecycle of the resource that hosts it:

spiffe://agents.global.org-123456789012.system.id.goog/resources/aiplatform/projects/9876543210/locations/us-central1/reasoningEngines/my-test-agent

In IAM, the same identity appears as a principal:// identifier. You grant roles to it like any other principal. To let one agent read one bucket:

gcloud storage buckets add-iam-policy-binding gs://support-kb \
  --member="principal://agents.global.org-123456789012.system.id.goog/resources/aiplatform/projects/9876543210/locations/us-central1/reasoningEngines/my-test-agent" \
  --role="roles/storage.objectViewer"

You opt in when you deploy the agent to Agent Runtime by setting the identity type to AGENT_IDENTITY. Without it, the agent keeps running as a service account. The Google Cloud client libraries inside the agent then pick up the agent's credentials through Application Default Credentials, so the agent code has no key file and no secret to read.

What you get over a service account, in Google's own terms: agent identities are not shared by multiple workloads by default, cannot be impersonated, and do not allow long-lived keys. Access tokens are cryptographically bound to the agent's X.509 certificate, and a Google-managed Context-Aware Access policy enforces that binding by default, so a stolen token is not useful from somewhere else. Agent identities work with IAM, Principal Access Boundary policies, VPC Service Controls and audit logs.

Two related pieces are still in preview: the Agent Identity auth manager, a credential vault for third-party access with auth providers for 3-legged OAuth (on behalf of a user), 2-legged OAuth and API keys, and Privileged Access Manager support for agent identities as grant requesters and approvers. Agent Gateway, which decrypts end-user credentials at the gateway so the agent never sees them, is in private preview. They are worth testing. Do not put a preview feature in the critical path of a production agent without a fallback.

One operational consequence of lifecycle binding: the principal includes the agent resource's ID. Delete and recreate the agent, and you have a new principal with none of the old bindings. Manage the bindings in the same Terraform or deployment pipeline that creates the agent.

AWS: AgentCore Identity (workload identities, token vault)

Amazon Bedrock AgentCore became generally available on 13 October 2025, with AgentCore Identity as one of its services. AWS's model is different from the other two, and it is easy to misread.

IAM still governs AWS access. An agent on AgentCore Runtime calls AWS APIs with the runtime's IAM execution role, as any AWS workload does. Least privilege on that role is your job, exactly as before.

AgentCore Identity governs everything outside AWS. Each agent has a workload identity in the AgentCore Identity directory. Runtime and Gateway create one automatically for each agent they host. For self-hosted or hybrid agents you create it yourself:

aws bedrock-agentcore-control create-workload-identity --name support-agent

The workload identity is used to obtain a workload access token, an AWS-signed token that carries both the agent's identity and the end user's identity and works only against AgentCore services. With it, the agent can ask the token vault for credentials from a credential provider. Register a provider once:

aws bedrock-agentcore-control create-oauth2-credential-provider \
  --name github-provider \
  --credential-provider-vendor GithubOauth2 \
  --oauth2-provider-config-input '{"githubOauth2ProviderConfig":{"clientId":"<client-id>","clientSecret":"<client-secret>"}}'

The response includes a callback URL to register with GitHub. API keys use create-api-key-credential-provider the same way. In agent code, the Python SDK injects the credential at call time:

from bedrock_agentcore.identity.auth import requires_access_token
 
@requires_access_token(
    provider_name="github-provider",
    scopes=["repo"],
    auth_flow="USER_FEDERATION",          # "M2M" for the agent's own access
    on_auth_url=lambda url: send_consent_link_to_user(url),
)
async def list_open_issues(repo: str, *, access_token: str) -> list:
    return await github_issues(repo, token=access_token)

On first use for a given user, the SDK hands you an authorization URL to show that user. After consent, the vault stores the token, and AWS documents that it can only be retrieved by the same agent and user combination that obtained it.

On Runtime, inbound authentication (a JWT authorizer for your identity provider, or IAM SigV4) feeds this flow automatically. Runtime validates the caller's token, calls GetWorkloadAccessTokenForJWT with the user and agent identities, and passes the workload access token to your code. For self-hosted agents there is also GetWorkloadAccessTokenForUserId, which accepts any user ID string your code supplies. It does not verify that string. Prefer the JWT variant, and restrict the user-ID one in IAM to the few principals that truly need it.

The three side by side

Azure: Entra Agent IDGCP: Agent IdentityAWS: AgentCore Identity
Principal per agentAgent identity, created from a blueprintSPIFFE-based principal:// for the agent resourceWorkload identity in the AgentCore directory
CredentialOn the blueprint: managed identity as federated credential preferred; agent identities hold noneCertificate and bound tokens managed by Google; no keysIAM execution role for AWS; workload access token for vault access
Acting for a userAgent on-behalf-of flow; agent's user account where a user object is requiredAuth manager 3-legged OAuth (preview)Token vault with user-federated OAuth (USER_FEDERATION)
Third-party toolsYour APIs and Microsoft APIs via Entra tokensAuth manager providers for OAuth and API keys (preview)OAuth2 and API key credential providers
Human accountabilityRequired sponsors on blueprint and agentThrough IAM and your own processThrough IAM and your own process
Policy on the agentConditional Access; ID Protection (preview)IAM, Principal Access Boundary, VPC Service ControlsIAM on the role; IAM on credential provider access
Main hostAnywhere: Azure with managed identity, or elsewhere via federation or the SDK sidecarAgent Runtime; Gemini Enterprise in previewAgentCore Runtime and Gateway; self-hosted with manual identities
What it does not doAuthorize AWS or GCP resourcesAuthorize AWS or Azure resourcesReplace IAM least privilege on the execution role

Read the last row first. Each product makes its own cloud's agent story much better. None of them removes the need for least privilege, and none authorizes the other two clouds.

Acting on behalf of a user without leaking their token

The most common mistake in agent authorization is passing the user's access token into the agent and letting tools use it. It is wrong for three reasons.

  1. The audience is wrong. The user's token was issued to your application. Forwarding it to other services means those services accept tokens that were never meant for them, which is the confused deputy problem in token form.
  2. The scope is wrong. The user's token carries everything your application can do for them. The agent needs a narrow slice for one task.
  3. The model can see it. If the token sits anywhere in the context window, a prompt injection can ask the agent to print it, put it in a URL or pass it to a tool.

The pattern that works is a token exchange, performed by code the model does not control:

Loading diagram...

On Azure this is the agent on-behalf-of flow: the resulting token names both the user and the agent identity, so Conditional Access and logs can tell them apart. On AWS, the token vault stores per-user OAuth tokens that only that agent and user can retrieve. On Google Cloud, the auth manager handles user consent and stores delegated tokens, with every access attributed to the agent's SPIFFE ID.

Whichever you use, two rules hold. The token is attached by tool code at call time and never placed in a prompt. And the agent asks for one resource and the smallest scope that task needs, so a hijacked agent holds a small key, not a master key. The same principle applies to MCP servers: the server should validate a token issued for it, not accept whatever the client forwards.

Agents that span clouds

Plenty of agents run in one place and call another: an agent on AWS that reads a SharePoint site, a GitHub Actions job that runs a coding agent against GCP, a self-hosted agent on a VPS. The agent identity products help on their home turf. Across clouds, workload identity federation does the work: the agent proves who it is with a token from where it runs, and the target cloud exchanges that for short-lived credentials.

Agent runs onCallsUse
Azure, with a managed identityGoogle CloudWorkload Identity Federation with Entra ID as the identity provider, mapped to a principal with narrow roles
AzureAWSAn IAM OIDC identity provider for your Entra tenant and AssumeRoleWithWebIdentity into a scoped role
AWSMicrosoft Graph or your Entra-protected APIsEntra Agent ID federation (AWS STS to a federated credential) or the Entra SDK sidecar
GitHub ActionsAny of the threeGitHub's OIDC token, trusted per repository and branch in each cloud. No stored cloud keys
A VPS or on-premises hostAWSIAM Roles Anywhere with an X.509 certificate from your own CA
A VPS or on-premises hostAzure or Google CloudFederation from an identity provider you run, or a certificate credential, kept in a secrets manager and rotated

Two rules keep this sane. Map each external identity to one agent's principal, not to a shared "integration" role. And scope trust conditions tightly: a GitHub trust that accepts any branch of any repository in your organization is one pull request away from a compromised agent.

What goes wrong in production

  • One identity for every agent. It starts as convenience and ends as a blast radius. When one agent is injected, every agent's permissions are in play, and the logs cannot say which one acted. One principal per agent per environment, always.
  • The user's token in the context window. Search the codebase for places where an Authorization header value or a raw token is put into a prompt template or a tool argument.
  • No sponsor, no off switch. Agents outlive their builders. On Azure, sponsors are required, so choose a group with real members rather than the person who happened to click the button. On AWS and GCP, record an accountable owner in tags or labels and review them on a schedule.
  • Client secrets on the blueprint. They work, so they ship. Microsoft says plainly not to use them in production. Use a managed identity as a federated credential, or a certificate where that is impossible.
  • Trusting a user ID string. On AgentCore, GetWorkloadAccessTokenForUserId with a user ID taken from the request lets one user retrieve another user's vault tokens. Derive the user from a validated JWT.
  • Bindings that vanish on redeploy. On Google Cloud the principal is tied to the agent resource. Recreate the agent outside your pipeline, and its role bindings are gone or, worse, recreated by hand with broader roles.
  • Preview features as foundations. Several pieces of these platforms are still in preview. Use them, but know which ones, and keep a fallback.

Frequently Asked Questions

Should an AI agent use a service account or its own identity?

Use the agent identity your platform provides when the agent runs there, because it is per agent, has no exportable keys and carries agent-specific governance. A plain service account or workload identity is still fine for a fixed pipeline that calls a model as one step, since that is an ordinary workload. Whatever you choose, give each agent its own principal instead of one shared identity for every agent.

What is Microsoft Entra Agent ID?

Microsoft Entra Agent ID is the generally available identity layer for AI agents in Microsoft Entra, licensed as part of Microsoft Agent 365. An agent identity blueprint holds the credentials and acts as a template, each agent gets its own agent identity, and every blueprint and agent identity needs a human sponsor. Conditional Access policies can target agents individually, by attribute or by blueprint.

What is Google Cloud Agent Identity?

Google Cloud Agent Identity gives each deployed agent a SPIFFE-based identity tied to the agent resource's lifecycle, generally available since April 2026. You grant IAM roles to a principal:// identifier for that agent instead of to a service account. Google documents that agent identities cannot be impersonated, do not allow long-lived keys, and receive access tokens bound to the agent's X.509 certificate.

How is AgentCore Identity different from an IAM role?

An IAM role decides which AWS APIs the agent can call. An AgentCore workload identity anchors the agent's access to third-party credentials: OAuth tokens and API keys held in the AgentCore Identity token vault, scoped to the agent and user that obtained them. Agents on AgentCore Runtime use both: the execution role for AWS calls and the workload identity for everything outside AWS.

How should an agent act on behalf of a user?

Exchange the user's token for a new token issued to the agent for one specific resource, using an on-behalf-of or token exchange flow. Never pass the user's original token to the model or forward it to tools, because its audience and scopes belong to your application, not to the agent. All three clouds offer a brokered path for this: Entra's agent on-behalf-of flow, Google's auth manager and AgentCore's token vault.

Can one identity provider cover agents in all three clouds?

Partly. One provider can be the source of truth for which agents exist and who sponsors them, and Entra Agent ID documents federation for agents running on AWS and Google Cloud. Each cloud still authorizes its own resources with its own IAM, so cross-cloud calls go through workload identity federation, and the agent needs a native principal in every cloud it touches.

Need help putting agents into production?

Identity is the control every other agent safeguard attaches to, and it is the one most often improvised. Our senior engineers design agent identities, token flows and cross-cloud federation that hold up under review, then stay on the pager for what we build. If we built it, we're on the pager.