DEV Community

Cover image for Build Anything With A2A Agent — Here’s How
Gao Dalie (Ilyass)
Gao Dalie (Ilyass)

Posted on

Build Anything With A2A Agent — Here’s How

Recently, I moved from Taiwan to North Carolina. During a transfer flight, I had some time to scroll through YouTube, and I saw that Google had open-sourced the first standard agent interaction protocol, the Agent2Agent Protocol (A2A for short), at the Google Cloud Next ’25 conference.

When this thing came out, it felt like the entire AI Agent community was shaken and had to learn

Why? Because it may really change the way intelligent entities interact overnight and completely break down the system

I built many cool AI agents to automate and augment many business processes, from booking a flight to supporting customer service representatives with supply chain planning.

However, the fundamental problem is that there are so many technologies and tools (frameworks, platforms) for creating AI agents that agents created using each of them cannot easily communicate (work together) with each other.

Just as it is difficult for humans to communicate using different languages, AI agents cannot cooperate if they use different rules for “speaking.

That’s where A2A comes in. It is “common language” and “communication rules” that AI agents use to communicate with each other.

No matter what technology (LangChain, CrewAI, etc.) is used, if you follow these rules, you will be able to understand what the other person is saying and convey your intentions. It is not a specific framework, but an open standard that defines the “way” of communication.

So, let me give you a quick demo of a live chatbot to show you what I mean.

Check Youtube

I just sorted out a multi-agent system for trip planning where agents communicate via a standard protocol. I created three specialised agents — a weather agent with its agent card providing city forecasts, a hotel agent with its own agent card offering accommodation options, and an activity agent with its agent card suggesting things to do.

The orchestrator connects these three running servers to build comprehensive travel plans. I initially faced several API issues — I tried using it send_message_async When the library only had send_messageThen I discovered it wasn't awaitable despite being in an async function.

We needed several dependencies (httpx, pydantic, fastapi), which I addressed systematically. The biggest challenge was handling error responses properly when services were unavailable or returned unexpected formats.

I implemented robust error handling with try/except blocks and type checking, allowing the orchestrator to continue working even when some services failed. These agents are now running on different ports (weather on 5001, hotel on 5002, activity on 5003), the system coordinates between all three specialized services to build comprehensive travel plans that adapt to real-time conditions.

So, by the end of this story, you will understand what A2A is, how it works, what the difference is between A2A and MCP, and even how we’re going to use A2A to create a powerful agentic chatbot

What is A2A?

Agent-to-Agent (A2A) communication is a mechanism by which AI agents cooperate by “talking” directly. Each agent sends messages to each other, exchanges knowledge and instructions, and divides and coordinates tasks, allowing multiple AI agents to work as a team to achieve advanced goals without human intervention.

Think about it: if a sales AI is dealing with a customer and needs a price quote, it can ask the finance AI directly, without human intervention, and if it needs to check inventory, it can contact the warehouse management AI — a world where this collaboration is done automatically.

How does A2A work?

Now that we understand the design concept of A2A, let’s take a look at how it enables Agents to “chat” and “work”

A2A can be compared to a movie production team, where each agent is like a crew member, such as a director, editor, or sound designer, each with a specific role and skill set.

Their Agent Card works like a resume, showing their abilities, the tools they use (like Adobe Premiere ), and how to contact them. When the director needs the editor to cut a scene, he sends a Task request, and both track its progress, just like how Studios track each stage of editing in a blockbuster film.

If the editor needs more time, they send updates, similar to how editors on real movie sets send daily progress reports during post-production via Push Notification. And just as only verified crew can access the film set using ID badges to prevent unauthorised people from entering, A2A uses secure Identity & Security protocols (like tokens and signatures) to make sure only trusted agents communicate and collaborate.

MCP Vs A2A

A2A and MCP are not competitors, but rather complementary: in a real application, it is recommended to model A2A agents as MCP resources (represented by AgentCards), so that the framework can communicate with users, remote agents and other agents using A2A, and can access tools and resources using MCP.

This combination results in:

Agents can access various tools and external resources through the MCP.
Agents naturally collaborate through A2A
End users benefit from multiple agents working together in a single interface
In general, it may be easier to remember that MCP is the “standard for connecting agents and tools” and A2A is the “standard for conversation between agents.”

Let’s start coding
Before we dive into our application, we will create an ideal environment for the code to work. For this, we need to install the requirements.txt


pip install python-a2a[all]
pip install fastapi
pip install pydantic
pip install httpx
Enter fullscreen mode Exit fullscreen mode

The next step is the usual one: We will import the relevant libraries, the significance of which will become evident as we proceed.

python_a2a: Python A2A is an implementation of Google’s Agent-to-Agent (A2A) protocol, designed to standardise communication between AI agents.

from python_a2a import A2AServer, Message, TextContent, MessageRole, run_server , A2AClient
import json
Enter fullscreen mode Exit fullscreen mode

Weather Agent Server
I made a simple weather info server using the Python_a2a framework. I created a WeatherAgent class by extending A2AServer, and inside it, I designed the handle_message Method to respond with weather data when a user sends a city name as text.

I developed a small lookup for Tokyo and New York, returning a default message if the city isn’t listed. I also created an agent card A JSON file that describes the agent’s name, version, and skill is then saved in a .well-known folder.

Finally, I set up the folder, generated the agent card, initialised the agent, and ran the server on port 5001 so it can respond to weather requests.

# simple_a2a_server.py
from python_a2a import A2AServer, Message, TextContent, MessageRole, run_server
import json

class WeatherAgent(A2AServer):
    def handle_message(self, message):
        if message.content.type == "text":
            city = message.content.text.strip()

            weather_info = {"tokyo": "sunny, 25°C", "new york": "cloudy, 18°C"}.get(
                city.lower(), "weather data not available"
            )
            return Message(
                content=TextContent(text=f"Weather in {city}: {weather_info}"),
                role=MessageRole.AGENT,
                parent_message_id=message.message_id,
                conversation_id=message.conversation_id
            )

# 定義したAgent Cardを作成
def create_agent_card():
    card = {
        "name": "Simple Weather Agent",
        "description": "Provides weather information for cities",
        "version": "1.0.0",
        "skills": [{"name": "getWeather", "description": "Get weather for a city"}]
    }
    with open(".well-known/agent.json", "w") as f:
        json.dump(card, f)

if __name__ == "__main__":
    import os
    os.makedirs(".well-known", exist_ok=True)
    create_agent_card()
    agent = WeatherAgent()
    run_server(agent, host="0.0.0.0", port=5001)
Enter fullscreen mode Exit fullscreen mode

Hotel Agent Server
I developed a hotel recommendation server using the Python_a2a framework. I created the HotelAgent class that listens for text messages and responds with hotel options based on the city mentioned in the user's message.

I designed a simple in-code hotel database with listings for Tokyo and New York, and developed logic to extract the city name from the query to fetch matching hotels. I also created an agent card that describes the agent’s name, version, and skill in finding hotels, then saved it in the .well-known directory.

Finally, I set up the folder, generated the card, initialised the agent, and ran the server on port 5002 so it could start handling hotel inquiries.

# hotel_agent.py
from python_a2a import A2AServer, Message, TextContent, MessageRole, run_server
import json

class HotelAgent(A2AServer):
    def handle_message(self, message):
        if message.content.type == "text":
            query = message.content.text.strip()
            # Simple hotel database
            hotels = {
                "tokyo": [
                    "Grand Tokyo Hotel - Near city center, indoor pool, 5-star",
                    "Budget Inn Tokyo - Economic option with free breakfast"
                ],
                "new york": [
                    "Manhattan Suites - Central location, luxury accommodations",
                    "Brooklyn Boutique Hotel - Hip neighborhood, rooftop bar"
                ]
            }

            # Extract city name from query
            city_key = ""
            for city in hotels.keys():
                if city in query.lower():
                    city_key = city
                    break

            if city_key:
                hotel_list = hotels[city_key]
                response_text = f"Recommended hotels in {city_key.title()}: {', '.join(hotel_list)}"
            else:
                response_text = "No hotel information available for this location."

            return Message(
                content=TextContent(text=response_text),
                role=MessageRole.AGENT,
                parent_message_id=message.message_id,
                conversation_id=message.conversation_id
            )

