Skip to main content

Capability Tokens

Capability tokens are Ed25519-signed JWTs that grant specific permissions to AI agents. They provide fine-grained, time-limited authorization that works in conjunction with UAPK manifests.

Overview

When an agent makes a request to the gateway, permissions are determined by the intersection of:

  1. The UAPK manifest constraints
  2. The capability token constraints (if provided)

This means a capability token can only restrict permissions further, never expand beyond what the manifest allows.

Token Structure

Capability tokens are JWTs with the following claims:

{
"iss": "gateway", // Issuer ID
"sub": "agent-123", // Agent ID
"org_id": "uuid", // Organization ID
"uapk_id": "my-agent", // UAPK manifest ID
"allowed_action_types": ["payment", "data_access"],
"allowed_tools": ["stripe_transfer", "email_send"],
"constraints": {
"amount_max": 1000.0,
"jurisdictions": ["US", "CA"],
"counterparty_allowlist": ["vendor-1", "vendor-2"]
},
"delegation_depth": 0,
"iat": 1702500000, // Issued at (Unix timestamp)
"exp": 1702503600, // Expires at (Unix timestamp)
"jti": "cap-abc123" // Unique token ID
}

Token Claims

ClaimDescription
issIssuer ID - either "gateway" or a registered issuer
subAgent ID the token is issued to
org_idOrganization the token belongs to
uapk_idUAPK manifest the token is bound to
allowed_action_typesAction types the agent can perform
allowed_toolsSpecific tools the agent can use
constraintsAdditional constraints (see below)
delegation_depthHow many times the token can be delegated (0 = no delegation)
iatIssued at timestamp
expExpiration timestamp
jtiUnique token identifier

Constraints

Constraints embedded in the token limit what the agent can do:

ConstraintDescription
amount_maxMaximum amount for financial operations
jurisdictionsAllowed jurisdiction codes (ISO country codes)
counterparty_allowlistOnly these counterparties are allowed
counterparty_denylistThese counterparties are blocked
expires_atHard expiration (separate from token expiry)

Issuing Tokens

Via API

# Issue a capability token
curl -X POST /v1/capabilities/issue \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "my-agent-instance",
"uapk_id": "my-agent",
"allowed_action_types": ["payment"],
"allowed_tools": ["stripe_transfer"],
"constraints": {
"amount_max": 500,
"jurisdictions": ["US"]
},
"expires_in_seconds": 3600
}'

Response:

{
"token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"token_id": "cap-abc123def456",
"issuer_id": "gateway",
"agent_id": "my-agent-instance",
"uapk_id": "my-agent",
"org_id": "uuid",
"issued_at": "2024-12-14T10:00:00Z",
"expires_at": "2024-12-14T11:00:00Z",
"allowed_action_types": ["payment"],
"allowed_tools": ["stripe_transfer"],
"constraints": {
"amount_max": 500,
"jurisdictions": ["US"]
}
}

Using Tokens

Include the token in gateway requests:

curl -X POST /v1/gateway/execute \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uapk_id": "my-agent",
"agent_id": "my-agent-instance",
"capability_token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"action": {
"type": "payment",
"tool": "stripe_transfer",
"params": {
"amount": 100,
"currency": "USD",
"recipient": "vendor-123"
}
}
}'

Registering External Issuers

Organizations can register external systems as capability issuers:

# Register an external issuer
curl -X POST /v1/capabilities/issuers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"issuer_id": "external-system-1",
"name": "External Authorization System",
"public_key": "base64-encoded-ed25519-public-key",
"description": "Our external auth system for agents"
}'

Tokens signed by registered issuers are verified using their public keys.

Getting the Gateway Public Key

# Get gateway's public key (for external verification)
curl /v1/capabilities/gateway-key
{
"issuer_id": "gateway",
"public_key": "base64-encoded-ed25519-public-key",
"algorithm": "EdDSA"
}

Revoking Issuers

If an external issuer's key is compromised, revoke it immediately:

curl -X POST /v1/capabilities/issuers/external-system-1/revoke \
-H "Authorization: Bearer $TOKEN"

Tokens from revoked issuers will no longer be accepted.

Security Considerations

Token Lifetime

  • Use short-lived tokens (1-8 hours for interactive use)
  • Use very short tokens (1-5 minutes) for one-time operations
  • Override tokens from approvals expire in 5 minutes by default

Principle of Least Privilege

Issue tokens with the minimum permissions needed:

// Good: Specific permissions
{
"allowed_action_types": ["data_access"],
"allowed_tools": ["read_customer_profile"],
"constraints": {
"counterparty_allowlist": ["customer-123"]
}
}

// Bad: Overly broad permissions
{
"allowed_action_types": [], // Empty = all types
"allowed_tools": [] // Empty = all tools
}

Key Rotation

  • Rotate the gateway keypair periodically
  • Keep old public keys available briefly for token verification during transition
  • Register new keys with any external systems that verify gateway tokens

Error Handling

Common token-related errors:

Error CodeDescription
capability_token_invalidToken signature verification failed
capability_token_expiredToken has expired
token_issuer_revokedIssuer has been revoked
token_agent_mismatchToken's sub doesn't match agent_id
token_org_mismatchToken's org_id doesn't match request
token_uapk_mismatchToken's uapk_id doesn't match request
token_action_type_not_allowedAction type not in token's allowed list
token_tool_not_allowedTool not in token's allowed list
token_amount_exceeds_capAmount exceeds token's amount_max
token_jurisdiction_not_allowedJurisdiction not in token's allowed list
token_counterparty_not_allowedCounterparty blocked by token

Next Steps