From 98b38aed06e9ec5c00e8e158706f2225a45dfed3 Mon Sep 17 00:00:00 2001 From: V Datta Adithya G Date: Thu, 15 May 2025 15:23:52 -0400 Subject: [PATCH 1/3] docs: A2A send/get task documentation --- docs/a2a.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/docs/a2a.md b/docs/a2a.md index 6b833bb98..bb40571c5 100644 --- a/docs/a2a.md +++ b/docs/a2a.md @@ -94,3 +94,133 @@ uvicorn agent_to_a2a:app --host 0.0.0.0 --port 8000 ``` Since the goal of `to_a2a` is to be a convenience method, it accepts the same arguments as the [`FastA2A`][fasta2a.FastA2A] constructor. + +### Interacting with the A2A Server using a Client + +For client-server interaction, we can create a client using the [`A2AClient`][fasta2a.client.A2AClient] class, which enables us to send and get tasks from the agent. In FastA2A, we expose two methods `send_task` and `get_task` to do so. +```python +from fasta2a.client import A2AClient + +client = A2AClient(base_url="http://localhost:8000") +``` + +To send a task for execution, we create a [`Message`][fasta2a.schema.Message] object and pass it to the client's `send_task` function. (example from [Google](https://google.github.io/A2A/tutorials/python/6-interact-with-server/#understanding-the-client-code)): +```python +from fasta2a.schema import Message + +async def send_message(): + send_message_payload = Message( + role="user", + parts=[ + {"type": "text", "text": "How much is 10 USD in INR?"} + ] + ) + + response = await client.send_task(message=send_message_payload) + print(response) + """ + { + 'jsonrpc': '2.0', + 'id': '09cd5ee1-81ca-4779-8679-47c002e5a09f', + 'result': { + 'id': 'b6e6cce0-bd98-43c7-8104-c5ce0836f2f6', + 'session_id': 'c0642116-b579-427e-a5e1-4bb2b41244f8', + 'status': { + 'state': 'submitted', + 'timestamp': '2025-05-14T12:33:50.618260' + }, + 'history': [ + {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} + ] + } + } + """ +``` + +Ensure that you call the main method using `asyncio.run` to execute the asynchronous code. + +We can use the `get_task` function to get the status and result from the task, however we need the result ID from the response in order to do so. Note that the task may still be in-progress on the agent's side while this is taking place. +```python {hl_lines="3 11-14"} +response = await client.send_task(message=send_message_payload) +response_task_id = str(response["result"]["id"]) +processed_task_response = await client.get_task(task_id=response_task_id) +""" +{ + 'jsonrpc': '2.0', + 'id': None, + 'result': { + 'id': '...', + 'session_id': '...', + 'status': { + 'state': 'working', + 'timestamp': '2025-05-14T19:36:45.963421' + }, + 'history': [ + {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} + ] + } +} +""" +``` + +In the case that you are debugging A2A using a client, you may want to add in a delay to retrieve the fulfilled response that you want from the agent. +```python {hl_lines="5"} +import time + +response = await client.send_task(message=send_message_payload) +response_task_id = str(response["result"]["id"]) +time.sleep(2) # Adding in a delay to ensure that we get a fulfilled response. +processed_task_response = await client.get_task(task_id=response_task_id) +""" +{ + 'jsonrpc': '2.0', + 'id': None, + 'result': { + 'id': '...', + 'session_id': '...', + 'status': { + 'state': 'completed', 'timestamp': '2025-05-14T19:13:07.759377' + }, + 'history': [ + {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} + ], + 'artifacts': [ + {'name': 'result', 'parts': [{'type': 'text', 'text': 'As of October 26, 2023, at 11:10 AM PST, 10 USD is approximately **833.18 INR**.\n\nKeep in mind that exchange rates fluctuate constantly, so this is just an estimate. For the most accurate conversion, you should check a real-time currency converter like Google Finance, XE.com, or a similar service just before you need the information.\n'}], 'index': 0} + ] + } +} +""" +``` + +Here's the full code: +```python {title="a2a_client.py"} +from fasta2a.client import A2AClient +from fasta2a.schema import Message +import time + +client = A2AClient(base_url="http://localhost:8000") + +async def send_message(): + send_message_payload = Message( + role="user", + parts=[ + {"type": "text", "text": "How much is 10 USD in INR?"} + ] + ) + + task_response = await client.send_task(message=send_message_payload) + task_response_result_id = str(task_response["result"]["id"]) + time.sleep(2) # <- Just for task fulfillment. + fulfilled_task_response = await client.get_task(task_id=task_response_result_id) + print(fulfilled_task_response["result"]["artifacts"]) + """ + [ + { + 'name': 'result', + 'parts': [{'type': 'text', 'text': 'As of October 26, 2023, at 11:10 AM PST, 10 USD is approximately **833.18 INR**.\n\nKeep in mind that exchange rates fluctuate constantly, so this is just an estimate. For the most accurate conversion, you should check a real-time currency converter like Google Finance, XE.com, or a similar service just before you need the information.\n'}], + 'index': 0 + } + ] + """ +``` +_(This example is complete, it can be run "as is" — you'll need to add `asyncio.run(main())` to run `main`)_ From 887ad6b911248ff3ed9e0ad06ff732107d20d5ef Mon Sep 17 00:00:00 2001 From: V Datta Adithya G Date: Thu, 15 May 2025 17:56:21 -0400 Subject: [PATCH 2/3] fix: linting errors --- docs/a2a.md | 118 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/docs/a2a.md b/docs/a2a.md index fc4e58e52..13b30fe3e 100644 --- a/docs/a2a.md +++ b/docs/a2a.md @@ -101,18 +101,21 @@ For client-server interaction, we can create a client using the [`A2AClient`][fa ```python from fasta2a.client import A2AClient -client = A2AClient(base_url="http://localhost:8000") +client = A2AClient(base_url='http://localhost:8000') ``` To send a task for execution, we create a [`Message`][fasta2a.schema.Message] object and pass it to the client's `send_task` function. (example from [Google](https://google.github.io/A2A/tutorials/python/6-interact-with-server/#understanding-the-client-code)): ```python +from fasta2a.client import A2AClient from fasta2a.schema import Message +client = A2AClient(base_url='http://localhost:8000') + async def send_message(): send_message_payload = Message( - role="user", + role='user', parts=[ - {"type": "text", "text": "How much is 10 USD in INR?"} + {'type': 'text', 'text': 'How much is 10 USD in INR?'} ] ) @@ -141,78 +144,93 @@ Ensure that you call the main method using `asyncio.run` to execute the asynchro We can use the `get_task` function to get the status and result from the task, however we need the result ID from the response in order to do so. Note that the task may still be in-progress on the agent's side while this is taking place. ```python {hl_lines="3 11-14"} -response = await client.send_task(message=send_message_payload) -response_task_id = str(response["result"]["id"]) -processed_task_response = await client.get_task(task_id=response_task_id) -""" -{ - 'jsonrpc': '2.0', - 'id': None, - 'result': { - 'id': '...', - 'session_id': '...', - 'status': { - 'state': 'working', - 'timestamp': '2025-05-14T19:36:45.963421' - }, - 'history': [ - {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} - ] +from fasta2a.client import A2AClient +from fasta2a.schema import Message + +client = A2AClient(base_url='http://localhost:8000') + +async def send_message(send_message_payload): + response = await client.send_task(message=send_message_payload) + response_task_id = str(response['result']['id']) + processed_task_response = await client.get_task(task_id=response_task_id) + print(processed_task_response) + """ + { + 'jsonrpc': '2.0', + 'id': None, + 'result': { + 'id': '...', + 'session_id': '...', + 'status': { + 'state': 'working', + 'timestamp': '2025-05-14T19:36:45.963421' + }, + 'history': [ + {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} + ] + } } -} -""" + """ ``` In the case that you are debugging A2A using a client, you may want to add in a delay to retrieve the fulfilled response that you want from the agent. ```python {hl_lines="5"} import time -response = await client.send_task(message=send_message_payload) -response_task_id = str(response["result"]["id"]) -time.sleep(2) # Adding in a delay to ensure that we get a fulfilled response. -processed_task_response = await client.get_task(task_id=response_task_id) -""" -{ - 'jsonrpc': '2.0', - 'id': None, - 'result': { - 'id': '...', - 'session_id': '...', - 'status': { - 'state': 'completed', 'timestamp': '2025-05-14T19:13:07.759377' - }, - 'history': [ - {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} - ], - 'artifacts': [ - {'name': 'result', 'parts': [{'type': 'text', 'text': 'As of October 26, 2023, at 11:10 AM PST, 10 USD is approximately **833.18 INR**.\n\nKeep in mind that exchange rates fluctuate constantly, so this is just an estimate. For the most accurate conversion, you should check a real-time currency converter like Google Finance, XE.com, or a similar service just before you need the information.\n'}], 'index': 0} - ] +from fasta2a.client import A2AClient +from fasta2a.schema import Message + +client = A2AClient(base_url='http://localhost:8000') + +async def send_message(send_message_payload): + response = await client.send_task(message=send_message_payload) + response_task_id = str(response['result']['id']) + time.sleep(2) # Adding in a delay to ensure that we get a fulfilled response. + processed_task_response = await client.get_task(task_id=response_task_id) + print(processed_task_response) + """ + { + 'jsonrpc': '2.0', + 'id': None, + 'result': { + 'id': '...', + 'session_id': '...', + 'status': { + 'state': 'completed', 'timestamp': '2025-05-14T19:13:07.759377' + }, + 'history': [ + {'role': 'user', 'parts': [{'type': 'text', 'text': 'how much is 10 USD in INR?'}]} + ], + 'artifacts': [ + {'name': 'result', 'parts': [{'type': 'text', 'text': 'As of October 26, 2023, at 11:10 AM PST, 10 USD is approximately **833.18 INR**.\n\nKeep in mind that exchange rates fluctuate constantly, so this is just an estimate. For the most accurate conversion, you should check a real-time currency converter like Google Finance, XE.com, or a similar service just before you need the information.\n'}], 'index': 0} + ] + } } -} -""" + """ ``` Here's the full code: ```python {title="a2a_client.py"} +import time + from fasta2a.client import A2AClient from fasta2a.schema import Message -import time -client = A2AClient(base_url="http://localhost:8000") +client = A2AClient(base_url='http://localhost:8000') async def send_message(): send_message_payload = Message( - role="user", + role='user', parts=[ - {"type": "text", "text": "How much is 10 USD in INR?"} + {'type': 'text', 'text': 'How much is 10 USD in INR?'} ] ) task_response = await client.send_task(message=send_message_payload) - task_response_result_id = str(task_response["result"]["id"]) + task_response_result_id = str(task_response['result']['id']) time.sleep(2) # <- Just for task fulfillment. fulfilled_task_response = await client.get_task(task_id=task_response_result_id) - print(fulfilled_task_response["result"]["artifacts"]) + print(fulfilled_task_response['result']['artifacts']) """ [ { From ee7b60cc1ce40cb87420c835b4fbb6cf96c40f76 Mon Sep 17 00:00:00 2001 From: V Datta Adithya G Date: Thu, 15 May 2025 18:34:03 -0400 Subject: [PATCH 3/3] fix: removed unused class `Message` --- docs/a2a.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/a2a.md b/docs/a2a.md index 13b30fe3e..a24e8ae21 100644 --- a/docs/a2a.md +++ b/docs/a2a.md @@ -143,9 +143,8 @@ async def send_message(): Ensure that you call the main method using `asyncio.run` to execute the asynchronous code. We can use the `get_task` function to get the status and result from the task, however we need the result ID from the response in order to do so. Note that the task may still be in-progress on the agent's side while this is taking place. -```python {hl_lines="3 11-14"} +```python {hl_lines="3 17-20"} from fasta2a.client import A2AClient -from fasta2a.schema import Message client = A2AClient(base_url='http://localhost:8000') @@ -174,11 +173,10 @@ async def send_message(send_message_payload): ``` In the case that you are debugging A2A using a client, you may want to add in a delay to retrieve the fulfilled response that you want from the agent. -```python {hl_lines="5"} +```python {hl_lines="10"} import time from fasta2a.client import A2AClient -from fasta2a.schema import Message client = A2AClient(base_url='http://localhost:8000')