A2A Protocol
The Agent-to-Agent (A2A) protocol enables agents to communicate with each other using a standardized JSON-RPC 2.0 interface. It defines how agents are discovered, how tasks are created and managed, and how messages flow between client and server agents.
Protocol Foundation
A2A is built on JSON-RPC 2.0 over HTTP. Every request is a JSON-RPC call with a method name and params, and every response contains a result or error.
{
"jsonrpc": "2.0",
"method": "message/send",
"id": "req-001",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "Analyze this repository" }]
}
}
}Key protocol properties:
- Transport: HTTP POST
- Format: JSON-RPC 2.0
- Streaming: Server-Sent Events (SSE) via
message/stream - Protocol Version: 0.3.0
Agent Card (Discovery)
Every A2A agent publishes an Agent Card at /.well-known/agent.json. This is the entry point for discovery — clients fetch the Agent Card to learn what the agent does, how to authenticate, and what capabilities it supports.
GET https://my-agent.fly.dev/.well-known/agent.json{
"name": "GitHub Repo Analyzer",
"description": "Analyzes GitHub repositories for code complexity, dependencies, and security vulnerabilities.",
"protocolVersion": "0.3.0",
"version": "1.0.0",
"url": "https://my-agent.fly.dev/api/a2a",
"skills": [
{
"id": "analyze-repo",
"name": "Analyze Repository",
"description": "Analyzes a GitHub repository and returns a structured report.",
"tags": ["github", "analysis", "security", "dependencies"],
"inputModes": ["text/plain"],
"outputModes": ["text/plain"]
}
],
"capabilities": {
"streaming": true,
"extensions": [
{
"uri": "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2",
"required": true
}
]
}
}The Agent Card contains:
| Field | Description |
|---|---|
name | Human-readable agent name |
description | What the agent does |
protocolVersion | A2A protocol version (e.g., "0.3.0") |
url | The A2A endpoint URL |
skills | Array of capabilities the agent offers |
capabilities | Streaming support and extensions |
securitySchemes | Authentication methods |
For complete Agent Card configuration, see the Agent Card Guide.
Task States
A Task is the central unit of work in A2A. It tracks the lifecycle of a request from creation to completion.
| State | Description |
|---|---|
submitted | Task has been created and is queued |
working | Agent is actively processing |
completed | Task finished successfully |
failed | Task encountered an error |
input-required | Agent needs more information from the client (used for X402 payment requests) |
canceled | Task was canceled by the client |
The input-required state is particularly important for X402 payments. When an agent requires payment, it sets the task state to input-required with payment requirements in the metadata. The client responds with a payment submission, and the task transitions to working then completed.
JSON-RPC Methods
message/send
Send a message and receive a complete task response.
Request:
{
"jsonrpc": "2.0",
"method": "message/send",
"id": "req-001",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "Analyze https://github.com/example/repo" }]
}
}
}Response:
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"kind": "task",
"id": "task-abc-123",
"contextId": "ctx-456",
"status": {
"state": "completed",
"timestamp": "2025-01-15T10:30:00Z",
"message": {
"kind": "message",
"role": "agent",
"parts": [{ "kind": "text", "text": "Here is the analysis report..." }]
}
}
}
}message/stream
Send a message and receive a streaming response via Server-Sent Events.
Request: Same as message/send.
Response: SSE stream with status-update and message events:
data: {"kind":"status-update","taskId":"task-123","status":{"state":"working"}}
data: {"kind":"message","role":"agent","parts":[{"kind":"text","text":"Analyzing..."}]}
data: {"kind":"status-update","taskId":"task-123","status":{"state":"completed"}}tasks/get
Retrieve the current state of an existing task.
{
"jsonrpc": "2.0",
"method": "tasks/get",
"id": "req-002",
"params": {
"id": "task-abc-123"
}
}tasks/cancel
Cancel an in-progress task.
{
"jsonrpc": "2.0",
"method": "tasks/cancel",
"id": "req-003",
"params": {
"id": "task-abc-123"
}
}Response Structure
All responses follow the JSON-RPC 2.0 format. Successful responses contain a result field; errors contain an error field.
Task Response
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"kind": "task",
"id": "task-abc-123",
"contextId": "ctx-456",
"status": {
"state": "completed",
"timestamp": "2025-01-15T10:30:00Z",
"message": {
"kind": "message",
"messageId": "msg-789",
"role": "agent",
"taskId": "task-abc-123",
"contextId": "ctx-456",
"parts": [{ "kind": "text", "text": "Response content" }],
"metadata": {}
}
},
"artifacts": []
}
}Message Parts
Messages contain an array of parts, each with a kind:
| Kind | Description |
|---|---|
text | Plain text content |
data | Structured data (JSON) |
file | File attachment with MIME type |
Error Response
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": -32600,
"message": "Invalid Request"
}
}Standard JSON-RPC 2.0 error codes:
| Code | Meaning |
|---|---|
-32700 | Parse error |
-32600 | Invalid request |
-32601 | Method not found |
-32602 | Invalid params |
-32603 | Internal error |
@a2a-js/sdk Implementation
The @a2a-js/sdk package provides a complete server-side implementation of the A2A protocol.
Core Server Components
import type { AgentCard } from '@a2a-js/sdk';
import {
DefaultRequestHandler,
InMemoryTaskStore,
JsonRpcTransportHandler,
} from '@a2a-js/sdk/server';| Class | Role |
|---|---|
JsonRpcTransportHandler | Parses JSON-RPC requests and routes to handler methods |
DefaultRequestHandler | Manages task lifecycle with Agent Card + Task Store + Executor |
InMemoryTaskStore | In-memory persistence for tasks and their message history |
The AgentExecutor Interface
Your agent implements the AgentExecutor interface:
import type { AgentExecutor, ExecutionEventBus, RequestContext } from '@a2a-js/sdk/server';
export class MyExecutor implements AgentExecutor {
async execute(requestContext: RequestContext, eventBus: ExecutionEventBus): Promise<void> {
// Your logic here
}
async cancelTask(taskId: string, eventBus: ExecutionEventBus): Promise<void> {
// Handle cancellation
}
}The RequestContext provides:
userMessage— The incoming messagetaskId— The task identifiercontextId— The conversation contexttask— The full task object (with history, if resuming)
EventBus Publishing Pattern
The Executor communicates back to the client through the ExecutionEventBus. This is an event-driven pattern — you publish events and the SDK handles serialization and transport.
Publishing a Task Event
const taskEvent: Task = {
kind: 'task',
id: taskId,
contextId,
status: { state: 'submitted', timestamp: new Date().toISOString() },
};
eventBus.publish(taskEvent);Publishing a Status Update
const statusUpdate: TaskStatusUpdateEvent = {
kind: 'status-update',
taskId,
contextId,
final: true,
status: {
state: 'completed',
timestamp: new Date().toISOString(),
message: {
kind: 'message',
messageId: crypto.randomUUID(),
role: 'agent',
taskId,
contextId,
parts: [{ kind: 'text', text: 'Done!' }],
},
},
};
eventBus.publish(statusUpdate);Publishing a Message Directly
const reply: Message = {
kind: 'message',
messageId: crypto.randomUUID(),
role: 'agent',
taskId,
contextId,
parts: [{ kind: 'text', text: responseText }],
metadata: { /* any metadata */ },
};
eventBus.publish(reply);
eventBus.finished();Important
eventBus.finished() when your executor is done. For status updates, set final: true on the last event.Extensions Mechanism
A2A supports extensions that add capabilities to the base protocol. Extensions are declared in the Agent Card's capabilities.extensions array.
{
"capabilities": {
"extensions": [
{
"uri": "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2",
"description": "Supports payments using the x402 protocol for on-chain settlement.",
"required": true
}
]
}
}Clients activate extensions by including the URI in the X-A2A-Extensions HTTP header:
X-A2A-Extensions: https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2Setting required: true means the client must understand and implement this extension to interact with the agent. The X402 payments extension is the primary extension used in the A2X ecosystem.
For full X402 payment protocol details, see X402 Payments.
Further Reading
- Official A2A Protocol Specification
- A2A Extensions Documentation
- X402 Payments — The payment extension used by A2X agents