http://localhost:9007/.well-known/agent.json http://localhost:9007/.well-known/agent-card.json
http://localhost:9008/.well-known/agent.json http://localhost:9008/.well-known/agent-card.json
- http://localhost:9006/docs (with FastAPI)
drwxr-xr-x@ 5 welcome staff 160 Dec 20 23:14 helloworld
(a2a-examples) welcome@jaisairams-Laptop A2A_Examples % python helloworld/__main__.py
INFO: Started server process [31227]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:9999 (Press CTRL+C to quit)
INFO: 127.0.0.1:49698 - "GET /.well-known/agent-card.json HTTP/1.1" 200 OK
HTTP GET for authenticated extended card has been called by a client. This endpoint is deprecated in favor of agent/authenticatedExtendedCard JSON-RPC method and will be removed in a future release.
INFO: 127.0.0.1:49698 - "GET /agent/authenticatedExtendedCard HTTP/1.1" 200 OK
INFO: 127.0.0.1:49698 - "POST / HTTP/1.1" 200 OK
INFO: 127.0.0.1:49698 - "POST / HTTP/1.1" 200 OK
welcome@jaisairams-Laptop A2A_Examples % source ~/.zprofile.sh
welcome@jaisairams-Laptop A2A_Examples % source .venv/bin/activate
(a2a-examples) welcome@jaisairams-Laptop A2A_Examples %
(a2a-examples) welcome@jaisairams-Laptop A2A_Examples % python helloworld/test_client.py
INFO:__main__:Attempting to fetch public agent card from: http://localhost:9999/.well-known/agent-card.json
INFO:httpx:HTTP Request: GET http://localhost:9999/.well-known/agent-card.json "HTTP/1.1 200 OK"
INFO:a2a.client.card_resolver:Successfully fetched agent card data from http://localhost:9999/.well-known/agent-card.json: {'capabilities': {'streaming': True}, 'defaultInputModes': ['text'], 'defaultOutputModes': ['text'], 'description': 'Just a hello world agent', 'name': 'Hello World Agent', 'preferredTransport': 'JSONRPC', 'protocolVersion': '0.3.0', 'skills': [{'description': 'just returns hello world', 'examples': ['hi', 'hello world'], 'id': 'hello_world', 'name': 'Returns hello world', 'tags': ['hello world']}], 'supportsAuthenticatedExtendedCard': True, 'url': 'http://localhost:9999/', 'version': '1.0.0'}
INFO:__main__:Successfully fetched public agent card:
INFO:__main__:{
"capabilities": {
"streaming": true
},
"defaultInputModes": [
"text"
],
"defaultOutputModes": [
"text"
],
"description": "Just a hello world agent",
"name": "Hello World Agent",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
"skills": [
{
"description": "just returns hello world",
"examples": [
"hi",
"hello world"
],
"id": "hello_world",
"name": "Returns hello world",
"tags": [
"hello world"
]
}
],
"supportsAuthenticatedExtendedCard": true,
"url": "http://localhost:9999/",
"version": "1.0.0"
}
INFO:__main__:
Using PUBLIC agent card for client initialization (default).
INFO:__main__:
Public card supports authenticated extended card. Attempting to fetch from: http://localhost:9999/agent/authenticatedExtendedCard
INFO:httpx:HTTP Request: GET http://localhost:9999/agent/authenticatedExtendedCard "HTTP/1.1 200 OK"
INFO:a2a.client.card_resolver:Successfully fetched agent card data from http://localhost:9999/agent/authenticatedExtendedCard: {'capabilities': {'streaming': True}, 'defaultInputModes': ['text'], 'defaultOutputModes': ['text'], 'description': 'The full-featured hello world agent for authenticated users.', 'name': 'Hello World Agent - Extended Edition', 'preferredTransport': 'JSONRPC', 'protocolVersion': '0.3.0', 'skills': [{'description': 'just returns hello world', 'examples': ['hi', 'hello world'], 'id': 'hello_world', 'name': 'Returns hello world', 'tags': ['hello world']}, {'description': 'A more enthusiastic greeting, only for authenticated users.', 'examples': ['super hi', 'give me a super hello'], 'id': 'super_hello_world', 'name': 'Returns a SUPER Hello World', 'tags': ['hello world', 'super', 'extended']}], 'supportsAuthenticatedExtendedCard': True, 'url': 'http://localhost:9999/', 'version': '1.0.1'}
INFO:__main__:Successfully fetched authenticated extended agent card:
INFO:__main__:{
"capabilities": {
"streaming": true
},
"defaultInputModes": [
"text"
],
"defaultOutputModes": [
"text"
],
"description": "The full-featured hello world agent for authenticated users.",
"name": "Hello World Agent - Extended Edition",
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0",
"skills": [
{
"description": "just returns hello world",
"examples": [
"hi",
"hello world"
],
"id": "hello_world",
"name": "Returns hello world",
"tags": [
"hello world"
]
},
{
"description": "A more enthusiastic greeting, only for authenticated users.",
"examples": [
"super hi",
"give me a super hello"
],
"id": "super_hello_world",
"name": "Returns a SUPER Hello World",
"tags": [
"hello world",
"super",
"extended"
]
}
],
"supportsAuthenticatedExtendedCard": true,
"url": "http://localhost:9999/",
"version": "1.0.1"
}
INFO:__main__:
Using AUTHENTICATED EXTENDED agent card for client initialization.
/Users/welcome/Desktop/Tech_Repos/python_envs/A2A/A2A_event_agents/A2A_Examples/helloworld/test_client.py:105: DeprecationWarning: A2AClient is deprecated and will be removed in a future version. Use ClientFactory to create a client with a JSON-RPC transport.
client = A2AClient(
INFO:__main__:A2AClient initialized.
INFO:httpx:HTTP Request: POST http://localhost:9999/ "HTTP/1.1 200 OK"
{'id': '69c93f2c-130e-4fea-a02c-c32bcc1c8b04', 'jsonrpc': '2.0', 'result': {'kind': 'message', 'messageId': 'bab14d85-8168-4c39-bf10-e31671358dd2', 'parts': [{'kind': 'text', 'text': 'Hello World'}], 'role': 'agent'}}
INFO:httpx:HTTP Request: POST http://localhost:9999/ "HTTP/1.1 200 OK"
{'id': 'b4cae74c-1b7c-49fd-9b27-d152a80015f8', 'jsonrpc': '2.0', 'result': {'kind': 'message', 'messageId': '33420605-7151-41d0-917c-1eff0dde2c86', 'parts': [{'kind': 'text', 'text': 'Hello World'}], 'role': 'agent'}}
(a2a-examples) welcome@jaisairams-Laptop A2A_Examples %
# 6. Interacting with the Server
With the Helloworld A2A server running, let's send some requests to it. The SDK includes a client (`A2AClient`) that simplifies these interactions.
## The Helloworld Test Client
The `test_client.py` script demonstrates how to:
1. Fetch the Agent Card from the server.
2. Create an `A2AClient` instance.
3. Send both non-streaming (`message/send`) and streaming (`message/stream`) requests.
Open a **new terminal window**, activate your virtual environment, and navigate to the `a2a-samples` directory.
Activate virtual environment (Be sure to do this in the same directory where you created the virtual environment):
=== "Mac/Linux"
```sh
source .venv/bin/activate
```
=== "Windows"
```powershell
.venv\Scripts\activate
```
Run the test client:
```bash
# from the a2a-samples directory
python samples/python/agents/helloworld/test_client.py
Let's look at key parts of test_client.py:
-
Fetching the Agent Card & Initializing the Client:
--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:A2ACardResolver"
The
A2ACardResolverclass is a convenience. It first fetches theAgentCardfrom the server's/.well-known/agent-card.jsonendpoint (based on the provided base URL) and then initializes the client with it. -
Sending a Non-Streaming Message (
send_message):--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message"
- The
send_message_payloadconstructs the data forMessageSendParams. - This is wrapped in a
SendMessageRequest. - It includes a
messageobject with theroleset to "user" and the content inparts. - The Helloworld agent's
executemethod will enqueue a single "Hello World" message. TheDefaultRequestHandlerwill retrieve this and send it as the response. - The
responsewill be aSendMessageResponseobject, which contains either aSendMessageSuccessResponse(with the agent'sMessageas the result) or aJSONRPCErrorResponse.
- The
-
Handling Task IDs (Illustrative Note for Helloworld):
The Helloworld client (
test_client.py) doesn't attemptget_taskorcancel_taskdirectly because the simple Helloworld agent'sexecutemethod, when called viamessage/send, results in theDefaultRequestHandlerreturning a directMessageresponse rather than aTaskobject. More complex agents that explicitly manage tasks (like the LangGraph example) would return aTaskobject frommessage/send, and itsidcould then be used forget_taskorcancel_task. -
Sending a Streaming Message (
send_message_streaming):--8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:send_message_streaming"
- This method calls the agent's
message/streamendpoint. TheDefaultRequestHandlerwill invoke theHelloWorldAgentExecutor.executemethod. - The
executemethod enqueues one "Hello World" message, and then the event queue is closed. - The client will receive this single message as one
SendStreamingMessageResponseevent, and then the stream will terminate. - The
stream_responseis anAsyncGenerator.
- This method calls the agent's
When you run test_client.py, you'll see JSON outputs for:
- The non-streaming response (a single "Hello World" message).
- The streaming response (a single "Hello World" message as one chunk, after which the stream ends).
The id fields in the output will vary with each run.
// Non-streaming response
{"jsonrpc":"2.0","id":"xxxxxxxx","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"yyyyyyyy"}}
// Streaming response (one chunk)
{"jsonrpc":"2.0","id":"zzzzzzzz","result":{"type":"message","role":"agent","parts":[{"type":"text","text":"Hello World"}],"messageId":"wwwwwwww","final":true}}(Actual IDs like xxxxxxxx, yyyyyyyy, zzzzzzzz, wwwwwwww will be different UUIDs/request IDs)
This confirms your server is correctly handling basic A2A interactions with the updated SDK structure!
Now you can shut down the server by typing Ctrl+C in the terminal window where __main__.py is running.
# Langgraph