# Agent Card creation
def create_agent_card():
    card = {
        "name": "Hotel Recommendation Agent",
        "description": "Recommends hotels based on location and preferences",
        "version": "1.0.0",
        "skills": [{"name": "findHotels", "description": "Find hotels in a specified location"}]
    }
    with open(".well-known/agent.json", "w") as f:
        json.dump(card, f)

if __name__ == "__main__":
    import os
    os.makedirs(".well-known", exist_ok=True)
    create_agent_card()
    agent = HotelAgent()
    run_server(agent, host="0.0.0.0", port=5002)
Enter fullscreen mode Exit fullscreen mode

Activity Agent Server
Then I made an activity suggestion server using the Python_a2a framework to help users find things to do based on city and weather. I created the ActivityAgent class and designed it to handle text queries by extracting both the city and weather conditions from the message.

I developed a simple activity database for Tokyo and New York, with different options for sunny, rainy, or default weather. The agent looks up the matching city and weather type, then returns a list of recommended activities. I also created an agent card that describes the service and its skill to suggest activities, then saved it in a .well-known folder.

Finally, I initialised the agent, created the card, and ran the server on port 5003 so it could start helping users plan fun things to do.

# activity_agent.py
from python_a2a import A2AServer, Message, TextContent, MessageRole, run_server
import json

class ActivityAgent(A2AServer):
    def handle_message(self, message):
        if message.content.type == "text":
            query = message.content.text.strip()
            # Simple activity database
            activities = {
                "tokyo": {
                    "sunny": ["Visit Tokyo Skytree", "Explore Meiji Shrine", "Shop in Ginza"],
                    "rainy": ["Tokyo National Museum", "TeamLab Borderless digital art", "Shopping at underground malls"],
                    "default": ["Tokyo Disneyland", "Try local cuisine in Shinjuku"]
                },
                "new york": {
                    "sunny": ["Central Park walk", "Top of the Rock observation deck", "High Line park"],
                    "rainy": ["Metropolitan Museum of Art", "American Museum of Natural History", "Broadway show"],
                    "default": ["Times Square", "Empire State Building", "Statue of Liberty"]
                }
            }

            # Extract city and weather from query
            city_key = ""
            weather_type = "default"

            for city in activities.keys():
                if city in query.lower():
                    city_key = city
                    break

            if "sunny" in query.lower():
                weather_type = "sunny"
            elif "rainy" in query.lower() or "cloudy" in query.lower():
                weather_type = "rainy"

            if city_key and city_key in activities:
                city_activities = activities[city_key]
                activity_list = city_activities.get(weather_type, city_activities["default"])
                response_text = f"Recommended activities in {city_key.title()}: {', '.join(activity_list)}"
            else:
                response_text = "No activity recommendations available for this location."

            return Message(
                content=TextContent(text=response_text),
                role=MessageRole.AGENT,
                parent_message_id=message.message_id,
                conversation_id=message.conversation_id
            )

# Agent Card creation
def create_agent_card():
    card = {
        "name": "Activity Recommendation Agent",
        "description": "Suggests activities based on location and weather",
        "version": "1.0.0",
        "skills": [{"name": "suggestActivities", "description": "Suggest activities for a location based on weather and preferences"}]
    }
    with open(".well-known/agent.json", "w") as f:
        json.dump(card, f)

if __name__ == "__main__":
    import os
    os.makedirs(".well-known", exist_ok=True)
    create_agent_card()
    agent = ActivityAgent()
    run_server(agent, host="0.0.0.0", port=5003)
Enter fullscreen mode Exit fullscreen mode

