Skip to content

Latest commit

 

History

History
executable file
·
454 lines (396 loc) · 12.4 KB

File metadata and controls

executable file
·
454 lines (396 loc) · 12.4 KB

A2A Protocol: Technical Documentation for Developers

Related Documentation:

Core Concepts

The Agent-to-Agent (A2A) protocol is an open standard for enabling communication between opaque agentic systems. Here's a comprehensive technical overview to help you get oriented:

Architecture

A2A follows a client-server model with three key actors:

  • User: The end-user (human or service) using an agentic system
  • Client: The entity requesting action from an agent on behalf of the user
  • Remote Agent (Server): The "blackbox" agent implementing the A2A server

Transport & Protocol

  • Uses HTTP for transport with JSON-RPC 2.0 as the data exchange format
  • Supports Server-Sent Events (SSE) for streaming updates
  • Push notifications for disconnected operation

Core Objects

Agent Card

interface AgentCard {
  name: string;                    // Human-readable name
  description: string;             // Optional description
  url: string;                     // Base URL for the agent
  provider?: {                     // Optional provider info
    organization: string;
    url: string;
  };
  version: string;                 // Agent version
  documentationUrl?: string;       // Optional documentation URL
  capabilities: {                  // Supported features
    streaming?: boolean;           // SSE support
    pushNotifications?: boolean;   // Push notification support
    stateTransitionHistory?: boolean; // Status change history
  };
  authentication: {                // Auth requirements (OpenAPI-compatible)
    schemes: string[];             // e.g., "Basic", "Bearer", "OAuth2"
    credentials?: string;          // For private cards
  };
  defaultInputModes: string[];     // Supported input MIME types
  defaultOutputModes: string[];    // Supported output MIME types
  skills: AgentSkill[];            // Available capabilities
}

Agent Skill

interface AgentSkill {
  id: string;                      // Unique skill identifier
  name: string;                    // Human-readable name
  description?: string;            // Optional description
  tags?: string[];                 // Categorization tags
  examples?: string[];             // Example prompts/queries
  inputModes?: string[];           // Override default input modes
  outputModes?: string[];          // Override default output modes
}

Task

interface Task {
  id: string;                      // Unique task identifier
  sessionId: string;               // Session grouping multiple tasks
  status: TaskStatus;              // Current state
  history?: Message[];             // Previous messages
  artifacts?: Artifact[];          // Results generated by the agent
  metadata?: Record<string, any>;  // Extension metadata
}

interface TaskStatus {
  state: TaskState;
  message?: Message;               // Optional status message
  timestamp?: string;              // ISO datetime
}

type TaskState = "submitted" | "working" | "input-required" | 
                "completed" | "canceled" | "failed" | "unknown";

Message

interface Message {
  role: "user" | "agent";          // Who sent the message
  parts: Part[];                   // Content pieces
  metadata?: Record<string, any>;  // Extension metadata
}

Part

Represents a piece of content, which can be:

// Text part
interface TextPart {
  type: "text";
  text: string;
  metadata?: Record<string, any>;
}

// File part
interface FilePart {
  type: "file";
  file: {
    name?: string;
    mimeType?: string;
    // One of:
    bytes?: string;  // base64 encoded content
    uri?: string;    // reference to content
  };
  metadata?: Record<string, any>;
}

// Data part (structured)
interface DataPart {
  type: "data";
  data: Record<string, any>;
  metadata?: Record<string, any>;
}

Artifact

interface Artifact {
  name?: string;                   // Optional name
  description?: string;            // Optional description
  parts: Part[];                   // Content pieces
  metadata?: Record<string, any>;  // Extension metadata
  index: number;                   // Position in result set
  append?: boolean;                // For streaming updates
  lastChunk?: boolean;             // Final chunk indicator
}

Push Notification

interface PushNotificationConfig {
  url: string;                     // Callback URL
  token?: string;                  // Unique task/session token
  authentication?: {               // Auth requirements
    schemes: string[];
    credentials?: string;
  };
}

Key Operations

Agent Discovery

  • Agents host their AgentCard at https://{base-url}/.well-known/agent.json
  • Clients can use DNS resolution and HTTP GET to retrieve the card
  • Enterprise environments may use private registries/catalogs

Task Operations

Create/Update Task

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/send",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "message": {
      "role": "user",
      "parts": [{
        "type": "text",
        "text": "tell me a joke"
      }]
    },
    "metadata": {}
  }
}

Get Task

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/get",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "historyLength": 10,
    "metadata": {}
  }
}

Cancel Task

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/cancel",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "metadata": {}
  }
}

Set Push Notification

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/pushNotification/set",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "pushNotificationConfig": {
      "url": "https://example.com/callback",
      "authentication": {
        "schemes": ["jwt"]
      }
    }
  }
}

Get Push Notification Config

// Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/pushNotification/get",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64"
  }
}

Streaming Operations

Create Streaming Task

