Using client credentials grant flow to issue Agent identity tokens

Autonomous agents that act without a human user can authenticate using the client credentials grant flow. The issued token is permanently bound to a unique Agent ID, providing a per-agent audit trail and supporting lifecycle management.

The Client Credentials grant flow, combined with IBM Verify Agent Identity, issues every autonomous agent its own scoped credential that is permanently bound to a unique Agent ID. Every token, every API call, and every audit event is attributed to that single identity — from the day the agent is onboarded to the day it is decommissioned.

Key learnings

  1. Why autonomous agents need their own identity rather than a shared service account.
  2. How to configure an OAuth client for the client credentials grant and link it to an Agent ID.
  3. How to obtain a client credentials token that carries the Agent ID as a claim.
  4. What the resulting agent token looks like and what its identity claims mean.
  5. How to query IBM Verify events to trace all token and agent identity activity.

Audience

  • IAM administrators
  • Security architects
  • Application developers integrating autonomous agent flows with IBM Verify

Concepts used in this guide

Concept Description
Agent ID The persistent identity record for the agent in IBM Verify
Agent client The OAuth client used by the agent to authenticate itself via client credentials
Agent token The access token issued to the agent — carries sub=client_id and agent_id=AgentID
Token attribute mapping rule A rule on the OAuth client that injects the Agent ID as a custom claim in the issued token
Autonomous agent An agent that acts on its own authority, without a delegating human user

Prerequisites

  • An IBM Verify tenant with the Verify Agent Identity feature enabled. Contact IBM Support to enable the feature on your tenant.
  • Create a new agent identity or onboard an existing one in the IBM Verify tenant. See Onboarding an AI agent in IBM Verify for more details.
  • An API client such as Insomnia or Postman for running the token requests.
  • Familiarity with the OAuth 2.0 client credentials flow.

Agent identity in IBM Verify

IBM Verify manages AI agents as first-class identities — separate from human identities. Every agent onboarded in IBM Verify is assigned a unique Agent ID — a persistent, durable identifier that becomes the anchor for ownership, credentials, and audit events.

Property Detail
Decoupled from credentials The Agent ID is generated at onboarding, before any OAuth client is attached. Identity and credentials are separate concerns.
Linkage point All management events (onboarding, owner assignment, client attachment, policy changes) and all runtime events (token issuance, API calls) reference this single ID.
Traceability anchor The Agent ID is the answer to "which agent did this?" — across both the management plane and the runtime plane.

When onboarding an agent, you supply metadata that reflects operational intent, including fields such as name, type, agent owner, and tags. For the full list of fields, see Onboarding an AI agent in IBM Verify. IBM Verify returns an Agent ID that is used in all subsequent configuration steps.

Why client credentials for autonomous agents?

The client credentials grant is the OAuth flow for machine-to-machine communication where no human user is involved. Autonomous agents — scheduled pipelines, background processors, and service-to-service callers — act entirely on their own authority. The client credentials grant makes this explicit: the token's sub is the client (the agent), not a user.

To make the Agent ID visible in every token this client issues, add a token attribute mapping rule that injects the Agent ID as a custom claim (agent_id). Resource server APIs and audit systems then have a stable, identity-anchored value to work with.

Configure the OAuth client

The client credentials flow for an autonomous agent requires a single OAuth client linked to the Agent ID in IBM Verify.

Field Value
Grant type client_credentials
Attached to agent Yes — linked via entityId
Purpose tag agent_id
Token role Issues an agent token carrying agent_id=AgentID as a custom claim

Create the client using one of the methods below. Save agent_client_id and agent_client_secret.

Method A — Dynamic Client Registration (DCR)

DCR is the preferred approach for programmatic, automated agent onboarding pipelines.

The scope field in the DCR request defines the maximum set of scopes this client is ever permitted to request. When the agent later calls /oauth2/token, it may request any subset of these scopes — but never more. This is the primary mechanism for restricting what an autonomous agent is allowed to do.

curl --request POST \
  --url https://<tenant>.verify.ibm.com/oauth2/register \
  --header 'Authorization: Bearer <registration-access-token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "client_name": "My Autonomous Agent - Identity Client",
  "grant_types": ["client_credentials"],
  "scope": "<space-separated list of allowed scopes>",
  "extension": {
    "entity_id": "<agent-id>",
    "entity_type": "agent"
  }
}'

Method B — Applications API (create new application)

The following snippet only shows the agent-linkage fields. For the full list of required fields see OpenID Connect applications in IBM Verify.

curl --request POST \
  --url https://<tenant>.verify.ibm.com/v1.0/applications \
  --header 'Authorization: Bearer <access-token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "... other application fields ...": "...",
  "providers": {
    "oidc": {
      "properties": {
        "... other oidc properties ...": "...",
        "entityType": "agent",
        "entityId": "<agent-id>"
      }
    }
  },
  "tags": [
    "... other tags ...",
    "purpose=agent_id"
  ]
}'

Method B — Applications API (patch existing application)

If the agent needs to be linked to an existing application:

curl --request PATCH \
  --url https://<tenant>.verify.ibm.com/v1.0/applications/<application-id> \
  --header 'Authorization: Bearer <access-token>' \
  --header 'Content-Type: application/json' \
  --data '[
  {
    "op": "add",
    "path": "/providers/oidc/properties",
    "value": {
      "entityType": "agent",
      "entityId": "<agent-id>"
    }
  },
  {
    "op": "add",
    "path": "tags",
    "value": "purpose=agent_id"
  }
]'

Configure the token attribute mapping rule

Add a token attribute mapping rule on the application that injects the agent_id attribute into every token the client issues. For the full attribute mapping reference see OpenID Connect introspect, ID token, and user info mapping.

Attribute name Value
agent_id '<agent-id>'
Introspect mapping configuration in IBM Verify — agent_id mapped to the Agent ID value

Once configured, every token issued by this client contains:

{
  "sub":       "<agent_client_id>",
  "agent_id":  "<agent-id>",
  "client_id": "<agent_client_id>"
}

Resource server APIs and the IBM Verify Events API use agent_id as the stable, identity-anchored value for this agent.

Run the flow

Client credentials flow for autonomous agents

Step 1 — Agent obtains an agent token

The agent authenticates directly against IBM Verify using its own agent_client_id and agent_client_secret. No user is involved — this token asserts the agent's own identity. For the full token endpoint reference see POST /oauth2/token.

The agent should request only the scopes it needs for the specific operation — not the full set registered on the client. IBM Verify issues a token scoped to exactly what was requested, provided those scopes fall within the allowed set defined at client registration.

POST /oauth2/token

grant_type=client_credentials
client_id=<agent_client_id>
client_secret=<agent_client_secret>
scope=<scopes required for this operation>

The response contains an access token. Decoded, its claims include:

{
  "sub":       "<agent_client_id>",
  "agent_id":  "<agent-id>",
  "client_id": "<agent_client_id>",
  "scope":     "<scopes requested>",
  "iss":       "https://<tenant>.verify.ibm.com/oauth2",
  "iat":       1720000000,
  "exp":       1720003600
}

The two identity claims are the core of the autonomous agent pattern:

  • sub is the OAuth client ID — the agent's credential identity, used for token validation.
  • agent_id is the Agent ID — the identity-anchored value, used for audit correlation and lifecycle management. Its value is injected by the token attribute mapping rule configured in the Configure the OAuth client section.

Step 2 — Agent calls the resource server

POST /v1/<resource-action>
Authorization: Bearer <access-token>
Host: <resource-server-host>

The resource server (or the Identity Runtime Proxy placed ahead of it) validates the token and confirms:

  • sub is a known OAuth client — the credential is valid and has not been revoked.
  • agent_id is a known Agent ID in IBM Verify — confirming the action was performed by an onboarded, tracked agent.
  • The token was issued to a client whose lifecycle is managed: if the agent is suspended in IBM Verify, its linked OAuth client is disabled and can no longer issue tokens, immediately blocking access.
  • scope covers the requested resource action.

Agent lifecycle and credential management

Binding the OAuth client to an Agent ID means the agent's operational status is enforced at token issuance.

Action Effect on the agent token
Agent active Client credentials requests succeed; tokens are issued normally
Agent suspended The linked OAuth client is disabled; token requests fail immediately — no new tokens can be issued
Agent reactivated The linked client is re-enabled; token requests resume
Client credential rotated Only the client_secret changes; the agent_id claim and Agent ID remain stable

This means revoking or pausing an autonomous agent is a single operation in IBM Verify — it does not require hunting down shared service account passwords or touching resource server API configurations.

Traceability — querying events by Agent ID

The Agent ID is the single correlation key across two planes of activity: the management plane (agent identity operations) and the runtime plane (token issuance).

Management-plane events

To retrieve all management-level events for a specific agent, query the Events API with:

Filter parameter Value
filter_key data.id
filter_value <agent-id>

This surfaces:

  • Agent onboarded: timestamp, submitting user, metadata snapshot
  • Owner assigned or changed
  • Agent client created and linked
  • Agent suspended or activated — when an agent is suspended, its linked OAuth client is disabled and can no longer issue tokens, immediately blocking the client credentials flow

Runtime-plane events

To retrieve all token activity for a specific agent, query the Events API with:

Filter parameter Value
filter_key data.entity_id
filter_value <agent-id>

This surfaces:

  • Agent token issued — agent authenticating as itself using client credentials. See Agent obtains an agent token for more details.
  • Token issuance failures — if the agent is suspended or its client secret is invalid

With the Agent ID represented as data.id in management events and data.entity_id in token events, the same identifier can be used to trace an agent's complete lifecycle, from onboarding to every autonomous action it performs. No custom correlation logic is required. Through this you can answer:

  • Who onboarded the agent and when
  • Who owns it and approved its operation
  • Every token it has ever been issued and the scope of each
  • Any ownership, policy, or suspension changes in the agent's history