Main.py
I developed a trip planning orchestrator function using asynchronous Python to connect three local AI-powered micro-agents: weather, hotel, and activity services. First, I created a A2AClient for each agent, pointing to their respective local endpoints.

Then, I made a weather request by sending the city name as a parameter Message With the role USERIf successful, I extracted the weather data. Based on that weather info, I crafted another message to the hotel agent asking it to find accommodation in the city while considering the weather conditions.

I made sure to check the response content type carefully to avoid runtime issues. Once I had the hotel info, I composed a final message for the activity agent, asking it to suggest things to do in the city, incorporating both the weather and hotel data into the request.

Throughout the whole process, I wrapped each request in try-except blocks to handle any potential errors gracefully. Finally, I assembled all the collected details—weather, hotel, and activities—into a single formatted travel plan and printed it.

import asyncio
from python_a2a import A2AClient, Message, TextContent, MessageRole

async def orchestrate_trip_planning(city):

    weather_client = A2AClient("http://localhost:5001/a2a")
    hotel_client = A2AClient("http://localhost:5002/a2a")
    activity_client = A2AClient("http://localhost:5003/a2a")

    # 1. Get weather information
    weather_msg = Message(content=TextContent(text=city), role=MessageRole.USER)
    try:
        weather_resp = weather_client.send_message(weather_msg)
        # Check response type by its type attribute or class name
        if hasattr(weather_resp.content, 'text'):
            weather_info = weather_resp.content.text
        else:
            weather_info = f"Error getting weather information"
    except Exception as e:
        weather_info = f"Error connecting to weather service: {str(e)}"

    # 2. Get hotel information
    hotel_msg = Message(
        content=TextContent(text=f"Find hotels in {city} considering: {weather_info}"),
        role=MessageRole.USER
    )
    try:
        hotel_resp = hotel_client.send_message(hotel_msg)
        # Check response type more carefully
        content_type = type(hotel_resp.content).__name__
        if content_type == 'TextContent' and hasattr(hotel_resp.content, 'text'):
            hotel_info = hotel_resp.content.text
        else:
            hotel_info = f"Error getting hotel information"
    except Exception as e:
        hotel_info = f"Error connecting to hotel service: {str(e)}"

    # 3. Suggest activities
    activity_msg = Message(
        content=TextContent(
            text=f"Suggest activities in {city}. Weather: {weather_info}. Staying at: {hotel_info}"
        ),
        role=MessageRole.USER
    )
    try:
        activity_resp = activity_client.send_message(activity_msg)
        content_type = type(activity_resp.content).__name__
        if content_type == 'TextContent' and hasattr(activity_resp.content, 'text'):
            activity_info = activity_resp.content.text
        else:
            activity_info = f"Error getting activity information"
    except Exception as e:
        activity_info = f"Error connecting to activity service: {str(e)}"

    # Create the final travel plan
    return f"""
    Travel Plan for {city}
    ---------------------
    Weather: {weather_info}
    Accommodation: {hotel_info}
    Activities: {activity_info}
    """

if __name__ == "__main__":
    city = "Tokyo"
    result = asyncio.run(orchestrate_trip_planning(city))
    print(result)
Enter fullscreen mode Exit fullscreen mode

Conclusion :

Although the A2A protocol is still in its early stages, it can potentially become a standard for interoperability between AI agents. Future developments will further enhance agent-to-agent communication, enabling the creation of more complex and advanced agent ecosystems.

Companies and developers can follow the A2A Protocol and contribute to developing this open standard to help shape the next generation of the AI agent ecosystem.

If this article might be helpful to your friends, please forward it to them.

🧙‍♂️ I am an AI Generative expert! If you want to collaborate on a project, drop an inquiry here or book a 1-on-1 Consulting Call With Me.

I would highly appreciate it if you

❣ Join my Patreon: https://www.patreon.com/GaoDalie_AI

Book an Appointment with me: https://topmate.io/gaodalie_ai

Support the Content (every Dollar goes back into the video):https://buymeacoffee.com/gaodalie98d

Subscribe to the Newsletter for free:https://substack.com/@gaodalie

Top comments (0)