Package org.a2aproject.sdk.server.apps.quarkus


package org.a2aproject.sdk.server.apps.quarkus
Quarkus JSON-RPC reference implementation for the A2A protocol.

This package provides a production-ready JSON-RPC 2.0 server implementation built on Quarkus and Vert.x Web, demonstrating best practices for A2A protocol integration.

Architecture

HTTP Request (JSON-RPC 2.0)
    ↓
A2AServerRoutes (@Singleton)
    ├─ Parse JSON-RPC request
    ├─ Create ServerCallContext (via CallContextFactory)
    ├─ Route to JSONRPCHandler
    └─ Return JSON or SSE stream
        ↓
JSONRPCHandler (transport layer)
    ↓
DefaultRequestHandler (server-common)
    ↓
AgentExecutor (your implementation)

Core Components

JSON-RPC Endpoint

Main Endpoint: POST /[tenant]

Agent Card: GET /.well-known/agent-card.json

Request Format

POST /
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "req-123",
  "method": "sendMessage",
  "params": {
    "message": {
      "parts": [{"text": "Hello"}]
    }
  }
}

Response Formats

Non-Streaming (JSON):

HTTP/1.1 200 OK
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "req-123",
  "result": {
    "task": { ... }
  }
}

Streaming (SSE):

HTTP/1.1 200 OK
Content-Type: text/event-stream

id: 0
data: {"jsonrpc":"2.0","id":"req-123","result":{...}}

id: 1
data: {"jsonrpc":"2.0","id":"req-123","result":{...}}

Error Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "req-123",
  "error": {
    "code": -32602,
    "message": "Invalid params"
  }
}

Supported Methods

  • sendMessage - Send message (blocking)
  • sendStreamingMessage - Send message (streaming SSE)
  • subscribeToTask - Subscribe to task events (streaming SSE)
  • getTask - Get task by ID
  • listTasks - List tasks with filtering
  • cancelTask - Cancel task execution
  • getTaskPushNotificationConfig - Get push notification config
  • setTaskPushNotificationConfig - Create push notification config
  • listTaskPushNotificationConfigs - List push notification configs
  • deleteTaskPushNotificationConfig - Delete push notification config
  • getExtendedAgentCard - Get extended agent card

Multi-Tenancy

Tenant identification from request path:

  • POST / → empty tenant
  • POST /tenant1 → tenant "tenant1"

Customization

Custom Context Creation:

Provide a CDI bean implementing CallContextFactory:

@ApplicationScoped
public class CustomCallContextFactory implements CallContextFactory {
    @Override
    public ServerCallContext build(RoutingContext rc) {
        // Extract user from Quarkus security context
        User user = (rc.user() == null) ? UnauthenticatedUser.INSTANCE :
            new AuthenticatedUser(rc.user().subject());

        // Extract custom data from routing context
        Map<String, Object> state = new HashMap<>();
        state.put("organization", rc.request().getHeader("X-Org-ID"));

        // Extract A2A protocol version from header
        String version = rc.request().getHeader(A2AHeaders.X_A2A_VERSION);

        // Extract requested extensions from header
        List<String> extensionHeaders = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS);
        Set<String> extensions = A2AExtensions.getRequestedExtensions(extensionHeaders);

        return new ServerCallContext(user, state, extensions, version);
    }
}

Configuration

No JSON-RPC-specific configuration required. Standard Quarkus HTTP configuration applies:

quarkus.http.port=9999
quarkus.http.host=0.0.0.0

Authentication

Uses Quarkus Security with @Authenticated annotation on routes. Configure authentication in application.properties:

quarkus.security.users.embedded.enabled=true
quarkus.security.users.embedded.plain-text=true
quarkus.security.users.embedded.users.alice=password
See Also: