+
+
+
+
+
+
+
+
Blog/Guides

Is the Agent Acting for Itself or on Behalf of a User?

BPBinoy Perera

How an app tells, in code, whether an AI agent is acting for itself or on behalf of a user: the AgentID principal model, delegated access through WorkOS auth.md and Auth0 Token Vault, workload identity such as Google Cloud Agent Identity, and what revocation and accountability mean in each.

Guide
Guides
AgentID
delegated-access
agent-identity
TL;DR

Every request an AI agent makes is either on its own account or on someone else's, and an app can tell which by reading the token rather than guessing. This post shows the check in code, what revoking access means under each model, where workload identity fits in, and who is accountable in each case.

An app can tell whether an AI agent is acting for itself or on behalf of a user by reading who the token names as its subject. If the subject is the agent, and the token says it is an agent, the agent is acting for itself; if the subject is a person and the agent only appears as the client holding the token, it is acting on that person's behalf.

With AgentID, the sign-in for AI agents from AgentMail, the answer is always the first one. That is a product choice, not a universal rule, and plenty of good systems are built on the second. The difficulty for an app is that both arrive as bearer tokens over the same kind of request, so the distinction has to be read out of the token's claims. Get it wrong and you bill the wrong party, revoke the wrong thing, or hold the wrong person accountable.

How do you tell the two apart in code?

You tell them apart by checking the issuer, the subject and, for AgentID, the actor_type claim. The conceptual difference between the models is laid out in agent owner verification vs end-user authentication, and the vocabulary in the agent identity terminology explainer; this section is the code.

// Illustrative. Classify a verified identity by what its token says.
type Claims = Record<string, unknown>

function whoIsActing(claims: Claims) {
    if (claims.iss === 'https://auth.agentid.com' && claims.actor_type === 'agent') {
        // Principal: the agent is the subject; the owner is a separate claim.
        return { model: 'agent-as-itself', agent: claims.sub, owner: claims.owner_sub ?? null }
    }
    // Anything else: the subject is whoever your identity provider says it is,
    // usually a person, with the agent visible only as the client.
    return { model: 'on-behalf-of-subject', subject: claims.sub }
}

Run a check like this only after the token's signature, issuer and audience have been verified. An unverified claim is only something the sender wrote, and an agent that could set its own actor_type could claim to be anything. The AgentID branch holds for every token the issuer mints, because every subject it issues is an agent inbox and actor_type is always the literal "agent". The owner, when your app is allowed to see it, travels as a claim beside the agent rather than as the subject. The second branch is deliberately loose. A delegated token names the user, and how it records the agent varies by provider, so check your provider's documentation for the field it uses.

What does each model mean for revocation?

Revocation means cutting off a key in one model and cutting off a grant in the other, and the difference shows up in what else stops working. The table compares the three models an app is likely to meet.

QuestionPrincipal (AgentID)Delegate (WorkOS auth.md, Auth0 Token Vault)Workload identity (Google Cloud Agent Identity)
Who is the subject?The agentThe user the agent works forThe workload running the agent
What credential does the app see?An ES256-signed OIDC id_tokenA short-lived access token tied to the userA SPIFFE identity and X.509 certificate
What does revoking stop?New sign-ins with that agent's key, at every app; nothing elseThat grant; revoking the user stops everything the user doesGoverned by the platform that issued the certificate
Who is accountable?The owner, as a claim registered apps can requestThe user, who is the accountOutside this credential; it names the workload

In the principal model, revoking one agent's key leaves the owner's own accounts and their other agents untouched, but it doesn't sign the agent out of apps it is already in; each app's session runs to its own limit. In the delegate model, the grant is the unit. WorkOS describes the credential auth.md issues as "a scoped access token tied to the user, short-lived and revocable", and Auth0 describes Token Vault handing the agent "a temporary, short-lived access token only when it needs to perform a specific task". Revoking that grant is clean. Revoking the user takes every agent they run with it.

Where does workload identity fit?

Workload identity fits underneath both models, at the infrastructure layer rather than at an app's login page. Google Cloud Agent Identity, generally available since August 2026, gives agents on Google's platform a SPIFFE identity and an X.509 certificate for authenticating to infrastructure.

That answers "which workload is calling", which is the right question inside a platform you run. It isn't the question a SaaS app asks when an agent arrives at its sign-up form from outside. The two also fail differently. A workload identity that leaks exposes the infrastructure it was scoped to; an AgentID sign-in key that leaks reaches only that one agent's sign-ins, because each key works only for its own agent. An agent can reasonably hold both: a workload identity for the infrastructure it runs on, and an AgentID for the apps it signs in to.

Who is accountable in each model?

In the principal model the accountable person is the agent's owner, delivered as a claim. Any app that requests profile receives owner_sub, which every agent with the same owner shares, and a registered app that requests the owner scopes also receives owner_name and owner_email. If the agent isn't allowed to share its owner, it can't finish that sign-in alone and the organization owner approves it.

In the delegate model the accountable person is the user, because the user is the account and the agent borrows their authority. That is the right shape when an agent works inside a person's own tools. Microsoft Entra Agent ID takes a principal approach inside a tenant and records accountability there: "Sponsors provide business accountability for agents, making lifecycle decisions without technical administrative access."

Neither model is wrong, and an app can accept both, as long as its code reads which one each token represents. The failure to avoid is treating a delegated token as the agent's own account, or an agent's own sign-in as a person, because limits, bills and bans then land on the wrong party. The claim reference is in the AgentID docs, and the agent builder's view of the same choice is on the AgentID page on AgentMail.

AgentID gives your agent a verified identity and its own email address. Free for apps to add.

FAQ

Let your agent sign in. Give it an AgentID and its own email address.