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.
The architecture adheres to the principles outlined in the broader agent community (e.g., A2A Project, FIPA-ACL, and CloudEvents):
Traditional A2A implementations often rely on HTTP Webhooks (POST /inbox) for asynchronous callbacks. While functional, this Point-to-Point (P2P) model suffers from significant scaling issues:
EventMesh A2A solves this by introducing Native Pub/Sub capabilities:
flowchart LR Publisher["Publisher Agent"] -->|1. Publish (Once)| Bus["EventMesh Bus"] subgraph FanoutLayer ["EventMesh Fanout Layer"] Queue["Topic Queue"] end Bus --> Queue Queue -->|"Push"| Sub1["Subscriber 1"] Queue -->|"Push"| Sub2["Subscriber 2"] Queue -->|"Push"| Sub3["Subscriber 3"] style Bus fill:#f9f,stroke:#333 style FanoutLayer fill:#ccf,stroke:#333
A2A Protocol introduces a unique Hybrid Architecture that bridges the gap between the AI ecosystem (which prefers simple JSON) and the Cloud Native ecosystem (which prefers structured CloudEvents).
| Feature | JSON-RPC 2.0 Mode | Native CloudEvents Mode |
|---|---|---|
| Primary Audience | LLMs, Scripts (Python/JS), LangChain | EventMesh Apps, Knative, Java SDK |
| Philosophy | “Battery Included” | “Power User” |
| Usage | Send raw JSON ({"method":...}) | Send CloudEvent object |
| Complexity | Low (No SDK required) | Medium (Requires CE SDK) |
| Mechanism | Adaptor automatically wraps JSON in CE | Adaptor passes through the event |
Benefits:
curl or simple JSON libraries.graph TD Client["Client Agent / LLM"] -- "JSON-RPC Request" --> EM["EventMesh Runtime"] EM -- "CloudEvent (Request)" --> Server["Server Agent / Tool"] Server -- "CloudEvent (Response)" --> EM EM -- "JSON-RPC Response" --> Client subgraph Runtime ["EventMesh Runtime"] Plugin["A2A Protocol Plugin"] end style EM fill:#f9f,stroke:#333,stroke-width:4px style Plugin fill:#ccf,stroke:#333,stroke-width:2px
eventmesh-protocol-a2a)The core logic resides in the eventmesh-protocol-plugin module.
EnhancedA2AProtocolAdaptor: The central brain of the protocol.CloudEvents or HTTP adaptors when necessary.A2AProtocolConstants: Defines standard operations like task/get, message/sendStream.JsonRpc* Models: Strictly typed POJOs for JSON-RPC 2.0 compliance.To support MCP on an Event Bus, synchronous RPC concepts are mapped to asynchronous events:
| Concept | MCP / JSON-RPC | CloudEvent Mapping |
|---|---|---|
| Action | method (e.g., tools/call) | Type: org.apache.eventmesh.a2a.tools.call.reqExtension: a2amethod |
| Correlation | id (e.g., req-123) | Extension: collaborationid (on Response)ID: Preserved on Request |
| Direction | Implicit (Request vs Result) | Extension: mcptype (request or response) |
| P2P Routing | params._agentId | Extension: targetagent |
| Pub/Sub Topic | params._topic | Subject: The topic value (e.g. market.btc) |
| Streaming Seq | params._seq | Extension: seq |
ProtocolTransportObject (byte array/string).jsonrpc: "2.0".method.message/sendStream, sets type suffix to .stream and extracts _seq._topic present, sets subject (Pub/Sub)._agentId present, sets targetagent (P2P).result/error. Sets collaborationid = id.List<CloudEvent>._agentId or _topic from JSON body to CloudEvent attributes.message/sendStream.stream event type and preserves sequence order via seq extension attribute.This mode is ideal for LLMs, scripts, and simple integrations where you want to send raw JSON without worrying about CloudEvent headers.
Client Sends (Raw JSON):
{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "weather", "city": "Shanghai", "_agentId": "weather-agent" }, "id": "req-101" }
EventMesh Converts to:
org.apache.eventmesh.a2a.tools.call.reqweather-agentrequestClient Sends (Raw JSON):
{ "jsonrpc": "2.0", "method": "notifications/alert", "params": { "message": "System Maintenance in 10 mins", "_topic": "system.alerts" } }
EventMesh Converts to:
org.apache.eventmesh.a2a.notifications.alertsystem.alertsnotification// See eventmesh-examples/src/main/java/org/apache/eventmesh/a2a/demo/mcp/McpCaller.java Map<String, Object> request = new HashMap<>(); request.put("jsonrpc", "2.0"); request.put("method", "tools/call"); request.put("params", Map.of("name", "weather", "_agentId", "weather-agent")); request.put("id", UUID.randomUUID().toString()); CloudEvent event = CloudEventBuilder.v1() .withType("org.apache.eventmesh.a2a.tools.call.req") .withData(JsonUtils.toJSONString(request).getBytes()) .withExtension("protocol", "A2A") // Critical to trigger A2A adaptor .build(); producer.publish(event);
This mode provides full control over all CloudEvent attributes and is recommended for robust, typed applications using the EventMesh SDK.
Client Sends (CloudEvent):
{ "specversion": "1.0", "type": "com.example.rpc.request", "source": "my-app", "id": "evt-123", "data": "...", "protocol": "A2A", "targetagent": "target-agent-001" }
Java SDK Example:
// See eventmesh-examples/src/main/java/org/apache/eventmesh/a2a/demo/ce/CloudEventsCaller.java CloudEvent event = CloudEventBuilder.v1() .withId(UUID.randomUUID().toString()) .withSource(URI.create("ce-client")) .withType("com.example.rpc.request") .withData("application/text", "RPC Payload".getBytes()) .withExtension("protocol", "A2A") .withExtension("targetagent", "target-agent-001") // Explicit routing .build(); producer.publish(event);
Client Sends (CloudEvent):
{ "specversion": "1.0", "type": "com.example.notification", "source": "my-app", "subject": "broadcast.topic", "protocol": "A2A" }
Client Sends (CloudEvent):
{ "specversion": "1.0", "type": "com.example.stream", "source": "my-app", "subject": "stream-topic", "protocol": "A2A", "sessionid": "session-555", "seq": "1" }
methods/list.