How to Set Up A2A Protocol Communication with Embabel: Complete Configuration Guide

To set up A2A protocol communication with Embabel, include the embabel-agent-a2a module in your Spring Boot application and rely on auto-configuration to instantiate the AgentCardHandler bean, which exposes the JSON-RPC endpoint at /a2a and publishes the Agent Card at .well-known/agent.json.

The A2A (Agent-to-Agent) protocol enables your Embabel agents to communicate via standardized HTTP JSON-RPC endpoints that external systems can query. By integrating the embabel-agent-a2a module from the embabel/embabel-agent repository, you expose any Embabel agent to interoperable workflows without writing custom controller logic.

Core Architecture of the A2A Implementation

The A2A protocol implementation consists of three coordinated components that wire automatically via Spring Boot auto-configuration. Understanding these classes helps you debug connectivity issues and extend default behaviors.

A2AConfiguration and AgentCardHandler

The A2AConfiguration class located at embabel-agent-a2a/src/main/kotlin/com/embabel/agent/a2a/server/config/A2AConfiguration.kt declares the primary AgentCardHandler bean. This handler registers the base endpoint under the path /a2a and publishes the Agent Card—a JSON metadata document describing the agent's name, capabilities, and provider information—at GET /a2a/.well-known/agent.json.

AutonomyA2ARequestHandler

Found in embabel-agent-a2a/src/main/kotlin/com/embabel/agent/a2a/server/support/AutonomyA2ARequestHandler.kt, this class receives the JSON-RPC payload from incoming HTTP requests. It forwards the deserialized message to the Embabel core AgentPlatform for processing, then constructs the appropriate response for both synchronous and streaming operations.

A2AEndpointRegistrar

The A2AEndpointRegistrar class in embabel-agent-a2a/src/main/kotlin/com/embabel/agent/a2a/server/support/A2AEndpointRegistrar.kt maps HTTP routes to Spring MVC controllers. It registers the main endpoint at /a2a along with task-specific sub-routes (/a2a/tasks/*), enabling the server to handle normal JSON-RPC calls and streaming connections through the same infrastructure.

Enabling Auto-Configuration

No manual bean definitions are required if you use Spring Boot's component scanning. Ensure your application or test class scans the com.embabel.agent.a2a package and enables auto-configuration:

@SpringBootApplication
@ComponentScan(basePackages = ["com.embabel.agent.a2a"])
@EnableAutoConfiguration
class MyEmbabelApplication

When the application context initializes, the A2AEndpointRegistrar automatically binds the routes. The AgentCardHandler becomes available immediately, exposing both the metadata endpoint and the message processing interface.

Testing A2A Communication

The A2AWebIntegrationTest class in embabel-agent-a2a/src/test/kotlin/com/embabel/agent/a2a/server/A2AWebIntegrationTest.kt demonstrates the complete interaction pattern using MockMvc.

Retrieving the Agent Card

Verify your setup by fetching the Agent Card to inspect capabilities and endpoint metadata:

@Test
fun `get agent card`() {
    val result = mockMvc.get("/a2a/.well-known/agent.json")
        .andExpect { status { isOk() } }
        .andReturn()
    
    val card = objectMapper.readValue(
        result.response.contentAsString, 
        AgentCard::class.java
    )
    println(card) // Contains name, description, capabilities, supported I/O modes
}

Sending Standard Messages

Construct a Message object, wrap it in a SendMessageRequest, and POST to /a2a:

@Test
fun `send message`() {
    val message = Message.Builder()
        .role(Message.Role.USER)
        .parts(listOf(TextPart("Hello!")))
        .messageId("msg-1")
        .taskId("task-1")
        .contextId("ctx-1")
        .build()
    
    val params = MessageSendParams.Builder()
        .message(message)
        .build()
    
    val request = SendMessageRequest.Builder()
        .jsonrpc(JSONRPCRequest.JSONRPC_VERSION)
        .method(SendMessageRequest.METHOD)
        .id("msg-1")
        .params(params)
        .build()

    val result = mockMvc.post("/a2a") {
        contentType = MediaType.APPLICATION_JSON
        content = objectMapper.writeValueAsString(request)
    }.andExpect { status { isOk() } }
      .andReturn()

    val response = objectMapper.readValue(
        result.response.contentAsString, 
        SendMessageResponse::class.java
    )
    println(response.result) // Task with completed status and conversation history
}

Handling Streaming Requests

For streaming scenarios, submit a SendStreamingMessageRequest to the same endpoint:

@Test
fun `send streaming message`() {
    val request = SendStreamingMessageRequest.Builder()
        .jsonrpc(JSONRPCRequest.JSONRPC_VERSION)
        .method(SendStreamingMessageRequest.METHOD)
        .id("stream-1")
        .params(/* MessageSendParams containing the message */)
        .build()

    mockMvc.post("/a2a") {
        contentType = MediaType.APPLICATION_JSON
        content = objectMapper.writeValueAsString(request)
    }.andExpect { status { isOk() } }
}

The server accepts the streaming payload immediately. Server-Sent Events (SSE) transport is handled separately by the underlying Spring MVC infrastructure once the request is accepted.

Summary

  • The A2A protocol exposes Embabel agents as JSON-RPC HTTP endpoints mounted at /a2a.
  • Auto-configuration via A2AConfiguration creates the AgentCardHandler bean automatically when the embabel-agent-a2a module is detected on the classpath.
  • The Agent Card publishes service metadata at /a2a/.well-known/agent.json, enabling discovery by other agents.
  • Request processing is handled by AutonomyA2ARequestHandler, which delegates to the core AgentPlatform for business logic execution.
  • Both standard (SendMessageRequest) and streaming (SendStreamingMessageRequest) interaction patterns are supported without additional configuration.

Frequently Asked Questions

What is the default URL path for the A2A endpoint in Embabel?

The A2A endpoint mounts at /a2a for all JSON-RPC message traffic. The Agent Card describing the agent's capabilities is available at GET /a2a/.well-known/agent.json. These paths are registered automatically by the A2AEndpointRegistrar class during application startup.

Does Embabel support streaming messages via A2A?

Yes. The AutonomyA2ARequestHandler accepts SendStreamingMessageRequest payloads at the same /a2a endpoint. While the request body initiates the stream, the actual Server-Sent Events (SSE) transport is handled separately by the underlying Spring MVC infrastructure.

How do I verify my A2A setup is working correctly?

Run the A2AWebIntegrationTest suite located in embabel-agent-a2a/src/test/kotlin/com/embabel/agent/a2a/server/A2AWebIntegrationTest.kt. This test validates Agent Card retrieval, standard message processing, and streaming request acceptance using MockMvc to simulate HTTP traffic against the full endpoint stack.

What dependencies are required to enable A2A protocol support?

You must include the embabel-agent-a2a module in your classpath. Spring Boot's auto-configuration detects the presence of this module and instantiates the required beans—including AgentCardHandler, AutonomyA2ARequestHandler, and A2AEndpointRegistrar—without requiring explicit configuration in your application code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →