This example demonstrates how to use the A2A Java SDK to communicate with an A2A server. The example includes a Java client that sends both regular and streaming messages to a Python A2A server.
- Java 11 or higher
- JBang (see INSTALL_JBANG.md for quick installation instructions)
- Python 3.8 or higher
- uv (recommended) or pip
- Git
The Python A2A server is part of the a2a-samples project. To set it up and run it:
-
Clone the a2a-samples repository:
git clone https://github.com/google-a2a/a2a-samples.git cd a2a-samples/samples/python/agents/helloworld -
Recommended method: Install dependencies using uv (much faster Python package installer):
# Install uv if you don't have it already # On macOS and Linux curl -LsSf https://astral.sh/uv/install.sh | sh # On Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex" # Install the package using uv uv venv source .venv/bin/activate # On Windows: .venv\Scripts\activate uv pip install -e .
-
Run the server with uv (recommended):
uv run .
The server will start running on http://localhost:9999.
Alternatively, you can use the Java server example instead of the Python server. The Java server supports multiple transport protocols (JSONRPC, GRPC, and HTTP+JSON). See the server README for details on starting the Java server with different transport protocols.
The Java client can be run using either Maven or JBang.
First, ensure you have built the a2a-java project:
cd /path/to/a2a-java
mvn clean installRun the client using Maven's exec plugin:
cd examples/helloworld/client
mvn exec:javaThe client supports multiple transport protocols. You can select which protocol to use via the quarkus.agentcard.protocol property:
Using JSONRPC (default):
mvn exec:javaUsing GRPC:
mvn exec:java -Dquarkus.agentcard.protocol=GRPCUsing HTTP+JSON:
mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSONAvailable protocols:
JSONRPC- Uses JSON-RPC for communication (default)GRPC- Uses gRPC for communicationHTTP+JSON- Uses HTTP with JSON payloads
Note: The protocol you select on the client must match the protocol configured on the server.
To enable OpenTelemetry with Maven:
mvn exec:java -Dopentelemetry=trueYou can combine protocol selection with OpenTelemetry:
mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=trueA JBang script is provided for running the client without Maven:
-
Make sure you have JBang installed. If not, follow the JBang installation guide.
-
Run the client using the JBang script:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java
Select the transport protocol using the same -Dquarkus.agentcard.protocol property:
Using JSONRPC (default):
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.javaUsing GRPC:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC Using HTTP+JSON:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSONTo enable OpenTelemetry with JBang:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=trueYou can combine protocol selection with OpenTelemetry:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -Dopentelemetry=trueThe Java client (HelloWorldClient.java) performs the following actions:
- Fetches the server's public agent card
- Fetches the server's extended agent card
- Creates a client using the extended agent card that connects to the Python server at
http://localhost:9999. - Sends a regular message asking "how much is 10 USD in INR?".
- Prints the server's response.
- Sends the same message as a streaming request.
- Prints each chunk of the server's streaming response as it arrives.
The client includes support for distributed tracing with OpenTelemetry. To enable it:
IMPORTANT: The client expects an OpenTelemetry collector to be ready and accepting traces. You have two options:
Instead of the Python server, use the Java server example which has built-in OpenTelemetry support:
-
Start the Java server with OpenTelemetry enabled:
mvn quarkus:dev -Popentelemetry -pl examples/helloworld/server/ -Dquarkus.agentcard.protocol=HTTP+JSON
This will:
- Start the server at
http://localhost:9999 - Launch Grafana at
http://localhost:3001 - Start OTLP collectors on ports 5317 (gRPC) and 5318 (HTTP)
- Start the server at
-
Run the client with OpenTelemetry:
Using Maven (from
examples/helloworld/client):mvn exec:java -Dopentelemetry=true
With specific protocol:
mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true
Or using JBang:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true
With specific protocol:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true
-
View traces in Grafana:
- Open
http://localhost:3001(credentials: admin/admin) - Go to "Explore" → select "Tempo" data source
- View distributed traces showing the full request flow from client to server
- Open
If you want to use the Python server with OpenTelemetry:
-
Start an OpenTelemetry collector on port 5317 (e.g., using Docker):
docker run -p 5317:4317 otel/opentelemetry-collector
-
Run the Python server
-
Run the client with OpenTelemetry:
mvn exec:java -Dopentelemetry=true
Or with JBang:
jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true
With specific protocol:
mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true
When OpenTelemetry is enabled, the client traces:
- Agent card fetching (public and extended)
- Message sending (blocking and streaming)
- Task operations (get, cancel, list)
- Push notification configuration operations
- Connection and transport layer operations
Client traces are automatically linked with server traces (when using the Java server), providing end-to-end visibility of the entire A2A protocol flow.
The client is configured to send traces to http://localhost:5317 (OTLP gRPC endpoint). To use a different endpoint, modify the initOpenTelemetry() method in HelloWorldClient.java:
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://your-collector:4317")
.build()- Make sure the Python server is running before starting the Java client.
- The client will wait for 10 seconds to collect streaming responses before exiting.
- You can modify the message text or server URL in the
HelloWorldClient.javafile if needed.