{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Copyright 2025 Google LLC\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Getting Started with Google A2A (Agent-to-Agent) Communication\n", "\n", "This notebook introduces you to Google's Agent-to-Agent (A2A) protocol, a standardized way for AI agents to communicate and collaborate. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What You'll Build\n", "\n", "A three-agent system that works together to analyze trending topics:\n", "1. **Trending Topics Agent** - Searches the web for current trending topics\n", "2. **Trend Analyzer Agent** - Performs deep analysis with quantitative data\n", "3. **Host Agent** - Orchestrates the other agents to provide comprehensive insights" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"drawing\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prerequisites\n", "\n", "- Python 3.11+\n", "- Google Cloud Project with Vertex AI enabled\n", "- Basic understanding of async Python\n", "\n", "## Other Resources\n", "\n", "- [Google ADK Documentation](https://google.github.io/adk-docs/)\n", "- [A2A Protocol Specification](https://github.com/google/a2a)\n", "- [Vertex AI Documentation](https://cloud.google.com/vertex-ai)\n", "- Codelabs:\n", " - [Google's Agent Stack in Action: ADK, A2A, MCP on Google Cloud](https://codelabs.developers.google.com/instavibe-adk-multi-agents/instructions)\n", " - [Getting Started with Agent-to-Agent (A2A) Protocol: Gemini on Cloud Run](https://codelabs.developers.google.com/intro-a2a-purchasing-concierge)\n", " - [Getting Started with MCP, ADK and A2A](https://codelabs.developers.google.com/codelabs/currency-agent)\n", "\n", "#### Important!\n", "A2A is a work in progress (WIP) thus, in the near future there might be changes that are different from what demonstrated in this code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup and Installation\n", "\n", "First, let's install the required dependencies:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Install required packages\n", "%pip install --upgrade -q google-genai google-adk==1.9.0 a2a-sdk==0.3.0 python-dotenv aiohttp uvicorn requests mermaid-python nest-asyncio" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Introduction to A2A\n", "\n", "### What is Agent-to-Agent (A2A) Communication?\n", "\n", "A2A is a standardized protocol that enables AI agents to:\n", "- **Discover** each other's capabilities\n", "- **Communicate** using a common JSON-RPC based protocol\n", "- **Collaborate** to solve complex tasks\n", "- **Stream** responses for real-time interactions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Environment Configuration" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Targeted workaround for google-adk==1.9.0 compatibility with a2a-sdk==0.3.0\n", "# This cell shall be removed when google-adk releases the version next to >1.9.0\n", "# (after https://github.com/google/adk-python/pull/2297)\n", "\n", "\n", "import sys\n", "\n", "from a2a.client import client as real_client_module\n", "from a2a.client.card_resolver import A2ACardResolver\n", "\n", "\n", "class PatchedClientModule:\n", " def __init__(self, real_module) -> None:\n", " for attr in dir(real_module):\n", " if not attr.startswith('_'):\n", " setattr(self, attr, getattr(real_module, attr))\n", " self.A2ACardResolver = A2ACardResolver\n", "\n", "\n", "patched_module = PatchedClientModule(real_client_module)\n", "sys.modules['a2a.client.client'] = patched_module # type: ignore" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "import os\n", "import sys\n", "import threading\n", "import time\n", "\n", "from typing import Any\n", "\n", "import httpx\n", "import logging\n", "import nest_asyncio\n", "import uvicorn\n", "\n", "from a2a.client import ClientConfig, ClientFactory, create_text_message_object\n", "from a2a.server.apps import A2AStarletteApplication\n", "from a2a.server.request_handlers import DefaultRequestHandler\n", "from a2a.server.tasks import InMemoryTaskStore\n", "from a2a.types import (\n", " AgentCapabilities,\n", " AgentCard,\n", " AgentSkill,\n", " TransportProtocol,\n", ")\n", "from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH\n", "from dotenv import load_dotenv\n", "from google.adk.a2a.executor.a2a_agent_executor import (\n", " A2aAgentExecutor,\n", " A2aAgentExecutorConfig,\n", ")\n", "from google.adk.agents import Agent, SequentialAgent\n", "from google.adk.agents.remote_a2a_agent import RemoteA2aAgent\n", "from google.adk.artifacts import InMemoryArtifactService\n", "from google.adk.memory.in_memory_memory_service import InMemoryMemoryService\n", "from google.adk.runners import Runner\n", "from google.adk.sessions import InMemorySessionService\n", "from google.adk.tools import google_search" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Set Google Cloud Configuration\n", "os.environ['GOOGLE_GENAI_USE_VERTEXAI'] = 'TRUE'\n", "os.environ['GOOGLE_CLOUD_PROJECT'] = (\n", " 'dataproc-workspaces-notebooks' # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n", ")\n", "os.environ['GOOGLE_CLOUD_LOCATION'] = (\n", " 'us-central1' # Replace with your location\n", ")\n", "\n", "load_dotenv()\n", "\n", "print('Environment variables configured:')\n", "print(f'GOOGLE_GENAI_USE_VERTEXAI: {os.environ[\"GOOGLE_GENAI_USE_VERTEXAI\"]}')\n", "print(f'GOOGLE_CLOUD_PROJECT: {os.environ[\"GOOGLE_CLOUD_PROJECT\"]}')\n", "print(f'GOOGLE_CLOUD_LOCATION: {os.environ[\"GOOGLE_CLOUD_LOCATION\"]}')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Authenticate your notebook environment (Colab only)\n", "if 'google.colab' in sys.modules:\n", " from google.colab import auth\n", "\n", " auth.authenticate_user(project_id=os.environ['GOOGLE_CLOUD_PROJECT'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Setup logging\n", "logging.basicConfig(\n", " level=logging.ERROR,\n", " format='%(asctime)s - %(levelname)s - %(name)s - %(message)s'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Building Your A2A System\n", "\n", "Let's build our three-agent system step by step. We'll create:\n", "\n", "1. **Trending Topics Agent** - Finds current trending topics\n", "2. **Trend Analyzer Agent** - Analyzes trends with quantitative data\n", "3. **Host Agent** - Orchestrates the other agents (sequentially)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Agent 1: Trending Topics Agent\n", "\n", "This agent searches the web for trending topics and returns a list of current trends." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create the Trending Topics ADK Agent\n", "trending_agent = Agent(\n", " model='gemini-2.5-pro',\n", " name='trending_topics_agent',\n", " instruction=\"\"\"\n", " You are a social media trends analyst. Your job is to search the web for current trending topics,\n", " particularly from social platforms.\n", "\n", " When asked about trends:\n", " 1. Search for \"trending topics today\" or similar queries\n", " 2. Extract the top 3 trending topics\n", " 3. Return them in a JSON format\n", "\n", " Focus on current, real-time trends from the last 24 hours.\n", "\n", " You MUST return your response in the following JSON format:\n", " {\n", " \"trends\": [\n", " {\n", " \"topic\": \"Topic name\",\n", " \"description\": \"Brief description (1-2 sentences)\",\n", " \"reason\": \"Why it's trending\"\n", " },\n", " {\n", " \"topic\": \"Topic name\",\n", " \"description\": \"Brief description (1-2 sentences)\",\n", " \"reason\": \"Why it's trending\"\n", " },\n", " {\n", " \"topic\": \"Topic name\",\n", " \"description\": \"Brief description (1-2 sentences)\",\n", " \"reason\": \"Why it's trending\"\n", " }\n", " ]\n", " }\n", "\n", " Only return the JSON object, no additional text.\n", " \"\"\",\n", " tools=[google_search],\n", ")\n", "\n", "print('Trending Topics Agent created successfully!')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "trending_agent_card = AgentCard(\n", " name='Trending Topics Agent',\n", " url='http://localhost:10020',\n", " description='Searches the web for current trending topics from social media',\n", " version='1.0',\n", " capabilities=AgentCapabilities(streaming=True),\n", " default_input_modes=['text/plain'],\n", " default_output_modes=['text/plain'],\n", " preferred_transport=TransportProtocol.jsonrpc,\n", " skills=[\n", " AgentSkill(\n", " id='find_trends',\n", " name='Find Trending Topics',\n", " description='Searches for current trending topics on social media',\n", " tags=['trends', 'social media', 'twitter', 'current events'],\n", " examples=[\n", " \"What's trending today?\",\n", " 'Show me current Twitter trends',\n", " 'What are people talking about on social media?',\n", " ],\n", " )\n", " ],\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "remote_trending_agent = RemoteA2aAgent(\n", " name='find_trends',\n", " description='Searches for current trending topics on social media',\n", " agent_card=f'http://localhost:10020{AGENT_CARD_WELL_KNOWN_PATH}',\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Agent 2: Trend Analyzer Agent\n", "\n", "This agent takes a specific trend and performs deep analysis with quantitative data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create the Trend Analyzer ADK Agent\n", "analyzer_agent = Agent(\n", " model='gemini-2.5-pro',\n", " name='trend_analyzer_agent',\n", " instruction=\"\"\"\n", " You are a data analyst specializing in trend analysis. When given a trending topic,\n", " perform deep research to find quantitative data and insights.\n", "\n", " For each trend you analyze:\n", " 1. Search for statistics, numbers, and metrics related to the trend\n", " 2. Look for:\n", " - Engagement metrics (views, shares, mentions)\n", " - Growth rates and timeline\n", " - Geographic distribution\n", " - Related hashtags or keywords\n", " 3. Provide concrete numbers and data points\n", "\n", " Keep it somehow concise\n", "\n", " Always prioritize quantitative information over qualitative descriptions.\n", " \"\"\",\n", " tools=[google_search],\n", ")\n", "\n", "print('Trend Analyzer Agent created successfully!')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "analyzer_agent_card = AgentCard(\n", " name='Trend Analyzer Agent',\n", " url='http://localhost:10021',\n", " description='Performs deep analysis of trends with quantitative data',\n", " version='1.0',\n", " capabilities=AgentCapabilities(streaming=True),\n", " default_input_modes=['text/plain'],\n", " default_output_modes=['text/plain'],\n", " preferred_transport=TransportProtocol.jsonrpc,\n", " skills=[\n", " AgentSkill(\n", " id='analyze_trend',\n", " name='Analyze Trend',\n", " description='Provides quantitative analysis of a specific trend',\n", " tags=['analysis', 'data', 'metrics', 'statistics'],\n", " examples=[\n", " 'Analyze the #ClimateChange trend',\n", " 'Get metrics for the Taylor Swift trend',\n", " 'Provide data analysis for AI adoption trend',\n", " ],\n", " )\n", " ],\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "remote_analyzer_agent = RemoteA2aAgent(\n", " name='analyze_trend',\n", " description='Provides quantitative analysis of a specific trend',\n", " agent_card=f'http://localhost:10021{AGENT_CARD_WELL_KNOWN_PATH}',\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Agent 3: Host Agent (Orchestrator)\n", "\n", "The Host Agent coordinates between the other two agents to provide comprehensive trend analysis." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create the Host ADK Agent\n", "host_agent = SequentialAgent(\n", " name='trend_analysis_host',\n", " sub_agents=[remote_trending_agent, remote_analyzer_agent],\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "host_agent_card = AgentCard(\n", " name='Trend Analysis Host',\n", " url='http://localhost:10022',\n", " description='Orchestrates, sequentially, trend discovery and analysis using specialized agents',\n", " version='1.0',\n", " capabilities=AgentCapabilities(streaming=True),\n", " default_input_modes=['text/plain'],\n", " default_output_modes=['application/json'],\n", " preferred_transport=TransportProtocol.jsonrpc,\n", " skills=[\n", " AgentSkill(\n", " id='comprehensive_trend_analysis',\n", " name='Comprehensive Trend Analysis',\n", " description='Finds trending topics and provides deep analysis of the most relevant one',\n", " tags=['trends', 'analysis', 'orchestration', 'insights'],\n", " examples=[\n", " 'Analyze current trends',\n", " \"What's trending and why is it important?\",\n", " 'Give me a comprehensive trend report',\n", " ],\n", " )\n", " ],\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Running\n", "\n", "Now let's put everything together. We'll create helper functions to start our agents and run the complete system." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Starting the A2A Servers\n", "\n", "Create function to run each remote agent as an A2A server:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def create_agent_a2a_server(agent, agent_card):\n", " \"\"\"Create an A2A server for any ADK agent.\n", "\n", " Args:\n", " agent: The ADK agent instance\n", " agent_card: The ADK agent card\n", "\n", " Returns:\n", " A2AStarletteApplication instance\n", " \"\"\"\n", " runner = Runner(\n", " app_name=agent.name,\n", " agent=agent,\n", " artifact_service=InMemoryArtifactService(),\n", " session_service=InMemorySessionService(),\n", " memory_service=InMemoryMemoryService(),\n", " )\n", "\n", " config = A2aAgentExecutorConfig()\n", " executor = A2aAgentExecutor(runner=runner, config=config)\n", "\n", " request_handler = DefaultRequestHandler(\n", " agent_executor=executor,\n", " task_store=InMemoryTaskStore(),\n", " )\n", "\n", " # Create A2A application\n", " return A2AStarletteApplication(\n", " agent_card=agent_card, http_handler=request_handler\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Apply nest_asyncio\n", "nest_asyncio.apply()\n", "\n", "# Store server tasks\n", "server_tasks: list[asyncio.Task] = []\n", "\n", "\n", "async def run_agent_server(agent, agent_card, port) -> None:\n", " \"\"\"Run a single agent server.\"\"\"\n", " app = create_agent_a2a_server(agent, agent_card)\n", "\n", " config = uvicorn.Config(\n", " app.build(),\n", " host='127.0.0.1',\n", " port=port,\n", " log_level='warning',\n", " loop='none', # Important: let uvicorn use the current loop\n", " )\n", "\n", " server = uvicorn.Server(config)\n", " await server.serve()\n", "\n", "\n", "async def start_all_servers() -> None:\n", " \"\"\"Start all servers in the same event loop.\"\"\"\n", " # Create tasks for all servers\n", " tasks = [\n", " asyncio.create_task(\n", " run_agent_server(trending_agent, trending_agent_card, 10020)\n", " ),\n", " asyncio.create_task(\n", " run_agent_server(analyzer_agent, analyzer_agent_card, 10021)\n", " ),\n", " asyncio.create_task(\n", " run_agent_server(host_agent, host_agent_card, 10022)\n", " ),\n", " ]\n", "\n", " # Give servers time to start\n", " await asyncio.sleep(2)\n", "\n", " print('\u2705 All agent servers started!')\n", " print(' - Trending Agent: http://127.0.0.1:10020')\n", " print(' - Analyzer Agent: http://127.0.0.1:10021')\n", " print(' - Host Agent: http://127.0.0.1:10022')\n", "\n", " # Keep servers running\n", " try:\n", " await asyncio.gather(*tasks)\n", " except KeyboardInterrupt:\n", " print('Shutting down servers...')\n", "\n", "\n", "# Run in a background thread\n", "\n", "\n", "def run_servers_in_background() -> None:\n", " loop = asyncio.new_event_loop()\n", " asyncio.set_event_loop(loop)\n", " loop.run_until_complete(start_all_servers())\n", "\n", "\n", "# Start the thread\n", "server_thread = threading.Thread(target=run_servers_in_background, daemon=True)\n", "server_thread.start()\n", "\n", "# Wait for servers to be ready\n", "time.sleep(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Testing the System" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Call the A2A agents (the 2 remote agents, and the host agent that refers to the 2 remote agents as sub agents)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class A2ASimpleClient:\n", " \"\"\"A2A Simple to call A2A servers.\"\"\"\n", "\n", " def __init__(self, default_timeout: float = 240.0):\n", " self._agent_info_cache: dict[\n", " str, dict[str, Any] | None\n", " ] = {} # Cache for agent metadata\n", " self.default_timeout = default_timeout\n", "\n", " async def create_task(self, agent_url: str, message: str) -> str:\n", " \"\"\"Send a message following the official A2A SDK pattern.\"\"\"\n", " # Configure httpx client with timeout\n", " timeout_config = httpx.Timeout(\n", " timeout=self.default_timeout,\n", " connect=10.0,\n", " read=self.default_timeout,\n", " write=10.0,\n", " pool=5.0,\n", " )\n", "\n", " async with httpx.AsyncClient(timeout=timeout_config) as httpx_client:\n", " # Check if we have cached agent card data\n", " if (\n", " agent_url in self._agent_info_cache\n", " and self._agent_info_cache[agent_url] is not None\n", " ):\n", " agent_card_data = self._agent_info_cache[agent_url]\n", " else:\n", " # Fetch the agent card\n", " agent_card_response = await httpx_client.get(\n", " f'{agent_url}{AGENT_CARD_WELL_KNOWN_PATH}'\n", " )\n", " agent_card_data = self._agent_info_cache[agent_url] = (\n", " agent_card_response.json()\n", " )\n", "\n", " # Create AgentCard from data\n", " agent_card = AgentCard(**agent_card_data)\n", "\n", " # Create A2A client with the agent card\n", " config = ClientConfig(\n", " httpx_client=httpx_client,\n", " supported_transports=[\n", " TransportProtocol.jsonrpc,\n", " TransportProtocol.http_json,\n", " ],\n", " use_client_preference=True,\n", " )\n", "\n", " factory = ClientFactory(config)\n", " client = factory.create(agent_card)\n", "\n", " # Create the message object\n", " message_obj = create_text_message_object(content=message)\n", "\n", " # Send the message and collect responses\n", " responses = []\n", " async for response in client.send_message(message_obj):\n", " responses.append(response)\n", "\n", " # The response is a tuple - get the first element (Task object)\n", " if (\n", " responses\n", " and isinstance(responses[0], tuple)\n", " and len(responses[0]) > 0\n", " ):\n", " task = responses[0][0] # First element of the tuple\n", "\n", " # Extract text: task.artifacts[0].parts[0].root.text\n", " try:\n", " return task.artifacts[0].parts[0].root.text\n", " except (AttributeError, IndexError):\n", " return str(task)\n", "\n", " return 'No response received'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a2a_client = A2ASimpleClient()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "async def test_trending_topics() -> None:\n", " \"\"\"Test trending topics agent.\"\"\"\n", " trending_topics = await a2a_client.create_task(\n", " 'http://localhost:10020', \"What's trending today?\"\n", " )\n", " print(trending_topics)\n", "\n", "\n", "# Run the async function\n", "asyncio.run(test_trending_topics())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "async def test_analysis() -> None:\n", " \"\"\"Test analysis agent.\"\"\"\n", " analysis = await a2a_client.create_task(\n", " 'http://localhost:10021', 'Analyze the trend AI in Social Media'\n", " )\n", " print(analysis)\n", "\n", "\n", "# Run the async function\n", "asyncio.run(test_analysis())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "async def test_host_analysis() -> None:\n", " \"\"\"Test host analysis agent.\"\"\"\n", " host_analysis = await a2a_client.create_task(\n", " 'http://localhost:10022',\n", " 'Find the most relevant trends in the web today, choose randomly one of the top '\n", " 'trends, and give me a complete analysis of it with quantitative data',\n", " )\n", " print(host_analysis)\n", "\n", "\n", "# Run the async function\n", "asyncio.run(test_host_analysis())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "Congratulations! You've successfully built a multi-agent system using Google's A2A protocol. Here's what you've learned:\n", "\n", "1. **A2A Protocol Basics**: How agents discover and communicate with each other\n", "2. **ADK Integration**: Creating ADK agents and wrapping them for A2A\n", "3. **Agent Orchestration**: Building a Host Agent that coordinates multiple agents\n", "4. **Practical Implementation**: Running and testing a complete multi-agent system\n", "\n", "### Next Steps\n", "\n", "- **Deploy Your Agents**: Deploy agents to Cloud Run or other platforms\n", "- **Add Authentication**: Implement security for production use\n", "- **Create More Agents**: Build agents for your specific use cases, even using other frameworks\n", "- **Advanced Patterns**: Explore agent chains, parallel execution, and more\n", "- **Callbacks**: Add in the Google ADK agents the before and after callbacks of the agent, model and tool, to increase observability\n", "\n", "Happy agent building! \ud83d\ude80" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Appendix\n", "\n", "### Why Use Google A2A (Agent-to-Agent) Protocol\n", "\n", "Google's Agent-to-Agent (A2A) protocol is a standardized communication framework that enables AI agents to discover, communicate, and collaborate with each other using a common JSON-RPC based protocol. \n", "It provides a uniform way for agents to interact, regardless of their underlying implementation. \n", "\n", "#### 1. Standardized Communication Protocol\n", "\n", "- A2A provides a consistent, JSON-RPC based protocol that any agent can implement\n", "- Agents can communicate without needing to know each other's internal implementation details\n", "- The protocol supports streaming responses for real-time interactions\n", "\n", "#### 2. Agent Discovery and Metadata\n", "\n", "- Agents expose their capabilities through standardized metadata (AgentCard)\n", "- Each agent publishes its skills, input/output modes, and capabilities\n", "- Host agents can dynamically discover what other agents can do through the `.well-known/agent-card.json` endpoint\n", "\n", "#### 3. Orchestration and Composition\n", "\n", "- Enables building complex multi-agent systems where a host agent can orchestrate multiple specialized agents\n", "- Supports sequential and parallel task execution patterns\n", "- Allows for sophisticated agent collaboration workflows\n", "\n", "#### 4. Platform Independence\n", "\n", "- A2A servers can wrap agents from different frameworks (not just ADK)\n", "- Agents can be deployed as independent services on different infrastructure\n", "- Promotes loose coupling between agents\n", "\n", "### Differences: Using ADK Agents Directly vs. Through A2A\n", "\n", "#### Using ADK Agents Directly\n", "\n", "```python\n", "# Conceptual Example: Defining Hierarchy\n", "from google.adk.agents import LlmAgent, BaseAgent\n", "\n", "# Define individual agents\n", "greeter = LlmAgent(name=\"Greeter\", model=\"gemini-2.5-pro\")\n", "task_doer = BaseAgent(name=\"TaskExecutor\") # Custom non-LLM agent\n", "\n", "# Create parent agent and assign children via sub_agents\n", "coordinator = LlmAgent(\n", " name=\"Coordinator\",\n", " model=\"gemini-2.5-pro\",\n", " description=\"I coordinate greetings and tasks.\",\n", " sub_agents=[ # Assign sub_agents here\n", " greeter,\n", " task_doer\n", " ]\n", ")\n", "```\n", "\n", "__Use Direct ADK for Multi-Agents System When:__\n", "\n", "- All agents are tightly related and always used together\n", "- Google ADK is the framework choice, and simplicity is prioritized\n", "- Performance of in-process communication is critical\n", "- You don't need distributed deployment\n", "- No built-in service discovery is needed\n", "\n", "#### Using ADK Agents Through A2A\n", "\n", "__Use A2A for Multi-Agents System When:__\n", "\n", "- Building complex multi-agent systems\n", "- Agents need to be developed, deployed, and scaled independently\n", "- You want to integrate agents from different teams or frameworks\n", "- You need dynamic agent discovery and composition\n", "- Building a platform where agents can be added/removed dynamically\n", "- You want to enable third-party agent integration" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.6" } }, "nbformat": 4, "nbformat_minor": 4 }