Who Is Actually Acting?
Understanding act, may_act, and the identities hidden inside an agent request.
A detour from The Agent Authorization Standard We Already Had, for the moment "the agent's token" stops being a good enough answer.
Agent authorization gets confusing because we keep calling everything "the agent's token." That phrase hides the exact questions the token needs to answer: whose authority is being used, which agent is exercising it, and where that authority is accepted.
This is the piece of OAuth delegation I wish more people discussed. Once you separate the subject from the actor, the whole model becomes much easier to reason about.
Subject, Actor, and Audience
If JSON Web Token claims are unfamiliar, I cover the header, payload, and signature in A JWT Is Not Authorization. Most of what follows lives in the JWT payload, or JWT Claims Set.
Bear with me here. The authorization model becomes much easier to reason about if we stop saying "the agent's token" and ask three separate questions:
Subject: Who owns the authority?
Actor: Who is currently exercising that authority?
Audience: Where may that authority be used?
If you buy a ticket for a Eurowings flight and try to use it to enter the Louvre, they are going to laugh at you. The ticket may be genuine. The audience is still wrong.
In Nadia's case, the same three questions produce three different token shapes. The examples below show only the relevant claims from each payload.
The personal assistant can act as itself, that is, with its own authority:
{
"sub": "personal-assistant",
"aud": "chat-mcp",
"scope": "messages.read"
}
That is fine when the work genuinely belongs to the machine. A bot posting its own health status does not need to pretend a human clicked the button.
The personal assistant can impersonate Nadia, which is the case with many systems currently:
{
"sub": "nadia",
"aud": "chat-mcp",
"scope": "messages.read"
}
This impersonation can still be tightly scoped. Impersonation does not automatically mean every permission Nadia has. The problem is that the chat MCP sees Nadia and only Nadia. It cannot tell whether Nadia read the thread directly, whether her personal assistant did it, or whether somebody copied the token into a curl command at 02:00.
Or, and this is where things get interesting, the personal assistant can act for Nadia through explicit delegation:
{
"sub": "nadia",
"act": {
"sub": "personal-assistant"
},
"aud": "chat-mcp",
"scope": "messages.read"
}
Now the token says two things at once: Nadia owns the authority, and the personal assistant is currently exercising it. act is the key here, and it is fundamental to the discussion we are going to have here.
A delegate cannot walk into a bank, announce that a friend sent them, and expect access to the savings. Banks remain oddly attached to proof.
Nadia's personal assistant faces the same requirement. It needs its own identity and a way to prove it. A client_id is not enough by itself. It identifies a client registration, but the client still needs a credential or another authentication mechanism to prove that it controls that identity.
That identity could be an OAuth client, a workload identity, or something based on a system such as SPIFFE. The specific mechanism matters operationally, but the logical requirement is simple: the agent must be able to prove that it is itself before an authorization server can name it as an actor.
act Tells Us Who Is Acting
The act claim is a central piece in this puzzle:
{
"sub": "nadia",// nadia remains the primary authority
"act": {
"sub": "personal-assistant" // assistant working for Nadia
},
"aud": "chat-mcp",
"scope": "messages.read"
}
The top-level token is about Nadia. The nested object identifies the personal assistant as the current actor. This is delegation in a form the chat MCP can inspect and log.
RFC 8693 also defines may_act. It makes a statement that a party is eligible to become the actor:
{
"sub": "nadia",
"aud": "personal-assistant",
"may_act": {
"sub": "personal-assistant" // personal assistant is allowed to assume act
}
}
The easiest mental model I have found is this:
actor authentication = proves who the personal assistant is
may_act = puts the personal assistant on the guest list
act = records the personal assistant in the visitor book
But beware: may_act is not mandatory, and I am not a huge fan. In many systems, this is better handled on the authorization server. An auth server can keep the same relationship in server-side policy, user consent, registered client relationships, or organizational rules. It becomes useful when the eligibility decision needs to travel inside a token to another trusted exchange service.
Neither claim grants a capability on its own. act identifies the actor. may_act identifies an eligible actor. Audience, scope, expiry, issuer, and authorization-server policy still do the actual work of bounding authority.
Why This Distinction Matters
Without act, the resource can identify Nadia or the personal assistant, but not both roles at the same time. With it, the system can preserve Nadia as the owner of the authority while applying actor-specific policy to the software performing the action.
may_act can make the eligibility relationship portable, but it remains optional. The authorization server can keep that decision in consent, registered-client relationships, workload policy, or organizational rules instead.
The important part is not adding more claims because claims are fashionable. It is giving the resource enough trustworthy context to answer a simple question: who is actually doing this?