# a2a-java **Repository Path**: abaoworld/a2a-java ## Basic Information - **Project Name**: a2a-java - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: code-analysis - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-19 - **Last Updated**: 2026-06-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # A2A Java SDK [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)

A2A Logo

A Java library that helps run agentic applications as A2AServers following the Agent2Agent (A2A) Protocol.

## Installation You can build the A2A Java SDK using `mvn`: ```bash mvn clean install ``` ### Regeneration of gRPC files We copy https://github.com/a2aproject/A2A/blob/main/specification/grpc/a2a.proto to the [`spec-grpc/`](./spec-grpc) project, and adjust the `java_package` option to be as follows: ``` option java_package = "org.a2aproject.sdk.grpc"; ``` Then build the `spec-grpc` module with `mvn clean install -Dskip.protobuf.generate=false` to regenerate the gRPC classes in the `org.a2aproject.sdk.grpc` package. ## Examples You can find examples of how to use the A2A Java SDK in the [a2a-samples repository](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents). More examples will be added soon. ## A2A Server The A2A Java SDK provides a Java server implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). To run your agentic Java application as an A2A server, simply follow the steps below. - [Add an A2A Java SDK Server Maven dependency to your project](#1-add-an-a2a-java-sdk-server-maven-dependency-to-your-project) - [Add a class that creates an A2A Agent Card](#2-add-a-class-that-creates-an-a2a-agent-card) - [Add a class that creates an A2A Agent Executor](#3-add-a-class-that-creates-an-a2a-agent-executor) ### 1. Add an A2A Java SDK Server Maven dependency to your project Adding a dependency on an A2A Java SDK Server will provide access to the core classes that make up the A2A specification and allow you to run your agentic Java application as an A2A server agent. The A2A Java SDK provides [reference A2A server implementations](reference) based on [Quarkus](https://quarkus.io) for use with our tests and examples. However, the project is designed in such a way that it is trivial to integrate with various Java runtimes. [Server Integrations](#server-integrations) contains a list of community contributed integrations of the server with various runtimes. You might be able to use one of these for your target runtime, or you can use them as inspiration to create your own. #### Server Transports The A2A Java SDK Reference Server implementations support the following transports: * JSON-RPC 2.0 * gRPC * HTTP+JSON/REST To use the reference implementation with the JSON-RPC protocol, add the following dependency to your project: ```xml org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc ${org.a2aproject.sdk.version} ``` To use the reference implementation with the gRPC protocol, add the following dependency to your project: ```xml org.a2aproject.sdk a2a-java-sdk-reference-grpc ${org.a2aproject.sdk.version} ``` To use the reference implementation with the HTTP+JSON/REST protocol, add the following dependency to your project: ```xml org.a2aproject.sdk a2a-java-sdk-reference-rest ${org.a2aproject.sdk.version} ``` Note that you can add more than one of the above dependencies to your project depending on the transports you'd like to support. ### 2. Add a class that creates an A2A Agent Card ```java import org.a2aproject.sdk.server.PublicAgentCard; import org.a2aproject.sdk.spec.AgentCapabilities; import org.a2aproject.sdk.spec.AgentCard; import org.a2aproject.sdk.spec.AgentInterface; import org.a2aproject.sdk.spec.AgentSkill; import org.a2aproject.sdk.spec.TransportProtocol; ... @ApplicationScoped public class WeatherAgentCardProducer { private static final String AGENT_URL = "http://localhost:10001"; @Produces @PublicAgentCard public AgentCard agentCard() { return AgentCard.builder() .name("Weather Agent") .description("Helps with weather") .supportedInterfaces(List.of( new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL))) .version("1.0.0") .capabilities(AgentCapabilities.builder() .streaming(true) .pushNotifications(false) .build()) .defaultInputModes(Collections.singletonList("text")) .defaultOutputModes(Collections.singletonList("text")) .skills(Collections.singletonList(AgentSkill.builder() .id("weather_search") .name("Search weather") .description("Helps with weather in cities or states") .tags(Collections.singletonList("weather")) .examples(List.of("weather in LA, CA")) .build())) .build(); } } ``` ### 3. Add a class that creates an A2A Agent Executor ```java import org.a2aproject.sdk.server.agentexecution.AgentExecutor; import org.a2aproject.sdk.server.agentexecution.RequestContext; import org.a2aproject.sdk.server.events.EventQueue; import org.a2aproject.sdk.server.tasks.AgentEmitter; import org.a2aproject.sdk.spec.JSONRPCError; import org.a2aproject.sdk.spec.Message; import org.a2aproject.sdk.spec.Part; import org.a2aproject.sdk.spec.Task; import org.a2aproject.sdk.spec.TaskNotCancelableError; import org.a2aproject.sdk.spec.TaskState; import org.a2aproject.sdk.spec.TextPart; ... @ApplicationScoped public class WeatherAgentExecutorProducer { @Inject WeatherAgent weatherAgent; @Produces public AgentExecutor agentExecutor() { return new WeatherAgentExecutor(weatherAgent); } private static class WeatherAgentExecutor implements AgentExecutor { private final WeatherAgent weatherAgent; public WeatherAgentExecutor(WeatherAgent weatherAgent) { this.weatherAgent = weatherAgent; } @Override public void execute(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { // mark the task as submitted and start working on it if (context.getTask() == null) { agentEmitter.submit(); } agentEmitter.startWork(); // extract the text from the message String userMessage = extractTextFromMessage(context.getMessage()); // call the weather agent with the user's message String response = weatherAgent.chat(userMessage); // create the response part TextPart responsePart = new TextPart(response); List> parts = List.of(responsePart); // add the response as an artifact and complete the task agentEmitter.addArtifact(parts); agentEmitter.complete(); } @Override public void cancel(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { Task task = context.getTask(); if (task.getStatus().state() == TaskState.CANCELED) { // task already cancelled throw new TaskNotCancelableError(); } if (task.getStatus().state() == TaskState.COMPLETED) { // task already completed throw new TaskNotCancelableError(); } // cancel the task agentEmitter.cancel(); } private String extractTextFromMessage(Message message) { StringBuilder textBuilder = new StringBuilder(); for (Part part : message.parts()) { if (part instanceof TextPart textPart) { textBuilder.append(textPart.text()); } } return textBuilder.toString(); } } } ``` ### 4. Configuration System The A2A Java SDK uses a flexible configuration system that works across different frameworks. **Default behavior:** Configuration values come from `META-INF/a2a-defaults.properties` files on the classpath (provided by core modules and extras). These defaults work out of the box without any additional setup. **Customizing configuration:** - **Quarkus/MicroProfile Config users**: Add the [`microprofile-config`](integrations/microprofile-config/README.md) integration to override defaults via `application.properties`, environment variables, or system properties - **Spring/other frameworks**: See the [integration module README](integrations/microprofile-config/README.md#custom-config-providers) for how to implement a custom `A2AConfigProvider` - **Reference implementations**: Already include the MicroProfile Config integration #### Configuration Properties **Executor Settings** (Optional) The SDK uses a dedicated executor for async operations like streaming. Default: 5 core threads, 50 max threads. ```properties # Core thread pool size for the @Internal executor (default: 5) a2a.executor.core-pool-size=5 # Maximum thread pool size (default: 50) a2a.executor.max-pool-size=50 # Thread keep-alive time in seconds (default: 60) a2a.executor.keep-alive-seconds=60 ``` **Blocking Call Timeouts** (Optional) ```properties # Timeout for agent execution in blocking calls (default: 30 seconds) a2a.blocking.agent.timeout.seconds=30 # Timeout for event consumption in blocking calls (default: 5 seconds) a2a.blocking.consumption.timeout.seconds=5 ``` **Why this matters:** - **Streaming Performance**: The executor handles streaming subscriptions. Too few threads can cause timeouts under concurrent load. - **Resource Management**: The dedicated executor prevents streaming operations from competing with the ForkJoinPool. - **Concurrency**: In production with high concurrent streaming, increase pool sizes accordingly. - **Agent Timeouts**: LLM-based agents may need longer timeouts (60-120s) compared to simple agents. **Note:** The reference server implementations (Quarkus-based) automatically include the MicroProfile Config integration, so properties work out of the box in `application.properties`. ### Serving Older Protocol Versions (Backward Compatibility) The A2A Java SDK includes compatibility layers that allow your server to accept requests from clients using older protocol versions. Each compatibility layer is a separate set of modules that you add to your project as needed. **No changes to your `AgentExecutor` are needed** — the compatibility layer converts older protocol requests to v1.0 internally before delegating to your agent. #### Adding v0.3 Protocol Support To enable v0.3 support, add the v0.3 compat reference module for your chosen transport alongside (or instead of) the v1.0 reference module: ```xml org.a2aproject.sdk a2a-java-sdk-compat-0.3-reference-jsonrpc ${org.a2aproject.sdk.version} org.a2aproject.sdk a2a-java-sdk-compat-0.3-reference-rest ${org.a2aproject.sdk.version} org.a2aproject.sdk a2a-java-sdk-compat-0.3-reference-grpc ${org.a2aproject.sdk.version} ``` For example, a server that supports **v1.0 and v0.3 over JSON-RPC** would include both: ```xml org.a2aproject.sdk a2a-java-sdk-reference-jsonrpc ${org.a2aproject.sdk.version} org.a2aproject.sdk a2a-java-sdk-compat-0.3-reference-jsonrpc ${org.a2aproject.sdk.version} ``` A server that only needs to support **v0.3** would include only the compat dependency. #### Multi-Version Convenience Modules For JSON-RPC and REST, multi-version modules are provided that bundle all supported protocol versions together with version-dispatching routes: ```xml org.a2aproject.sdk a2a-java-sdk-reference-multiversion-jsonrpc ${org.a2aproject.sdk.version} org.a2aproject.sdk a2a-java-sdk-reference-multiversion-rest ${org.a2aproject.sdk.version} ``` These are a convenience — they transitively include all the individual compat reference modules. #### How Version Routing Works - **JSON-RPC and REST**: When serving multiple protocol versions, version routing inspects the `A2A-Version` HTTP header on each request. If the header is `"1.0"`, the request is routed to the v1.0 handler. If it is `"0.3"` or absent, the request is routed to the v0.3 handler. - **gRPC**: Version dispatch is implicit — v0.3 clients use the `a2a.v1` protobuf package and v1.0 clients use `lf.a2a.v1`, so requests are routed to the correct service automatically. - **Agent card**: When both v1.0 and v0.3 are enabled, the v1.0 `AgentCard` takes precedence and is served at `/.well-known/agent-card.json`. The v0.3 `AgentCard_v0_3` is ignored. If only v0.3 is enabled, the v0.3 agent card is used. If only v1.0 is enabled, the v1.0 agent card is used as-is. #### Making the v1.0 Agent Card Compatible with v0.3 Clients When serving both protocol versions, you need to ensure the v1.0 agent card contains fields that v0.3 clients expect. Existing v0.3 client implementations (in any language) look for `url`, `preferredTransport`, and `additionalInterfaces` with `transport`/`url` entries — fields that don't exist in the v1.0 format by default. To make your v1.0 `AgentCard` parsable by v0.3 clients, set these fields on the builder: ```java AgentCard card = AgentCard.builder() .name("My Agent") // ... other v1.0 fields ... .supportedInterfaces(List.of( new AgentInterface("jsonrpc", "http://localhost:9999"))) // v0.3 backward-compatibility fields: .url("http://localhost:9999") .preferredTransport("jsonrpc") .additionalInterfaces(List.of( new Legacy_0_3_AgentInterface("jsonrpc", "http://localhost:9999"))) .build(); ``` The two interface lists serve different clients: - `supportedInterfaces` — used by **v1.0 clients** to discover endpoints (uses `AgentInterface` with `protocolBinding`/`url`/`tenant` fields) - `additionalInterfaces` — used by **v0.3 clients** to discover endpoints (uses `Legacy_0_3_AgentInterface` with v0.3 field names: `transport`/`url`) - `url` and `preferredTransport` — top-level fields that v0.3 clients use to discover the primary endpoint #### Push Notification Behavior Push notification payloads are automatically formatted to match the protocol version used when the push notification configuration was registered. When a v0.3 client registers a push notification configuration (via any transport), the server records the protocol version alongside the configuration. When a notification is later sent to that webhook, the payload is formatted as a v0.3 Task object. Configurations registered by v1.0 clients receive v1.0 `StreamResponse` payloads as usual. This happens transparently — no additional configuration is needed beyond adding the compat reference module. ## A2A Client The A2A Java SDK provides a Java client implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/), allowing communication with A2A servers. The Java client implementation supports the following transports: * JSON-RPC 2.0 * gRPC * HTTP+JSON/REST To make use of the Java `Client`: ### 1. Add the A2A Java SDK Client dependency to your project Adding a dependency on `a2a-java-sdk-client` will provide access to a `ClientBuilder` that you can use to create your A2A `Client`. ```xml org.a2aproject.sdk a2a-java-sdk-client ${org.a2aproject.sdk.version} ``` ### 2. Add one or more dependencies on the A2A Java SDK Client Transport(s) you'd like to use By default, the `sdk-client` artifact includes the JSONRPC transport dependency. However, you must still explicitly configure this transport when building the `Client` as described in the [JSON-RPC Transport section](#json-rpc-transport-configuration). If you want to use the gRPC transport, you'll need to add a relevant dependency: ```xml org.a2aproject.sdk a2a-java-sdk-client-transport-grpc ${org.a2aproject.sdk.version} ``` If you want to use the HTTP+JSON/REST transport, you'll need to add a relevant dependency: ```xml org.a2aproject.sdk a2a-java-sdk-client-transport-rest ${org.a2aproject.sdk.version} ``` ### Sample Usage #### Create a Client using the ClientBuilder ```java // First, get the agent card for the A2A server agent you want to connect to AgentCard agentCard = A2ACardResolver.builder().baseUrl("http://localhost:1234").build().getAgentCard(); // Specify configuration for the ClientBuilder ClientConfig clientConfig = new ClientConfig.Builder() .setAcceptedOutputModes(List.of("text")) .build(); // Create event consumers to handle responses that will be received from the A2A server // (these consumers will be used for both streaming and non-streaming responses) List> consumers = List.of( (event, card) -> { if (event instanceof MessageEvent messageEvent) { // handle the messageEvent.getMessage() ... } else if (event instanceof TaskEvent taskEvent) { // handle the taskEvent.getTask() ... } else if (event instanceof TaskUpdateEvent updateEvent) { // handle the updateEvent.getTask() ... } } ); // Create a handler that will be used for any errors that occur during streaming Consumer errorHandler = error -> { // handle the error.getMessage() ... }; // Create the client using the builder Client client = Client .builder(agentCard) .clientConfig(clientConfig) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) .addConsumers(consumers) .streamingErrorHandler(errorHandler) .build(); ``` #### Configuring Transport-Specific Settings Different transport protocols can be configured with specific settings using specific `ClientTransportConfig` implementations. The A2A Java SDK provides `JSONRPCTransportConfig` for the JSON-RPC transport and `GrpcTransportConfig` for the gRPC transport. ##### JSON-RPC Transport Configuration For the JSON-RPC transport, to use the default `JdkA2AHttpClient`, provide a `JSONRPCTransportConfig` created with its default constructor. To use a custom HTTP client implementation, simply create a `JSONRPCTransportConfig` as follows: ```java // Create a custom HTTP client A2AHttpClient customHttpClient = ... // Configure the client settings ClientConfig clientConfig = new ClientConfig.Builder() .setAcceptedOutputModes(List.of("text")) .build(); Client client = Client .builder(agentCard) .clientConfig(clientConfig) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig(customHttpClient)) .build(); ``` To customize the default JDK HTTP client without replacing the SDK implementation, provide your own `java.net.http.HttpClient` to `JdkA2AHttpClient`: ```java HttpClient jdkHttpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) .followRedirects(HttpClient.Redirect.NORMAL) .version(HttpClient.Version.HTTP_2) .build(); Client client = Client .builder(agentCard) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig( new JdkA2AHttpClient(jdkHttpClient))) .build(); ``` ##### gRPC Transport Configuration For the gRPC transport, you must configure a channel factory: ```java // Create a channel factory function that takes the agent URL and returns a Channel Function channelFactory = agentUrl -> { return ManagedChannelBuilder.forTarget(agentUrl) ... .build(); }; // Configure the client with transport-specific settings ClientConfig clientConfig = new ClientConfig.Builder() .setAcceptedOutputModes(List.of("text")) .build(); Client client = Client .builder(agentCard) .clientConfig(clientConfig) .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) .build(); ``` ##### HTTP+JSON/REST Transport Configuration For the HTTP+JSON/REST transport, if you'd like to use the default `JdkA2AHttpClient`, provide a `RestTransportConfig` created with its default constructor. To use a custom HTTP client implementation, simply create a `RestTransportConfig` as follows: ```java // Create a custom HTTP client A2AHttpClient customHttpClient = ... // Configure the client settings ClientConfig clientConfig = new ClientConfig.Builder() .setAcceptedOutputModes(List.of("text")) .build(); Client client = Client .builder(agentCard) .clientConfig(clientConfig) .withTransport(RestTransport.class, new RestTransportConfig(customHttpClient)) .build(); ``` ##### Multiple Transport Configurations You can specify configuration for multiple transports, the appropriate configuration will be used based on the selected transport: ```java // Configure both JSON-RPC and gRPC transports Client client = Client .builder(agentCard) .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) .withTransport(RestTransport.class, new RestTransportConfig()) .build(); ``` #### Send a message to the A2A server agent ```java // Send a text message to the A2A server agent Message message = A2A.toUserMessage("tell me a joke"); // Send the message (uses configured consumers to handle responses) // Streaming will automatically be used if supported by both client and server, // otherwise the non-streaming send message method will be used automatically client.sendMessage(message); // You can also optionally specify a ClientCallContext with call-specific config to use client.sendMessage(message, clientCallContext); ``` #### Send a message with custom event handling ```java // Create custom consumers for this specific message List> customConsumers = List.of( (event, card) -> { // handle this specific message's responses ... } ); // Create custom error handler Consumer customErrorHandler = error -> { // handle the error ... }; Message message = A2A.toUserMessage("tell me a joke"); client.sendMessage(message, customConsumers, customErrorHandler); ``` #### Get the current state of a task ```java // Retrieve the task with id "task-1234" Task task = client.getTask(new TaskQueryParams("task-1234")); // You can also specify the maximum number of history items for the task // to include in the response Task task = client.getTask(new TaskQueryParams("task-1234", 10)); // You can also optionally specify a ClientCallContext with call-specific config to use Task task = client.getTask(new TaskQueryParams("task-1234"), clientCallContext); ``` #### Cancel an ongoing task ```java // Cancel the task we previously submitted with id "task-1234" Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234")); // You can also specify additional properties using a map Map metadata = Map.of("reason", "user_requested"); Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234", metadata)); // You can also optionally specify a ClientCallContext with call-specific config to use Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234"), clientCallContext); ``` #### Get a push notification configuration for a task ```java // Get task push notification configuration TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("task-1234")); // The push notification configuration ID can also be optionally specified TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("task-1234", "config-4567")); // Additional properties can be specified using a map Map metadata = Map.of("source", "client"); TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("task-1234", "config-1234", metadata)); // You can also optionally specify a ClientCallContext with call-specific config to use TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( new GetTaskPushNotificationConfigParams("task-1234"), clientCallContext); ``` #### Set a push notification configuration for a task ```java // Set task push notification configuration PushNotificationConfig pushNotificationConfig = PushNotificationConfig.builder() .url("https://example.com/callback") .authenticationInfo(new AuthenticationInfo(Collections.singletonList("jwt"), null)) .build(); TaskPushNotificationConfig taskConfig = TaskPushNotificationConfig.builder() .taskId("task-1234") .pushNotificationConfig(pushNotificationConfig) .build(); TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig); // You can also optionally specify a ClientCallContext with call-specific config to use TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig, clientCallContext); ``` #### List the push notification configurations for a task ```java List configs = client.listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams("task-1234")); // Additional properties can be specified using a map Map metadata = Map.of("filter", "active"); List configs = client.listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams("task-1234", metadata)); // You can also optionally specify a ClientCallContext with call-specific config to use List configs = client.listTaskPushNotificationConfigurations( new ListTaskPushNotificationConfigParams("task-1234"), clientCallContext); ``` #### Delete a push notification configuration for a task ```java client.deleteTaskPushNotificationConfigurations( new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567")); // Additional properties can be specified using a map Map metadata = Map.of("reason", "cleanup"); client.deleteTaskPushNotificationConfigurations( new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567", metadata)); // You can also optionally specify a ClientCallContext with call-specific config to use client.deleteTaskPushNotificationConfigurations( new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567", clientCallContext); ``` #### Subscribe to a task ```java // Subscribe to an ongoing task with id "task-1234" using configured consumers TaskIdParams taskIdParams = new TaskIdParams("task-1234"); client.subscribeToTask(taskIdParams); // Or subscribe with custom consumers and error handler List> customConsumers = List.of( (event, card) -> System.out.println("Subscribe event: " + event) ); Consumer customErrorHandler = error -> System.err.println("Subscribe error: " + error.getMessage()); client.subscribeToTask(taskIdParams, customConsumers, customErrorHandler); // You can also optionally specify a ClientCallContext with call-specific config to use client.subscribeToTask(taskIdParams, clientCallContext); ``` #### Retrieve details about the server agent that this client agent is communicating with ```java AgentCard serverAgentCard = client.getAgentCard(); ``` ### Communicating with v0.3 Agents If you need to communicate with an agent that only supports protocol v0.3, use the compatibility client `Client_v0_3`. #### 1. Add the v0.3 client dependency ```xml org.a2aproject.sdk a2a-java-sdk-compat-0.3-client ${org.a2aproject.sdk.version} ``` #### 2. Add a v0.3 client transport dependency ```xml org.a2aproject.sdk a2a-java-sdk-compat-0.3-client-transport-jsonrpc ${org.a2aproject.sdk.version} ``` gRPC and REST transports are also available: - `a2a-java-sdk-compat-0.3-client-transport-grpc` - `a2a-java-sdk-compat-0.3-client-transport-rest` #### 3. Create the v0.3 client ```java AgentCard card = A2ACardResolver.builder().baseUrl("http://localhost:1234").build().getAgentCard(); // Find the v0.3 interface from the agent card AgentInterface v03Interface = card.supportedInterfaces().stream() .filter(iface -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(iface.protocolVersion())) .findFirst() .orElseThrow(); // Create the v0.3 compatibility client Client_v0_3 client = ClientBuilder_v0_3.forUrl(v03Interface.url()) .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) .build(); ``` **Note:** `Client_v0_3` exposes only operations available in protocol v0.3. For example, `listTasks()` is not available (it was added in v1.0). Return types use v0.3 domain objects from the `org.a2aproject.sdk.compat03.spec` package. ## Additional Examples ### Hello World Client Example A complete example of a Java A2A client communicating with a Python A2A server is available in the [examples/helloworld/client](examples/helloworld/client/README.md) directory. This example demonstrates: - Setting up and using the A2A Java client - Sending regular and streaming messages to a Python A2A server - Receiving and processing responses from the Python A2A server The example includes detailed instructions on how to run the Python A2A server and how to run the Java A2A client using JBang. Check out the [example's README](examples/helloworld/client/README.md) for more information. ### Hello World Server Example A complete example of a Python A2A client communicating with a Java A2A server is available in the [examples/helloworld/server](examples/helloworld/server/README.md) directory. This example demonstrates: - A sample `AgentCard` producer - A sample `AgentExecutor` producer - A Java A2A server receiving regular and streaming messages from a Python A2A client Check out the [example's README](examples/helloworld/server/README.md) for more information. ## Community Articles See [COMMUNITY_ARTICLES.md](COMMUNITY_ARTICLES.md) for a list of community articles and videos. ## License This project is licensed under the terms of the [Apache 2.0 License](LICENSE). ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. ## Server Integrations The following list contains community contributed integrations with various Java Runtimes. To contribute an integration, please see [CONTRIBUTING_INTEGRATIONS.md](CONTRIBUTING_INTEGRATIONS.md). * This project contains integration with Quarkus and has the reference implementations for the JSON-RPC, gRPC, and HTTP+JSON (REST) transports. * https://github.com/wildfly-extras/a2a-jakarta - This integration is based on Jakarta EE, and should work in all runtimes supporting the [Jakarta EE Web Profile](https://jakarta.ee/specifications/webprofile/). # Extras See the [`extras`](./extras/README.md) folder for extra functionality not provided by the SDK itself!