Skip to content

RFC: Agent-to-Agent (A2A) Protocol Support #517

@lakhansamani

Description

@lakhansamani

RFC: Agent-to-Agent (A2A) Protocol Support

Phase: 4 — AI-Era Auth
Priority: P2 — Medium
Estimated Effort: Medium
Depends on: M2M Auth (#509), Token Exchange (#521 — to be created)


Problem Statement

Google's Agent-to-Agent (A2A) protocol (backed by 50+ partners including Salesforce, SAP, Atlassian) defines how AI agents discover, authenticate, and communicate with each other. Authorizer can serve as the identity backbone for agent ecosystems — issuing agent identities, managing agent-to-agent trust, and auditing agent actions. No self-hosted auth platform currently offers this.


Proposed Solution

1. Agent Identity via Service Accounts

Agents are registered as specialized M2M applications (extends #509) with agent-specific metadata:

Enhanced Application schema (add fields to existing Application from #509):

// Additional fields on Application schema:
AgentType       string `json:"agent_type" gorm:"type:varchar(50)"`           // "ai_agent", "service", "automation"
AgentCardURL    string `json:"agent_card_url" gorm:"type:text"`              // URL where agent card is published
Capabilities    string `json:"capabilities" gorm:"type:text"`                // JSON array of capability descriptors
DelegationRules string `json:"delegation_rules" gorm:"type:text"`            // JSON: which agents/scopes this agent can delegate to
MaxDelegationDepth int `json:"max_delegation_depth" gorm:"default:3"`        // prevent infinite delegation chains

2. Agent Card Generation

A2A protocol requires agents to publish an Agent Card at /.well-known/agent.json.

Authorizer generates Agent Cards for registered agents:

New endpoint: GET /.well-known/agents/:client_id/agent.json

{
    "name": "billing-agent",
    "description": "Handles billing and invoice operations",
    "url": "https://billing-agent.example.com",
    "provider": {
        "organization": "Acme Corp",
        "url": "https://acme.com"
    },
    "version": "1.0.0",
    "capabilities": {
        "streaming": false,
        "pushNotifications": false,
        "stateTransitionHistory": true
    },
    "authentication": {
        "schemes": ["OAuth2"],
        "credentials": null
    },
    "defaultInputModes": ["text/plain", "application/json"],
    "defaultOutputModes": ["text/plain", "application/json"],
    "skills": [
        {
            "id": "create-invoice",
            "name": "Create Invoice",
            "description": "Creates a new invoice for a customer",
            "inputModes": ["application/json"],
            "outputModes": ["application/json"]
        }
    ]
}

GraphQL admin API for agent card configuration:

type Mutation {
    _update_agent_card(params: UpdateAgentCardInput!): Application!
}

input UpdateAgentCardInput {
    application_id: ID!
    agent_type: String
    capabilities: Map
    skills: [AgentSkillInput!]
}

3. Agent-Specific OAuth Scopes

Scopes for agent operations:

Scope Purpose
agent:invoke Invoke another agent's skills
agent:delegate Delegate a task to another agent on behalf of a user
agent:read_context Read shared context/state from another agent
agent:write_context Write to shared context
agent:discover Discover available agents and their capabilities

These scopes are enforced when agents present tokens to each other.

4. Short-Lived Agent Tokens

Agent-to-agent tokens have intentionally short lifetimes to minimize blast radius:

  • Default TTL: 5 minutes (configurable per agent)
  • Max TTL: 30 minutes
  • Automatic refresh via client_credentials grant (agents re-authenticate frequently)
  • No refresh tokens for agent-to-agent flows
// In token generation for agent clients:
if app.AgentType != "" {
    // Enforce short TTL
    ttl := min(app.TokenExpiresIn, maxAgentTokenTTL)
    claims["exp"] = time.Now().Add(time.Duration(ttl) * time.Second).Unix()
    claims["agent_type"] = app.AgentType
    claims["grant_type"] = "client_credentials"
}

5. Token Exchange for Agent Delegation (RFC 8693)

When Agent A needs to act on behalf of a user through Agent B:

POST /oauth/token
    grant_type=urn:ietf:params:oauth:grant-type:token-exchange
    subject_token={user's access token}
    subject_token_type=urn:ietf:params:oauth:token-type:access_token
    requested_token_type=urn:ietf:params:oauth:token-type:access_token
    audience={Agent B's client_id}
    scope=agent:invoke

Response: A new token scoped for Agent B, with delegation chain:

{
    "sub": "user_123",
    "act": {
        "sub": "app_agent_a",
        "act": {
            "sub": "app_agent_b"
        }
    },
    "scope": "agent:invoke",
    "aud": "app_agent_b",
    "delegation_depth": 2,
    "original_actor": "user_123"
}

Delegation chain tracking: The act (actor) claim creates a verifiable chain showing who delegated to whom. max_delegation_depth prevents infinite chains.

6. Agent Audit Trail

All agent actions logged with enhanced metadata:

auditProvider.Log(ctx, audit.AuditEvent{
    ActorID:      agentClientID,
    ActorType:    "agent",
    Action:       "agent.invoked",
    ResourceType: "agent",
    ResourceID:   targetAgentClientID,
    Metadata: map[string]interface{}{
        "delegating_user_id": originalUserID,
        "skill_invoked":      "create-invoice",
        "scope_used":         "agent:invoke",
        "delegation_depth":   2,
        "delegation_chain":   []string{"user_123", "app_agent_a", "app_agent_b"},
    },
})

7. Agent Discovery Endpoint

New endpoint: GET /agents — lists registered agents (filtered by capabilities)

{
    "agents": [
        {
            "client_id": "app_billing_agent",
            "name": "Billing Agent",
            "description": "Handles billing operations",
            "agent_card_url": "https://auth.example.com/.well-known/agents/app_billing_agent/agent.json",
            "capabilities": ["create-invoice", "get-balance"],
            "authentication": {"type": "oauth2", "token_endpoint": "https://auth.example.com/oauth/token"}
        }
    ]
}

Requires agent:discover scope.


CLI Configuration Flags

--enable-agent-auth=false                  # Enable A2A features
--agent-token-default-ttl=300              # Default agent token TTL (5 min)
--agent-token-max-ttl=1800                 # Max agent token TTL (30 min)
--agent-max-delegation-depth=3             # Maximum delegation chain depth

Testing Plan

  • Integration test: agent registration with agent card generation
  • Test agent-to-agent token exchange with delegation chain
  • Test delegation depth enforcement (reject at max depth)
  • Test short-lived token TTL enforcement
  • Test agent audit trail captures full delegation chain
  • Test agent discovery endpoint with scope filtering

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions