Skip to content

A2A Protocol

Agent-to-Agent (A2A) is Google’s open protocol for interoperable agent communication. It defines how agents discover each other, exchange messages, manage long-running tasks, and stream partial results — all over plain HTTP using JSON-RPC 2.0.

PromptFleet implements A2A v1.0 across four crates, giving you the protocol for free when you enable the a2a-server or a2a-client features on agent_sdk.

An Agent Card is a JSON document that describes what an agent can do. Clients fetch it via GET /.well-known/agent.json (or the JSON-RPC method agent/authenticatedExtendedCard) to discover an agent’s skills, supported content types, and capabilities before sending any messages.

{
"name": "weather-agent",
"description": "Provides weather forecasts",
"url": "https://weather-agent.default.agentmesh",
"version": "1.0.0",
"capabilities": {
"streaming": true,
"pushNotifications": false
},
"skills": [
{
"id": "get_weather",
"name": "get_weather",
"description": "Returns current weather for a location"
}
]
}

A Task is the unit of work in A2A. When a client sends a message, the server creates (or resumes) a Task that tracks state through a lifecycle:

submitted → working → completed
↘ failed
↘ canceled

Each Task has an ID, a history of Messages, optional Artifacts (structured output), and a status that the client can poll or stream.

Messages carry the conversation between client and agent. Each Message has a role (user or agent) and a list of Parts — typed content blocks:

  • TextPart — plain text or markdown
  • DataPart — arbitrary JSON (structured tool output, metadata)
  • FilePart — binary content (inline base64 or URI reference)

A2A defines a small set of JSON-RPC 2.0 methods:

MethodDirectionPurpose
message/sendClient → AgentSend a message and get a synchronous response
message/streamClient → AgentSend a message and receive SSE streaming events
tasks/getClient → AgentRetrieve a task by ID
tasks/cancelClient → AgentRequest cancellation of a running task
tasks/listClient → AgentList tasks (filtered by context or state)
sequenceDiagram
    participant Client
    participant Agent

    Client->>Agent: POST /a2a {"method": "message/send", "params": {...}}
    Agent->>Agent: Create/resume Task, run skills
    Agent-->>Client: {"result": {"task": {...}, "contextId": "..."}}
sequenceDiagram
    participant Client
    participant Agent

    Client->>Agent: POST /a2a {"method": "message/stream", "params": {...}}
    Agent-->>Client: SSE: event: message (partial text)
    Agent-->>Client: SSE: event: message (more text)
    Agent-->>Client: SSE: event: artifact (structured output)
    Agent-->>Client: SSE: event: status (task completed)

PromptFleet splits the A2A implementation into four focused crates, following clean architecture principles:

CrateLayerWhat it does
protocol_transport_coreTransportJSON-RPC 2.0 foundation — request/response/error types, request parsing, batch support. Shared by A2A, MCP, and LLM client.
a2a_protocol_coreDomainPure A2A types — AgentCard, Task, Message, Part, TaskStatus, A2AError. Protocol handler and method registry. Zero transport dependency.
a2a_http_serverAdapter (inbound)HTTP dispatch: routes JSON-RPC requests to the protocol handler, serves Agent Cards, handles SSE streaming. Uses Spin SDK on WASM, Axum on native.
a2a_http_clientAdapter (outbound)HTTP client: sends JSON-RPC requests, parses responses, supports SSE streaming consumption. Uses Spin SDK on WASM, Reqwest on native.
a2a_app_portsPortsClean-architecture traits (MessageHandler, TaskStorage) that decouple the server adapter from your application logic.
a2a_rpc_macrosCodegen#[a2a_rpc("method")] proc-macro for registering custom JSON-RPC methods.
graph LR
    A[a2a_http_server] --> B[a2a_protocol_core]
    A --> C[a2a_app_ports]
    A --> D[protocol_transport_core]
    C --> B
    B --> D
    E[a2a_http_client] --> B
    E --> D