EventMesh A2A (Agent-to-Agent Communication Protocol)

Overview

The EventMesh A2A (Agent-to-Agent) Protocol is a specialized, high-performance protocol plugin designed to enable asynchronous communication, collaboration, and task coordination between autonomous agents.

With the release of v2.0, A2A adopts the MCP (Model Context Protocol) architecture, transforming EventMesh into a robust Agent Collaboration Bus. It bridges the gap between synchronous LLM-based tool calls (JSON-RPC 2.0) and asynchronous Event-Driven Architectures (EDA), enabling scalable, distributed, and decoupled agent systems.

Core Features

1. MCP over CloudEvents

  • Standard Compliance: Fully supports standard methods defined by MCP (Model Context Protocol), such as tools/call, resources/read.
  • Event-Driven: Maps synchronous RPC calls to asynchronous Request/Response Event Streams, leveraging EventMesh's high-concurrency processing capabilities.
  • Transport Agnostic: All MCP messages are encapsulated within standard CloudEvents envelopes, running over any transport layer supported by EventMesh (HTTP, TCP, gRPC, Kafka).

2. Dual-Mode Support (Hybrid Architecture)

A2A Protocol features a unique Dual-Mode architecture that simultaneously supports:

  1. JSON-RPC 2.0 (MCP Mode):
    • Target: LLMs, Scripts (Python/JS), LangChain integration.
    • Benefit: Extremely low barrier to entry. Clients send simple JSON objects; the adaptor automatically wraps them in CloudEvents.
  2. Native CloudEvents (Power Mode):
    • Target: EventMesh native apps, Knative, Serverless functions.
    • Benefit: Full control over event metadata. Allows pass-through of custom or binary data.

Mechanism: The EnhancedA2AProtocolAdaptor intelligently detects the payload format. If jsonrpc: "2.0" is present, it engages the MCP translation engine; otherwise, it treats the payload as a standard CloudEvent (delegating to the underlying CloudEvents adaptor).

3. Native Pub/Sub Semantics

  • O(1) Broadcast: Publishers send messages once to a Topic, and EventMesh efficiently fans out to all subscribers.
  • Decoupling: Solves the scalability issues of traditional P2P Webhook callbacks.
  • Isolation: Provides backpressure isolation between publishers and subscribers.

3. High Performance & Routing

  • Batch Processing: Natively supports JSON-RPC Batch requests. EventMesh automatically splits them into parallel event streams.
  • Intelligent Routing: Extracts routing hints (_agentId for P2P, _topic for Pub/Sub) from MCP parameters and injects them into CloudEvents attributes for zero-decoding routing.

4. Streaming Support

  • Sequencing: Preserves message order for streaming operations (message/sendStream) using sequence IDs.

Architecture

Core Components

┌─────────────────────────────────────────────────────────────┐
│                EventMesh A2A Protocol v2.0                │
│              (MCP over CloudEvents Architecture)            │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ MCP/JSON-RPC│  │ Native      │  │  Protocol   │         │
│  │   Handler   │  │ Pub/Sub     │  │  Delegator  │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
├─────────────────────────────────────────────────────────────┤
│  ┌───────────────────────────────────────────────────────┐  │
│  │           Enhanced A2A Protocol Adaptor               │  │
│  │      (Intelligent Parsing & CloudEvent Mapping)       │  │
│  └───────────────────────────────────────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│              EventMesh Protocol Infrastructure             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ CloudEvents │  │    HTTP     │  │    gRPC     │         │
│  │  Protocol   │  │  Protocol   │  │  Protocol   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘

Gateway Runtime Architecture

  protocol-a2a module              runtime module                   examples module
  ┌─────────────────┐           ┌──────────────────┐           ┌──────────────┐
  │ A2AMessageTransport(Iface)   │ A2AGatewayServer  │           │ A2AGatewayDemo│
  │ A2AClient (SDK)  │<──HTTP──>│ (main, Netty HTTP)│<──HTTP──>│ (client only) │
  │ AgentCard/Topic  │           │ InMemoryTransport │           └──────────────┘
  └─────────────────┘           │ GatewayService    │
                                │ TaskRegistry(TTL) │
                                └──────────────────┘

Core Runtime Components

ComponentModuleResponsibility
A2AGatewayServerruntimeNetty HTTP server entry point, pre-registers mock agents
A2AGatewayHttpHandlerruntimeHTTP request router, supports SSE streaming
A2AGatewayServiceruntimeCore orchestration: task submission, response handling, SSE push
TaskRegistryruntimeIn-memory task state machine + TTL auto-cleanup (5 min)
A2APublishSubscribeServiceruntimeAgentCard registration, discovery, heartbeat
InMemoryA2AMessageTransportruntimeIn-memory pub/sub (replaceable by EventMesh broker)
A2AClientprotocol-a2aJava SDK with typed API

