a2a-protocol
Use this skill when working with the A2A (Agent-to-Agent) protocol - agent interoperability, multi-agent communication, agent discovery, agent cards, task lifecycle, streaming, and push notifications. Triggers on any A2A-related task including implementing A2A servers/clients, building agent cards, sending messages between agents, managing tasks, and configuring push notification webhooks.
ai-ml a2aagent-interoperabilitymulti-agentagent-cardjson-rpcgrpcWhat is a2a-protocol?
Use this skill when working with the A2A (Agent-to-Agent) protocol - agent interoperability, multi-agent communication, agent discovery, agent cards, task lifecycle, streaming, and push notifications. Triggers on any A2A-related task including implementing A2A servers/clients, building agent cards, sending messages between agents, managing tasks, and configuring push notification webhooks.
a2a-protocol
a2a-protocol is a production-ready AI agent skill for claude-code, gemini-cli, openai-codex, and 1 more. Working with the A2A (Agent-to-Agent) protocol - agent interoperability, multi-agent communication, agent discovery, agent cards, task lifecycle, streaming, and push notifications.
Quick Facts
| Field | Value |
|---|---|
| Category | ai-ml |
| Version | 0.1.0 |
| Platforms | claude-code, gemini-cli, openai-codex, mcp |
| License | MIT |
How to Install
- Make sure you have Node.js installed on your machine.
- Run the following command in your terminal:
npx skills add AbsolutelySkilled/AbsolutelySkilled --skill a2a-protocol- The a2a-protocol skill is now available in your AI coding agent (Claude Code, Gemini CLI, OpenAI Codex, etc.).
Overview
A2A is an open protocol for seamless communication and collaboration between AI agents, regardless of their underlying frameworks or vendors. Originally created by Google and now under the Linux Foundation, it enables agents to discover each other via agent cards, exchange messages through JSON-RPC/gRPC/HTTP bindings, and manage long-running tasks with streaming and push notification support. A2A is complementary to MCP - while MCP connects models to tools and data, A2A enables agent-to-agent collaboration where agents remain autonomous entities.
Tags
a2a agent-interoperability multi-agent agent-card json-rpc grpc
Platforms
- claude-code
- gemini-cli
- openai-codex
- mcp
Related Skills
Pair a2a-protocol with these complementary skills:
Frequently Asked Questions
What is a2a-protocol?
Use this skill when working with the A2A (Agent-to-Agent) protocol - agent interoperability, multi-agent communication, agent discovery, agent cards, task lifecycle, streaming, and push notifications. Triggers on any A2A-related task including implementing A2A servers/clients, building agent cards, sending messages between agents, managing tasks, and configuring push notification webhooks.
How do I install a2a-protocol?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill a2a-protocol in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support a2a-protocol?
This skill works with claude-code, gemini-cli, openai-codex, mcp. Install it once and use it across any supported AI coding agent.
Maintainers
Generated from AbsolutelySkilled
SKILL.md
A2A Protocol (Agent-to-Agent)
A2A is an open protocol for seamless communication and collaboration between AI agents, regardless of their underlying frameworks or vendors. Originally created by Google and now under the Linux Foundation, it enables agents to discover each other via agent cards, exchange messages through JSON-RPC/gRPC/HTTP bindings, and manage long-running tasks with streaming and push notification support. A2A is complementary to MCP - while MCP connects models to tools and data, A2A enables agent-to-agent collaboration where agents remain autonomous entities.
When to use this skill
Trigger this skill when the user:
- Wants to implement an A2A server or client for agent interoperability
- Needs to create or parse an agent card for agent discovery
- Asks about multi-agent communication or agent-to-agent protocols
- Wants to send messages between agents using A2A
- Needs to manage A2A tasks (create, get, list, cancel, subscribe)
- Wants to implement streaming (SSE) for real-time agent updates
- Needs to configure push notification webhooks for async task updates
- Asks about A2A vs MCP or how they complement each other
Do NOT trigger this skill for:
- MCP (Model Context Protocol) tool/data integration without agent-to-agent needs
- General LLM API calls that don't involve inter-agent communication
Setup & authentication
A2A is a protocol specification, not an SDK. Implementations exist in multiple languages. The protocol uses HTTP(S) with three binding options.
Protocol bindings
| Binding | Transport | Best for |
|---|---|---|
| JSON-RPC 2.0 | HTTP POST | Web-based agents, broadest compatibility |
| gRPC | HTTP/2 | High-performance, typed contracts |
| HTTP+JSON/REST | Standard HTTP | Simple integrations, REST-native services |
Authentication
A2A supports these security schemes declared in agent cards:
- API Key (header, query, or cookie)
- HTTP Basic / Bearer token
- OAuth 2.0 (authorization code, client credentials, device code)
- OpenID Connect
- Mutual TLS (mTLS)
Credentials are passed via HTTP headers, separate from protocol messages. The spec strongly recommends dynamic credentials over embedded static secrets.
Core concepts
Client-Server model
A2A defines two roles: A2A Client (sends requests on behalf of a user or orchestrator) and A2A Server (remote agent that processes tasks and returns results). Communication is always client-initiated.
Agent card
A JSON metadata document at /.well-known/agent-card.json declaring an agent's
identity, endpoint URL, capabilities (streaming, push notifications), security
schemes, and skills. This is how agents discover each other.
Task lifecycle
Tasks are the core work unit. A client sends a message, which may create a task with a unique ID. Tasks progress through states:
submitted -> working -> completed
\-> failed
\-> canceled
\-> input-required (multi-turn)
\-> auth-required
\-> rejectedTerminal states: completed, failed, canceled, rejected.
Messages, parts, and artifacts
- Message: A single communication turn with
role(user/agent) andparts - Part: Smallest content unit - text, file (raw bytes or URI), or structured JSON data
- Artifact: Named output produced by an agent, composed of parts
- Context: A
contextIdgroups related tasks across interaction turns
Common tasks
Discover an agent
Fetch the agent card from the well-known URI:
curl https://agent.example.com/.well-known/agent-card.jsonThree discovery strategies exist: well-known URI (public agents), curated registries (enterprise), and direct configuration (dev/testing).
Send a message (JSON-RPC)
{
"jsonrpc": "2.0",
"method": "a2a.sendMessage",
"id": "req-1",
"params": {
"message": {
"message_id": "msg-001",
"role": "user",
"parts": [
{ "text": "Find flights from SFO to JFK on March 20" }
]
},
"configuration": {
"accepted_output_modes": ["text/plain"],
"return_immediately": false
},
"a2a-version": "1.0"
}
}Response contains either a Task (async) or Message (sync) object.
Send a streaming message
Use a2a.sendStreamingMessage for real-time updates. The server must declare
capabilities.streaming: true in its agent card. Returns StreamResponse
wrappers containing task updates, messages, or artifact chunks.
{
"jsonrpc": "2.0",
"method": "a2a.sendStreamingMessage",
"id": "req-2",
"params": {
"message": {
"message_id": "msg-002",
"role": "user",
"parts": [{ "text": "Summarize this 500-page report" }]
},
"a2a-version": "1.0"
}
}Get task status
{
"jsonrpc": "2.0",
"method": "a2a.getTask",
"id": "req-3",
"params": {
"id": "task-abc-123",
"history_length": 10,
"a2a-version": "1.0"
}
}history_length: 0 = no history, unset = full history, N = last N messages.
Handle multi-turn (input-required)
When a task enters input-required state, the client sends a follow-up message
with the same task_id and context_id:
{
"jsonrpc": "2.0",
"method": "a2a.sendMessage",
"id": "req-4",
"params": {
"message": {
"message_id": "msg-003",
"task_id": "task-abc-123",
"context_id": "ctx-xyz",
"role": "user",
"parts": [{ "text": "I prefer a morning departure" }]
},
"a2a-version": "1.0"
}
}Configure push notifications
For long-running tasks, configure webhook callbacks instead of polling:
{
"jsonrpc": "2.0",
"method": "a2a.createTaskPushNotificationConfig",
"id": "req-5",
"params": {
"task_id": "task-abc-123",
"push_notification_config": {
"url": "https://my-client.example.com/webhook",
"authentication": {
"scheme": "bearer",
"credentials": "webhook-token-here"
}
},
"a2a-version": "1.0"
}
}The server sends TaskStatusUpdateEvent and TaskArtifactUpdateEvent payloads
to the configured webhook URL.
Cancel a task
{
"jsonrpc": "2.0",
"method": "a2a.cancelTask",
"id": "req-6",
"params": {
"id": "task-abc-123",
"a2a-version": "1.0"
}
}Error handling
| Error | Cause | Resolution |
|---|---|---|
TaskNotFoundError |
Invalid or expired task ID | Verify task ID; task may have been cleaned up |
TaskNotCancelableError |
Task already in terminal state | Check task status before canceling |
PushNotificationNotSupportedError |
Server lacks push capability | Fall back to polling or streaming |
UnsupportedOperationError |
Method not implemented by server | Check agent card capabilities first |
ContentTypeNotSupportedError |
Unsupported media type in parts | Check agent's accepted input/output modes |
VersionNotSupportedError |
Client/server version mismatch | Align a2a-version parameter |
Gotchas
a2a-versionin every request - Thea2a-versionfield is required in every JSON-RPC params object. Omitting it causesVersionNotSupportedErroreven if the server version matches. Always include"a2a-version": "1.0".Streaming requires capability declaration - You cannot call
a2a.sendStreamingMessageunless the agent card explicitly declarescapabilities.streaming: true. Check the agent card before attempting streaming; fall back tosendMessageotherwise.Task IDs and context IDs are distinct -
task_ididentifies the specific work unit;context_idgroups related tasks across turns. In multi-turn flows, you must pass both. Sending onlytask_idwithout the originalcontext_idcreates a new context instead of continuing the conversation.Push notifications require HTTPS - The webhook URL in
createTaskPushNotificationConfigmust be an HTTPS endpoint. HTTP URLs are rejected. During local development, use a tunnel (ngrok, localtunnel) rather than trying to configure HTTP.Terminal states are final - Once a task reaches
completed,failed,canceled, orrejected, no further messages can be sent to it. Attempting to send a message to a terminal task silently creates a new task in some implementations. Always check task state before continuing a thread.
References
For detailed content on specific A2A sub-domains, read the relevant file
from the references/ folder:
references/agent-card.md- Full agent card schema, discovery strategies, caching, and extended cardsreferences/protocol-bindings.md- JSON-RPC, gRPC, and HTTP+JSON/REST method mappings and endpointsreferences/task-states.md- Complete task state machine, streaming responses, and push notification payloads
Only load a references file if the current task requires it - they are long and will consume context.
References
agent-card.md
Agent Card Reference
Agent card structure
The agent card is a JSON document declaring an agent's identity, capabilities, and how to interact with it.
Core fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Human-readable agent name |
description |
string | No | What the agent does |
supported_interfaces |
AgentInterface[] | Yes | Protocol binding endpoints |
provider |
object | No | Organization info (name, url) |
version |
string | No | Agent version |
documentation_url |
string | No | Link to agent docs |
capabilities |
AgentCapabilities | No | Feature flags |
security_schemes |
map | No | Available auth methods |
security_requirements |
SecurityRequirement[] | No | Required auth for access |
default_input_modes |
string[] | No | Accepted input media types |
default_output_modes |
string[] | No | Produced output media types |
skills |
AgentSkill[] | No | List of agent abilities |
AgentInterface
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | Service endpoint URL |
protocol_binding |
string | Yes | One of: jsonrpc, grpc, http+json |
tenant |
string | No | Multi-tenant path parameter |
protocol_version |
string | No | A2A version (e.g. "1.0") |
AgentCapabilities
| Field | Type | Description |
|---|---|---|
streaming |
bool | Supports SSE streaming |
push_notifications |
bool | Supports webhook callbacks |
extended_agent_card |
bool | Offers authenticated extended card |
extensions |
Extension[] | Supported protocol extensions |
AgentSkill
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique skill identifier |
name |
string | Yes | Human-readable name |
description |
string | No | What the skill does |
tags |
string[] | No | Categorization tags |
examples |
string[] | No | Example prompts |
input_modes |
string[] | No | Override default input modes |
output_modes |
string[] | No | Override default output modes |
security_requirements |
SecurityRequirement[] | No | Skill-specific auth |
Example agent card
{
"name": "Travel Planner Agent",
"description": "Books flights, hotels, and creates travel itineraries",
"supported_interfaces": [
{
"url": "https://travel-agent.example.com/a2a",
"protocol_binding": "jsonrpc",
"protocol_version": "1.0"
}
],
"provider": {
"organization": "TravelCo",
"url": "https://travelco.example.com"
},
"version": "2.1.0",
"capabilities": {
"streaming": true,
"push_notifications": true,
"extended_agent_card": false
},
"security_schemes": {
"bearer": {
"type": "http",
"scheme": "bearer"
}
},
"security_requirements": [
{ "bearer": [] }
],
"default_input_modes": ["text/plain"],
"default_output_modes": ["text/plain", "application/json"],
"skills": [
{
"id": "flight-search",
"name": "Flight Search",
"description": "Search and book flights between any two airports",
"tags": ["travel", "flights", "booking"],
"examples": ["Find flights from SFO to JFK on March 20"]
},
{
"id": "hotel-booking",
"name": "Hotel Booking",
"description": "Search and reserve hotel rooms",
"tags": ["travel", "hotels"],
"examples": ["Book a hotel near Times Square for 3 nights"]
}
]
}Discovery strategies
1. Well-known URI (recommended for public agents)
Host agent card at https://{domain}/.well-known/agent-card.json per RFC 8615.
2. Curated registries (enterprise)
Central service maintains agent card collections. Clients query by skills, tags, or capabilities. Provides centralized governance and capability-based discovery.
3. Direct configuration (dev/testing)
Hardcoded details, config files, or environment variables. Simple but inflexible.
Extended agent cards
When capabilities.extended_agent_card is true, the server offers a
GetExtendedAgentCard operation that returns additional capabilities visible
only to authenticated clients. This allows agents to expose sensitive skills
or detailed configurations after credential exchange.
Security schemes
| Type | Description |
|---|---|
apiKey |
API key in header, query param, or cookie |
http |
HTTP Basic or Bearer token |
oauth2 |
OAuth 2.0 flows (authorizationCode, clientCredentials, deviceCode) |
openIdConnect |
OpenID Connect discovery |
mutualTLS |
Mutual TLS client certificates |
Caching
- Servers should include
Cache-Controlheaders with appropriatemax-age - Servers should include
ETagheaders for conditional requests - Clients should honor HTTP caching semantics
- Use conditional requests (
If-None-Match) rather than unconditional re-fetching
protocol-bindings.md
Protocol Bindings Reference
A2A defines a three-layer architecture: a canonical data model (Protocol Buffers), abstract operations (binding-independent), and protocol bindings. All three bindings are functionally equivalent.
JSON-RPC 2.0 Binding
All methods are prefixed with a2a. and sent as HTTP POST to the agent endpoint.
Methods
| Method | Description | Returns |
|---|---|---|
a2a.sendMessage |
Send message to agent | Task or Message |
a2a.sendStreamingMessage |
Streaming message send | StreamResponse (SSE) |
a2a.getTask |
Get task by ID | Task |
a2a.listTasks |
List tasks with filters | ListTasksResponse |
a2a.cancelTask |
Cancel a task | Task |
a2a.subscribeToTask |
Subscribe to task updates | StreamResponse (SSE) |
a2a.createTaskPushNotificationConfig |
Create webhook config | PushNotificationConfig |
a2a.getTaskPushNotificationConfig |
Get webhook config | PushNotificationConfig |
a2a.listTaskPushNotificationConfigs |
List webhook configs | PushNotificationConfig[] |
a2a.deleteTaskPushNotificationConfig |
Delete webhook config | void |
a2a.getExtendedAgentCard |
Get authenticated card | AgentCard |
Service parameters
Passed in the params object alongside method-specific params:
{
"jsonrpc": "2.0",
"method": "a2a.sendMessage",
"id": "req-1",
"params": {
"message": { ... },
"a2a-version": "1.0",
"a2a-extensions": "urn:example:ext1,urn:example:ext2"
}
}Streaming
For sendStreamingMessage and subscribeToTask, the server responds with
Content-Type: text/event-stream (SSE). Each event is a JSON-encoded
StreamResponse wrapper.
gRPC Binding
Service definition
service A2AService {
// Unary RPCs
rpc SendMessage(SendMessageRequest) returns (SendMessageResponse);
rpc GetTask(GetTaskRequest) returns (Task);
rpc ListTasks(ListTasksRequest) returns (ListTasksResponse);
rpc CancelTask(CancelTaskRequest) returns (Task);
rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard);
rpc CreateTaskPushNotificationConfig(...) returns (PushNotificationConfig);
rpc GetTaskPushNotificationConfig(...) returns (PushNotificationConfig);
rpc ListTaskPushNotificationConfigs(...) returns (...);
rpc DeleteTaskPushNotificationConfig(...) returns (google.protobuf.Empty);
// Server-streaming RPCs
rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse);
rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse);
}Service parameters
Transmitted via gRPC metadata headers:
a2a-version: Protocol versiona2a-extensions: Comma-separated extension URIs
HTTP+JSON/REST Binding
RESTful endpoints using standard HTTP methods.
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /messages |
Send a message |
| POST | /messages:stream |
Send streaming message (SSE response) |
| GET | /tasks/{id} |
Get task by ID |
| GET | /tasks |
List tasks (query params for filtering) |
| POST | /tasks/{id}:cancel |
Cancel a task |
| POST | /tasks/{id}:subscribe |
Subscribe to task updates (SSE) |
| POST | /tasks/{taskId}/pushNotificationConfigs |
Create push config |
| GET | /tasks/{taskId}/pushNotificationConfigs/{configId} |
Get push config |
| GET | /tasks/{taskId}/pushNotificationConfigs |
List push configs |
| DELETE | /tasks/{taskId}/pushNotificationConfigs/{configId} |
Delete push config |
| GET | /agent-card |
Get extended agent card (authenticated) |
Query parameters for listing
| Parameter | Type | Description |
|---|---|---|
contextId |
string | Filter by context |
status |
string | Filter by task state |
pageSize |
int | Results per page |
pageToken |
string | Pagination cursor |
Service parameters
Passed as HTTP headers:
A2A-Version: 1.0A2A-Extensions: urn:example:ext1,urn:example:ext2
Multi-tenant support
For multi-tenant deployments, a tenant path parameter can prefix all endpoints:
/tenants/{tenant}/messages, /tenants/{tenant}/tasks/{id}, etc.
StreamResponse wrapper
All streaming operations return StreamResponse objects, each containing
exactly one of:
| Field | Type | When sent |
|---|---|---|
task |
Task | Full task state update |
message |
Message | Agent message in conversation |
statusUpdate |
TaskStatusUpdateEvent | Task state transition |
artifactUpdate |
TaskArtifactUpdateEvent | New or updated artifact chunk |
TaskArtifactUpdateEvent includes append (boolean) and last_chunk (boolean)
fields for incremental artifact streaming.
task-states.md
Task States and Lifecycle Reference
Task object
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique task identifier |
context_id |
string | No | Groups related tasks across turns |
status |
TaskStatus | Yes | Current state and metadata |
artifacts |
Artifact[] | No | Output artifacts produced |
history |
Message[] | No | Conversation history |
metadata |
map | No | Arbitrary key-value data |
Task states
+-> completed (terminal)
|
submitted -> working +-> failed (terminal)
|
+-> canceled (terminal)
|
+-> rejected (terminal)
|
+-> input-required (interrupted) -> working (on new message)
|
+-> auth-required (interrupted) -> working (on auth)State descriptions
| State | Category | Description |
|---|---|---|
submitted |
Active | Task received, not yet processing |
working |
Active | Agent is processing the task |
completed |
Terminal | Task finished successfully |
failed |
Terminal | Task encountered an unrecoverable error |
canceled |
Terminal | Task was canceled by client |
rejected |
Terminal | Agent refused to process the task |
input-required |
Interrupted | Agent needs more info from client |
auth-required |
Interrupted | Agent needs authentication/authorization |
State transitions
- Active states can transition to any other state
- Interrupted states transition back to
workingwhen the client responds - Terminal states are final - no further transitions allowed
- Servers must reject
cancelTaskfor tasks already in terminal states
Multi-turn conversation flow
- Client sends
sendMessagewith initial request - Server creates task in
submittedstate, moves toworking - Server transitions to
input-requiredif it needs clarification - Client sends follow-up
sendMessagewith sametask_idandcontext_id - Server resumes processing (
working) - Repeat until task reaches a terminal state
The context_id is server-generated on the first interaction. Clients must
preserve and reuse it for related follow-up messages. Servers must reject
requests with mismatched context_id/task_id pairs.
History and pagination
The history_length parameter on getTask and sendMessage controls how
many historical messages are returned:
| Value | Behavior |
|---|---|
0 |
No history returned |
| Unset/null | Full history (no limit) |
N (positive int) |
Last N messages only |
Artifacts
| Field | Type | Required | Description |
|---|---|---|---|
artifact_id |
string | Yes | Unique artifact identifier |
name |
string | No | Human-readable name |
description |
string | No | What the artifact contains |
parts |
Part[] | Yes | Content parts |
metadata |
map | No | Arbitrary key-value data |
extensions |
Extension[] | No | Extension data |
Push notification payloads
When push notifications are configured, the server sends webhooks with these event types:
TaskStatusUpdateEvent
Sent when a task's state changes.
{
"task_id": "task-abc-123",
"context_id": "ctx-xyz",
"status": {
"state": "completed",
"message": {
"role": "agent",
"parts": [{ "text": "Task completed successfully" }]
}
},
"metadata": {}
}TaskArtifactUpdateEvent
Sent when an artifact is created or updated.
{
"task_id": "task-abc-123",
"context_id": "ctx-xyz",
"artifact": {
"artifact_id": "art-001",
"name": "search-results",
"parts": [{ "text": "Found 3 matching flights..." }],
"append": false,
"last_chunk": true
}
}append: truemeans this chunk should be appended to the existing artifactlast_chunk: truemeans no more chunks will follow for this artifact
Push notification configuration
{
"url": "https://client.example.com/webhook",
"token": "unique-config-id",
"authentication": {
"scheme": "bearer",
"credentials": "secret-token"
}
}Authentication options for webhooks
| Scheme | Description |
|---|---|
basic |
HTTP Basic auth (base64 user:pass) |
bearer |
Bearer token in Authorization header |
apiKey |
API key in configured location |
Management operations
createTaskPushNotificationConfig- Register a new webhookgetTaskPushNotificationConfig- Get config by IDlistTaskPushNotificationConfigs- List all configs for a taskdeleteTaskPushNotificationConfig- Remove a webhook config
Update delivery mechanisms
| Mechanism | When to use | Requirements |
|---|---|---|
| Polling | Simple clients, infrequent updates | None - always available |
| Streaming (SSE) | Real-time updates, interactive UIs | capabilities.streaming: true |
| Push notifications | Long-running tasks, serverless clients | capabilities.push_notifications: true |
Frequently Asked Questions
What is a2a-protocol?
Use this skill when working with the A2A (Agent-to-Agent) protocol - agent interoperability, multi-agent communication, agent discovery, agent cards, task lifecycle, streaming, and push notifications. Triggers on any A2A-related task including implementing A2A servers/clients, building agent cards, sending messages between agents, managing tasks, and configuring push notification webhooks.
How do I install a2a-protocol?
Run npx skills add AbsolutelySkilled/AbsolutelySkilled --skill a2a-protocol in your terminal. The skill will be immediately available in your AI coding agent.
What AI agents support a2a-protocol?
a2a-protocol works with claude-code, gemini-cli, openai-codex, mcp. Install it once and use it across any supported AI coding agent.