Skip to the content.

In previous posts, we explored direct authorization, user consent, token exchange, and other ways agents and resources obtain access. This flow covers a different problem: how one logical agent can safely operate through multiple delegates, each with its own signing key. This is where Agent Auth uses agent delegation and agent tokens.

← Back to index

The Distributed Identity Problem

Modern agents rarely run as a single process with a single key. Consider:

Each instance needs to act as the same logical agent, but naive approaches break down:

  1. Shared signing keys create one large blast radius.
  2. Separate agent identifiers fragment policy and user understanding.
  3. Bearer-style delegation loses proof-of-possession.

AAuth’s delegation model takes a different approach:

Roles in This Flow

This flow uses two agent-side roles:

The Flow

Phase 1: The Delegate Obtains an Agent Token

The delegate first asks the agent server for an agent token:

================================================================================
>>> DELEGATE REQUEST to https://agent.supply-chain.com/delegate/token
================================================================================
POST https://agent.supply-chain.com/delegate/token HTTP/1.1
Content-Type: application/json

[Body (143 bytes)]
{"sub": "delegate-1", "cnf_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "-XbMHZc393RgM8I3PFQqLYWLnOSC1KPCA1hYgOyAxVc", "kid": "delegate-key-1"}}
================================================================================

The delegate sends:

In a real deployment, this request would not be anonymous. The delegate still needs to authenticate to the agent server before the agent server will issue an agent token. AAuth leaves that authentication method out of scope so deployments can use whatever attestation or platform identity fits their environment. Common examples include:

So the important distinction is:

The agent server responds with an agent token:

================================================================================
<<< AGENT SERVER RESPONSE
================================================================================
HTTP/1.1 200 OK
Content-Type: application/json

[Body]
{
  "agent_token": "eyJhbGciOiJFZERTQSIsImtpZCI6ImtleS0xIiwidHlwIjoiYWdlbnQrand0In0...",
  "expires_in": 3600
}
================================================================================

The Agent Token Shape

For this flow, the agent token looks like this:

{
  "alg": "EdDSA",
  "kid": "key-1",
  "typ": "agent+jwt"
}
{
  "iss": "https://agent.supply-chain.com",
  "sub": "delegate-1",
  "jti": "8eb1e0fc-db74-4446-909d-664052a379c6",
  "cnf": {
    "jwk": {
      "kty": "OKP",
      "crv": "Ed25519",
      "x": "-XbMHZc393RgM8I3PFQqLYWLnOSC1KPCA1hYgOyAxVc",
      "kid": "delegate-key-1"
    }
  },
  "iat": 1774977290,
  "exp": 1774980890
}

The important parts are:

This means the delegate can say: “I am delegate delegate-1, acting for https://agent.supply-chain.com, and this is the specific key I’m allowed to use.”

Phase 2: The Delegate Accesses a Resource

With the agent token, the delegate can now call a resource that requires agent identity:

================================================================================
>>> DELEGATE REQUEST to https://important.resource.com/data-jwks
================================================================================
GET https://important.resource.com/data-jwks HTTP/1.1
Signature: sig=:ooGVsioU9vOZplVZgQFjCACPyIMQg9iLf7qFms-Owq4_4PAidGMS5bsG-Z2yMl2EdShZRfaaOAESypP1ABNxBg:
Signature-Input: sig=("@method" "@authority" "@path" "signature-key");created=1774977290
Signature-Key: sig=(scheme=jwt jwt="eyJhbGciOiJFZERTQSIsImtpZCI6ImtleS0xIiwidHlwIjoiYWdlbnQrand0In0.eyJpc3MiOiJo...")
================================================================================

The delegate signs the request with its own private key. The resource verifies:

  1. the agent+jwt signature using the parent agent server’s JWKS
  2. the token’s claims (iss, sub, exp, typ)
  3. the request signature using the key inside cnf.jwk
  4. that the request signature matches the key bound in the agent token

If all of that checks out, the resource grants access:

================================================================================
<<< RESOURCE RESPONSE
================================================================================
HTTP/1.1 200
content-length: 206
content-type: application/json

[Body (206 bytes)]
{"message":"Access granted","data":"This is protected data (identified via agent token)","scheme":"jwt","token_type":"agent+jwt","method":"GET","agent":"https://agent.supply-chain.com","agent_delegate":"delegate-1"}
================================================================================

Notice what the resource learns:

That gives the resource both a stable policy identity and per-delegate visibility for auditing or rate limiting.

Phase 3: Delegates and Auth Tokens

Delegation also matters when a resource requires authorization, not just identity. In that case, the delegate follows the same auth-token flow as any other caller, but presents the agent+jwt instead of proving identity via JWKS discovery.

Conceptually, that request looks like:

================================================================================
>>> DELEGATE REQUEST to https://auth-server.com/token
================================================================================
POST https://auth-server.com/token HTTP/1.1
Content-Type: application/json
Signature-Key: sig=(scheme=jwt jwt="eyJhbGciOiJFZERTQSIsImtpZCI6ImtleS0xIiwidHlwIjoiYWdlbnQrand0In0...")

[Body]
{"resource_token":"..."}
================================================================================

The auth server can then:

  1. validate the agent token against the parent agent’s JWKS
  2. validate the resource token
  3. verify the request signature against cnf.jwk
  4. issue an auth token that records both the parent agent and the delegate

That resulting auth token would include claims like:

{
  "iss": "https://auth-server.com",
  "aud": "https://important.resource.com",
  "agent": "https://agent.supply-chain.com",
  "agent_delegate": "delegate-1",
  "cnf": {
    "jwk": {
      "kty": "OKP",
      "crv": "Ed25519",
      "x": "-XbMHZc393RgM8I3PFQqLYWLnOSC1KPCA1hYgOyAxVc",
      "kid": "delegate-key-1"
    }
  },
  "scope": "data.read data.write"
}

That agent_delegate claim tells the resource exactly which delegate was responsible for the authorization.

For this flow, we focus on two concrete things:

It then notes that the same delegated identity can be used in the auth-token flow as well.

Why Delegation Matters

This solves a real operational problem for distributed agents:

That gives you a clean balance:

Summary

Agent delegation lets multiple workloads or devices act as one logical agent without sharing a signing key. The parent agent server issues short-lived agent+jwt tokens to delegates, each bound to the delegate’s own key. Resources can then verify both the parent agent identity and the delegate instance that made the request. This preserves proof-of-possession, supports per-delegate auditing and policy, and avoids the security problems of shared keys.

Where to Next

We’ve now covered:

After these flows, we have the main building blocks for putting AAuth into a real implementation.

In the next post, we look at clarification chat, where the auth server can ask the agent for additional context during a pending authorization flow.

← Back to index