Asynchronous RPC Pattern

To support the MCP Request/Response model within an event-driven architecture, A2A defines the following mapping rules:

MCP ConceptCloudEvent MappingDescription
Request (tools/call)type: org.apache.eventmesh.a2a.tools.call.req
mcptype: request
Request event.
Response (result)type: org.apache.eventmesh.a2a.common.response
mcptype: response
Response event.
Correlation (id)extension: collaborationid / idLinks Response to Request.
P2P Targetextension: targetagentRouting target Agent ID.
Pub/Sub Topicsubject: <topic_name>Broadcast Topic.

Protocol Message Format

1. MCP Request (P2P)

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "_agentId": "weather-service" // P2P Routing
  },
  "id": "req-123"
}

2. MCP Request (Pub/Sub)

{
  "jsonrpc": "2.0",
  "method": "market/update",
  "params": {
    "price": 50000,
    "_topic": "market.btc" // Pub/Sub Routing
  }
}

Usage Guide

1. Initiate Call (Client)

// 1. Construct MCP Request JSON
String mcpRequest = "{" +
    "\"jsonrpc\": \"2.0\"," +
    "\"method\": \"tools/call\"," +
    "\"params\": { \"name\": \"weather\", \"_agentId\": \"weather-agent\" }," +
    "\"id\": \"req-001\"" +
    "}";

// 2. Send via EventMesh SDK
eventMeshProducer.publish(new A2AProtocolTransportObject(mcpRequest));

2. Handle Request (Server)

Subscribe to the topic org.apache.eventmesh.a2a.tools.call.req, process logic, and send back response with matching id.

3. Gateway REST API

The A2A Gateway provides a full REST API for external clients and non-Java agents:

# Sync task
curl -X POST 'http://localhost:10105/a2a/tasks?mode=sync' \
  -H 'Content-Type: application/json' \
  -d '{"targetAgent":"weather-agent","message":"Beijing"}'

# Async task
curl -X POST 'http://localhost:10105/a2a/tasks?mode=async' \
  -H 'Content-Type: application/json' \
  -d '{"targetAgent":"weather-agent","message":"Shanghai"}'

# Query status
curl http://localhost:10105/a2a/tasks/{taskId}

# SSE stream
curl -N http://localhost:10105/a2a/tasks/{taskId}/stream

# List agents
curl http://localhost:10105/a2a/agents

REST API Endpoints

MethodPathDescription
POST/a2a/tasks?mode=syncSubmit task synchronously (wait for result)
POST/a2a/tasks?mode=asyncSubmit task asynchronously (return taskId)
GET/a2a/tasks/{taskId}Get task status
DELETE/a2a/tasks/{taskId}Cancel task
GET/a2a/tasks/{taskId}/waitLong-poll wait for result
GET/a2a/tasks/{taskId}/streamSSE stream of task status updates
GET/a2a/agentsList registered agents
POST/a2a/heartbeatAgent heartbeat
GET/a2a/cards/listList all AgentCards
POST/a2a/cards/card/{org}/{unit}/{agent}Register AgentCard

4. A2AClient Java SDK

A2AClient client = A2AClient.builder()
    .gatewayUrl("http://localhost:10105")
    .namespace("global")
    .agentName("my-agent")
    .agentCard(card)
    .heartbeatInterval(30_000)
    .build();

client.start();

// Sync task (returns typed TaskResult)
TaskResult result = client.sendTaskSync("weather-agent", "Beijing", null);

// Async task (returns taskId)
String taskId = client.sendTaskAsync("weather-agent", "Shanghai", null);

// Query status
TaskResult status = client.getTaskStatus(taskId);

// Cancel
boolean cancelled = client.cancelTask(taskId);

// List agents (returns List<String>)
List<String> agents = client.listAgents();

client.shutdown();

Version History

  • v2.0.0: Fully Embraced MCP (Model Context Protocol)

    • Introduced EnhancedA2AProtocolAdaptor supporting JSON-RPC 2.0.
    • Implemented Async RPC over CloudEvents pattern.
    • Added Native Pub/Sub support via _topic parameter.
    • Added Streaming support via _seq parameter.
  • v2.1.0: Gateway Runtime Architecture

    • Added A2AGatewayServer (Netty HTTP) standalone Gateway service.
    • Implemented TaskRegistry task state machine + TTL auto-cleanup (5 min).
    • Added SSE streaming response (GET /a2a/tasks/{taskId}/stream).
    • A2AClient SDK returns typed objects (TaskResult, List<String>).
    • Fixed pendingTasks race condition (put-before-publish).
    • AgentCard registration, discovery, heartbeat management.
    • 73 test scenarios all passing.

Contribution

Welcome to contribute code and documentation!

License

Apache License 2.0

Contact