// Request
{
  "method": "tasks/sendSubscribe",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "message": {
      "role": "user",
      "parts": [{
        "type": "text",
        "text": "write a long paper"
      }]
    }
  }
}

// Streaming responses
data: {
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "status": {
      "state": "working",
      "timestamp": "2025-04-02T16:59:25.331844"
    },
    "final": false
  }
}

data: {
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",    
    "artifact": {
      "parts": [
        {"type": "text", "text": "<content chunk 1>"}
      ],
      "index": 0,
      "append": false,      
      "lastChunk": false
    }
  }
}

Resubscribe to Task

// Request
{
  "method": "tasks/resubscribe",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "metadata": {}
  }
}

Multi-turn Conversations

A2A supports complex multi-turn conversations through its task state management:

  1. Client sends initial task request
  2. Agent responds with input-required status when more input is needed
  3. Client sends additional input using the same task ID
  4. Process repeats until task is completed
// Response with input-required
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "sessionId": "c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status": {
      "state": "input-required",
      "message": {
        "role": "agent",
        "parts": [{
          "type": "text",
          "text": "Select a phone type (iPhone/Android)"
        }]
      }
    },
    "metadata": {}
  }
}

Structured Output

A2A supports requesting and receiving structured data:

// Request for structured output
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "tasks/send",
  "params": {
    "id": "de38c76d-d54c-436c-8b9f-4c2703648d64",
    "message": {
      "role": "user",
      "parts": [{
        "type": "text",
        "text": "Show me a list of my open IT tickets",
        "metadata": {
          "mimeType": "application/json",
          "schema": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ticketNumber": { "type": "string" },
                "description": { "type": "string" }
              }
            }
          }
        }
      }]
    }
  }
}

Error Handling

Standard JSON-RPC error codes plus A2A-specific codes:

Error Code Message Description
-32700 JSON parse error Invalid JSON was sent
-32600 Invalid Request Request payload validation error
-32601 Method not found Not a valid method
-32602 Invalid params Invalid method parameters
-32603 Internal error Internal JSON-RPC error
-32001 Task not found Task not found with the provided id
-32002 Task cannot be canceled Task cannot be canceled by the remote agent
-32003 Push notifications not supported Push Notification is not supported by the agent
-32004 Unsupported operation Operation is not supported
-32005 Incompatible content types Incompatible content types between client and an agent

Error response format:

interface ErrorMessage {
  code: number;
  message: string;
  data?: any;
}

Authentication & Security

  • Authentication is handled at the HTTP level, not in A2A payloads
  • Follows OpenAPI Authentication specification
  • Supports OAuth, JWT, Basic Auth, API keys, etc.
  • Uses standard HTTP response codes (401, 403) for auth failures

Push Notification Security

For secure push notifications:

  1. Challenge Verification: Agents should verify push notification URLs by issuing a GET challenge with a validation token
  2. Authentication: Use JWT, OAuth, or symmetric key signing for notification authenticity
  3. Replay Prevention: Use timestamps in push notifications to prevent replay attacks
  4. Key Rotation: Implement key rotation for long-lived notification channels

Implementation Considerations

  1. Opaque Execution: Agents don't share internal thoughts/plans/tools
  2. Enterprise Ready: Design for auth, security, privacy, tracing, monitoring
  3. Async First: Support for very long-running tasks
  4. Modality Agnostic: Handle different content types appropriately
  5. Extensibility: Use metadata fields for custom extensions

MCP Relationship

  • Model Context Protocol (MCP) is complementary to A2A
  • Use MCP for connecting agents to tools (function calling)
  • Use A2A for agent-to-agent communication
  • Model A2A agents as MCP resources represented by their AgentCard

Best Practices

  1. Implementation Discovery: Support standard URL patterns (/.well-known/agent.json)
  2. Proper Status Updates: Keep clients informed with appropriate task states
  3. Secure Authentication: Implement industry-standard authentication
  4. Robust Error Handling: Provide meaningful error messages
  5. Proper Content Negotiation: Honor client's requested input/output modes
  6. Clean Task Management: Implement retention policies for completed tasks
  7. Streaming Efficiently: Use chunked responses efficiently
  8. Push Notification Verification: Always verify push notification endpoints
  9. (Advanced) Task Decomposition: For complex tasks, consider implementing internal planning logic to break down the request into smaller sub-tasks that can be executed sequentially or in parallel, potentially involving multiple tools or remote agents. Synthesize the results before responding to the original client.
  10. (Advanced) Intent Clarification: Before committing to complex execution plans, consider adding a step where the agent verifies its understanding of an ambiguous request by asking the client for clarification (e.g., using the input-required state).

Implementation Examples

Sample implementations are available in the A2A GitHub repository for:

  • Google Agent Developer Kit (ADK)
  • CrewAI
  • LangGraph
  • Genkit

Each sample demonstrates different aspects of the A2A protocol and can serve as a reference for your implementation.