A2A has become like a standard for enabling agent to agent communication, we could use the a2a-sdk for running and configuring the a2a server and its features such as agent card, agent skills, agent executor, request handler etc. However we are going to go with a simplified approach here with strands where the agent card will be fetched automatically. Let's get started!
Server
Initialize a uv project for the a2a server and switch to that directory.
uv init ~/strands-a2a-server
cd ~/strands-a2a-server
Add the required packages.
uv add python-dotenv==1.2.2 strands-agents[a2a]==1.42.0
Change the code in main.py to look like below.
$ cat main.py
from dotenv import load_dotenv
from strands import Agent
from strands.multiagent.a2a import A2AServer
load_dotenv()
def main():
agent = Agent(
callback_handler=None,
description="A sample strands agent",
model="us.amazon.nova-micro-v1:0",
)
a2a_server = A2AServer(agent=agent)
a2a_server.serve()
if __name__ == "__main__":
main()
I like the simplicity here, as you see above, it's quite simple to start a basic a2a server from with in strands, with just a couple of lines of code, we didn't have to install the a2a-sdk separately.
Run the code, to start the a2a server.
$ uv run main.py
INFO: Started server process [18006]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:9000 (Press CTRL+C to quit)
Client
Let's now do the client part on a separate terminal. Initialize the project and switch the directory.
uv init ~/strands-a2a-client
cd ~/strands-a2a-client
Modify main.py code to look as follows.
import asyncio
from strands.agent.a2a_agent import A2AAgent
async def main():
agent = A2AAgent(endpoint="http://localhost:9000")
agent_card = await agent.get_agent_card()
print("Invoking remote agent with agent card:")
for key, value in agent_card:
print(key, ":", value)
print('-' * 20)
while True:
prompt = input("User: ")
if prompt.lower() == "exit":
break
async for event in agent.stream_async(prompt):
if "result" in event:
print("AI: ", event["result"], end="", flush=True)
if __name__ == "__main__":
asyncio.run(main())
We just call the remote endpoint, which is our a2a server, and iterate through the stream. We are also retrieving and printing the agent card of the remote agent.
Run the code.
$ uv run main.py
Invoking remote agent with agent card:
additional_interfaces : None
capabilities : extensions=None push_notifications=None state_transition_history=None streaming=True
default_input_modes : ['text']
default_output_modes : ['text']
description : A sample strands agent
documentation_url : None
icon_url : None
name : my strands agent
preferred_transport : JSONRPC
protocol_version : 0.3.0
provider : None
security : None
security_schemes : None
signatures : None
skills : []
supports_authenticated_extended_card : None
url : http://127.0.0.1:9000/
version : 0.0.1
--------------------
User: hi, tell me abt yourself in a single line
AI: I'm an artificial intelligence system designed to assist and provide information on a wide range of topics.
User: exit
Tools
As you see in the output above, for now the remote agent card didn't show any skills, we can add a tool on the server and the a2a wrapper in strands should automatically convert that to skills. So, we don't have to define the skills manually and can save some effort here. Let's try that. For simplicity I am going to use a built in tool from strands itself, let's add that package. Before this, You can stop the server first with ctrl c if it's running...
uv add strands-agents-tools==0.8.0
We shall do a couple of changes in main.py of the a2a server. We have to import the tool at the top.
from strands_tools import http_request
And we just need to use this in the agent.
tools=[http_request],
So our updated code will look like:
$ cat main.py
from dotenv import load_dotenv
from strands import Agent
from strands.multiagent.a2a import A2AServer
from strands_tools import http_request
load_dotenv()
def main():
agent = Agent(
callback_handler=None,
description="A sample strands agent",
model="us.amazon.nova-micro-v1:0",
name="my strands agent",
tools=[http_request],
)
a2a_server = A2AServer(agent