Create multi agent system with ADK, deploy in Agent Engine and get started with A2A protocol

1. Objective of this lab

In this hands-on lab you will build a multi agent application that generates an image, based on your prompt and evaluates it against your prompt. If the image does not satisfactorily meet the requirements described in the prompt, the agent will continuously generate images until the image that meets your requirements is generated. Each of the agents in this hands-on have a single purpose, the agents co-operate with each other to achieve the overall goal.

What you'll learn

  • Understand the basics of ADK and learn how to create a multi-agent system.
  • Learn how to easily deploy and use the agents in GCP.
  • Understand the basics of A2A protocol
  • Learn how to use A2A protocol and ADK together to create open agents.

2. Before you begin

  • If you already do not have a project that you can use, you will need to create a new project in the GCP console.
  • In this lab, we will use GCP Cloud Shell to perform our tasks. Open the Cloud Shell and set the project using Cloud Shell.
  • Open the GCP Cloud Shell Editor by pressing the Cloud Shell Editor Button. If you see the "Authorize Shell" popup, click to authorize the Cloud Shell Editor.
  • You can check if the project is already authenticated using the following command.
gcloud auth list
  • Run the following command in Cloud Shell to confirm your project
gcloud config list project
  • If your project is not set, use the following command to set it
gcloud config set project <YOUR_PROJECT_ID>
  • We need to enable some services to run this lab. Run the following command in Cloud Shell.
gcloud services enable aiplatform.googleapis.com

3. Overview: Benefits of Agent Development Kit

Agent Development Kit offers several key advantages for developers building agentic applications:

  1. Multi-Agent Systems: Build modular and scalable applications by composing multiple specialized agents in a hierarchy. Enable complex coordination and delegation.
  2. Rich Tool Ecosystem: Equip agents with diverse capabilities: use pre-built tools (Search, Code Execution, etc.), create custom functions, integrate tools from third-party agent frameworks (LangChain, CrewAI), or even use other agents as tools.
  3. Flexible Orchestration: Define workflows using workflow agents (SequentialAgent, ParallelAgent, and LoopAgent) for predictable pipelines, or leverage LLM-driven dynamic routing (LlmAgent transfer) for adaptive behavior.
  4. Integrated Developer Experience: Develop, test, and debug locally with a powerful CLI and an interactive dev UI. Inspect events, state, and agent execution step-by-step.
  5. Built-in Evaluation: Systematically assess agent performance by evaluating both the final response quality and the step-by-step execution trajectory against predefined test cases.
  6. Deployment Ready: Containerize and deploy your agents anywhere – run locally, scale with Vertex AI Agent Engine, or integrate into custom infrastructure using Cloud Run or Docker.

While other Gen AI SDKs or agent frameworks also allow you to query models and even empower them with tools, dynamic coordination between multiple models requires a significant amount of work on your end.

Agent Development Kit offers a higher-level framework than these tools, allowing you to easily connect multiple agents to one another for complex but easy-to-maintain workflows.

e554e9e43aafc757.png

4. Introduction to A2A

The Agent2Agent (A2A) protocol is an open standard designed to enable seamless and secure communication and collaboration between autonomous AI agents from different frameworks, vendors, and domains.

  1. Universal Interoperability: A2A allows agents to work together regardless of their underlying technologies, fostering a truly multi-agent ecosystem. This means agents built by different companies on different platforms can communicate and coordinate.
  2. Capability Discovery: Agents can advertise their capabilities using "Agent Cards" (JSON documents), which describe their identity, supported A2A features, skills, and authentication requirements. This allows other agents to discover and select the most suitable agent for a given task.
  3. Secure by Default: Security is a core principle. A2A incorporates enterprise-grade authentication and authorization mechanisms, utilizing standards like HTTPS/TLS, JWT, OIDC, and API keys to ensure secure interactions and protect sensitive data.
  4. Modality Agnostic: The protocol supports various communication modalities, including text, audio, and video streaming, as well as interactive forms and embedded iframes. This flexibility allows agents to exchange information in the most appropriate format for the task and user.
  5. Structured Task Management: A2A defines clear protocols for task delegation, monitoring, and completion. It supports grouping related tasks and managing them across different agents using unique task IDs. Tasks can transition through defined lifecycles (e.g., submitted, working, completed).
  6. Opaque Execution: A significant feature is that agents don't need to reveal their internal reasoning processes, memory, or specific tools to other agents. They only expose their callable services, promoting modularity and privacy.
  7. Built on Existing Standards: A2A leverages established web technologies such as HTTP, Server-Sent Events (SSE) for real-time streaming, and JSON-RPC for structured data exchange, making it easier to integrate with existing IT infrastructure.
  8. Asynchronous Communication: The protocol is designed with asynchronous communication as a primary consideration, facilitating flexible task progression and enabling push notifications for updates even when a connection isn't persistently maintained.

5. Agent Architecture

In this lab, you will create a multi-agent application that generates an image according to your specification and evaluates the image before presenting it to you.

The system is structured with a main agent called image_scoring that orchestrates the entire process. This main agent has a sub-agent called image_generation_scoring_agent which in turn has its own sub-agents for more specific tasks. This creates a hierarchical relationship where the main agent delegates tasks to its sub-agents. 6e21de5b4f92669c.png Figure 2: Overall Agent flow.

List of All Agents

  1. image_scoring (Main Agent):
  2. Purpose: This is the root agent that manages the overall workflow. It repeatedly runs the image_generation_scoring_agent and the checker_agent in a loop until a termination condition is met.
  3. Sub-agents:
  • image_generation_scoring_agent
  • checker_agent_instance
  1. image_generation_scoring_agent (Sub-agent of image_scoring):
  2. Purpose: This agent is responsible for the core logic of generating and scoring images. It executes a sequence of three sub-agents to achieve this.
  3. Sub-agents:
  • image_generation_prompt_agent
  • image_generation_agent
  • scoring_images_prompt
  1. checker_agent_instance (Sub-agent of image_scoring):
  2. Purpose: This agent checks if the image scoring process should continue or terminate. It uses the check_tool_condition tool to evaluate the termination condition.
  3. image_generation_prompt_agent (Sub-agent of image_generation_scoring_agent):
  4. Purpose: This agent is an expert in creating prompts for image generation. It takes an input text and generates a detailed prompt suitable for the image generation model.
  5. image_generation_agent (Sub-agent of image_generation_scoring_agent):
  6. Purpose: This agent is an expert in creating images using Imagen 3. It takes the prompt from the image_generation_prompt_agent and generates an image.
  7. scoring_images_prompt (Sub-agent of image_generation_scoring_agent):
  8. Purpose: This agent is an expert in evaluating and scoring images based on various criteria. It takes the generated image and assigns a score to it.

Tools Used by the Agents

  1. check_tool_condition:
  2. Description: This tool checks if the loop termination condition is met or if the maximum number of iterations has been reached. If either of these is true, it stops the loop.
  3. Used by: checker_agent_instance
  4. generate_images:
  5. Description: This tool generates images using the Imagen 3 model. It can also save the generated images to a Google Cloud Storage bucket.
  6. Used by: image_generation_agent
  7. get_policy:
  8. Description: This tool fetches a policy from a JSON file. The policy is used by the image_generation_prompt_agent to create the image generation prompt and by the scoring_images_prompt to score the images.
  9. Used by: image_generation_prompt_agent, scoring_images_prompt
  10. get_image:
  11. Description: This tool loads the generated image artifact so that it can be scored.
  12. Used by: scoring_images_prompt
  13. set_score:
  14. Description: This tool sets the total score of the generated image in the session state.
  15. Used by: scoring_images_prompt

6. Task 1. Install ADK and set up your environment

In this Hands on we will use Cloud Shell to perform the tasks.

  1. In the Google Cloud console, navigate to Vertex AI by searching for it at the top of the console.
  2. Click Enable all recommended APIs.

Prepare a Cloud Shell Editor tab

  1. With your Google Cloud console window selected, open Cloud Shell by pressing the G key and then the S key on your keyboard. Alternatively, you can click the cloud shell button 231dc0e6754519c8.pngon the top right corner of the Google Cloud Console.
  2. Click Continue.
  3. When prompted to authorize Cloud Shell, click Authorize.
  4. In the upper right corner of the Cloud Shell pane, click the Open in new window button Open in new window button.
  5. Click the Open Editor pencil icon ( Open Editor pencil icon) at the top of the pane to view files.
  6. At the top of the left-hand navigation menu, click the Explorer icon Explorer icon to open your file explorer.
  7. Click the Open Folder button.
  8. Throughout the rest of this lab, you can work in this window as your IDE with the Cloud Shell Editor and Cloud Shell Terminal.

Download and install the ADK and code samples for this lab

  1. Execute the following commands to clone the needed source from github and install necessary libraries.
#create the project directory
mkdir imagescoring
cd imagescoring
#clone the code in the local directory
git clone https://github.com/haren-bh/multiagenthandson.git

#Create the virtual environment
python3 -m venv pythonenv
source pythonenv/bin/activate

#install google-adk and a2a sdk
python3 -m pip install google-adk==1.8.0
python3 -m pip install a2a-sdk==0.2.16
  1. We will use poetry to install additional requirements:
cd multiagenthandson #go to the application directory
pip install poetry poetry-plugin-export
poetry install --with deployment
  1. If you do not have a cloud storage bucket, create a new one in Google Cloud Storage. You can also create the bucket using gsutil command.
gsutil mb gs://YOUR-UNIQUE-BUCKETNAME
  1. In the editor go to View->Toggle hidden files. And in the image_scoring folder create a .env file with the following content. Add the required details such as your project name and cloud storage bucket.
GOOGLE_GENAI_USE_VERTEXAI=1 #1 if VERTEXAI has to be used. Can be 0 if API_KEY is specified
GOOGLE_CLOUD_PROJECT=YOUR CLOUD PROJECT NAME
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_CLOUD_STORAGE_BUCKET=YOUR BUCKET NAME  # Only required for deployment on Agent Engine
GCS_BUCKET_NAME=YOUR BUCKET NAME #Bucket for storing generated images.
SCORE_THRESHOLD=40 # Min threshold for image_score. Max Score is 50 , hence should be less than 50. 
#If the computed score is higher then loop will terminate
#MAX_ITERATIONS=5 #Max iterations for evaluating the image_score before terminating the loop.
IMAGEN_MODEL="imagen-3.0-generate-002" 
GENAI_MODEL="gemini-2.5-flash"
#AGENT_ENGINE_ID=<AGENT_ENGINE_ID> #The Agent Engine ID obtained after deploying to the agent engine.
  1. Look at the agent structure in the source code, start at agent.py . This agent contains the root agent that will connect to the other agents.
  2. Go back to the top directory multiagenthandson in the terminal and execute the following command to run the agent locally
# Run the following command to run agents locally
export GCS_BUCKET_NAME=your gcs bucket name
adk web

7bb4bc5f8244c140.png Figure 1

Ctrl+Click (CMD+Click for MacOS) on the http:// url displayed on the terminal to open the ADK's browser based GUI client. It should look like Figure 2

  1. Let's generate some images. Try the following prompts or your own prompts.
  2. A peaceful mountain landscape at sunset
  3. A cat riding a bicycle

99e23472f80a81f2.png Figure 2

7. Task 2. Deploy to Agent Engine

Now we deploy the agent to the Agent Engine. Agent Engine is a fully managed service for deploying agents in GCP. Agent Engine is compatible with ADK so the agents built with ADK can be deployed in Agent Engine.

  1. Define some environment variables
export GOOGLE_CLOUD_LOCATION='us-central1'
export GOOGLE_CLOUD_PROJECT='your project id'
  1. Create the requirements.txt file using poetry. Poetry will use pyproject.toml to create requirements.txt file. After running the command check if requirements.txt file has been created.
# Go to the parent folder containing pyproject.toml file
# install poetry-plugin-export
pip install poetry-plugin-export

#Create requirements.txt file
poetry export -f requirements.txt --output requirements.txt --without-hashes
  1. Create the package. We need to bundle our app into a .whl python package. We will use poetry to do that. Once you execute the command make sure a dist folder is created and it contains the .whl file.
# Go to the parent folder containing pyproject.toml file
#Create python package, to create whl file
poetry build
  1. Now we will prepare the deploy script. The deploy script will deploy our image-scoring agent or agent engine service. Please change the content of deploy.py inside the image_scoring folder as below.
# Change the content of the following. Look for #change this comment
import vertexai
from .agent import root_agent
import os
import glob # To easily find the wheel file

PROJECT_ID = "YOUR PROJECT ID" #change this your project
LOCATION = "us-central1" #change this
STAGING_BUCKET = "gs://YOUR BUCKET " #change this to your bucket

from vertexai import agent_engines

vertexai.init(
   project=PROJECT_ID,
   location=LOCATION,
   staging_bucket=STAGING_BUCKET,
)

remote_app = agent_engines.create(
   agent_engine=root_agent,
   requirements=open(os.path.join(os.getcwd(), "requirements.txt")).readlines()+["./dist/image_scoring-0.1.0-py3-none-any.whl"],#change this to your local location
   extra_packages=[
       "./dist/image_scoring-0.1.0-py3-none-any.whl", # change this to your location
   ]
)

print(remote_app.resource_name)
  1. We can now run the deploy script.
#run deploy script from the parent folder containing deploy.py
python3 -m image_scoring.deploy

After you deploy you should see something like below, 13109f2a5c5c5af9.png

Figure 3

  1. Now let's test the deployed agent. In order to test the remotely deployed agent engine first copy the agent location from the deploy output in the terminal. It should look something like this, projects/85469421903/locations/us-central1/reasoningEngines/7369674597261639680 .
    Go to the folder testclient, open the file remote_test.py and edit the following lines.
PROJECT_ID = "" #change this
LOCATION = "" #change this
STAGING_BUCKET = "" #change this

#replace the id with your own.
reasoning_engine_id="your agent engine id"

#You can replace this with your own prompt
image_prompt="A cat riding a bicycle"

#execute remote_test.py
python3 remote_test.py

8. Task 3. Create an A2A agent

In this step we are going to create a simple A2A agent based on the agent we created in the previous steps. Existing ADK agents can be published under A2A protocol. These are the key things you will learn in this step.

  • Learn the basics of A2A protocol.
  • Learn how ADK and A2A protocols work with each other.
  • Learn how to interact with A2A protocol.

In this hands on we will use the code in image_scoring_adk_a2a_server folder. Before you start the task please change your directory to this folder.

Create A2A agent card

A2A protocol requires an agent card that contains all the information about the agent such as agent capabilities, agent usage guide etc. Once an A2A agent is deployed the agent card is viewable using the ".well-known/agent-card.json" link. Clients can refer to this information to send the request to agents.

In the remote_a2a/image_scoring folder confirm there is agents.json with the following content.

{
 "name": "image_scoring",
 "description": "Agent that generates images based on user prompts and scores their adherence to the prompt.",
 "url": "http://localhost:8001/a2a/image_scoring",
 "version": "1.0.0",
 "defaultInputModes": ["text/plain"],
 "defaultOutputModes": ["image/png", "text/plain"],
 "capabilities": {
   "streaming": true,
   "functions": true
 },
 "skills": [
   {
     "id": "generate_and_score_image",
     "name": "Generate and Score Image",
     "description": "Generates an image from a given text prompt and then evaluates how well the generated image adheres to the original prompt, providing a score.",
     "tags": ["image generation", "image scoring", "evaluation", "AI art"],
     "examples": [
       "Generate an image of a futuristic city at sunset",
       "Create an image of a cat playing a piano",
       "Show me an image of a serene forest with a hidden waterfall"
     ]
   }
 ]
}

Create A2A agent

Within the root folder image_scoring_adk_a2a_server, confirm that there is an a2a_agent.py file, which is the entry point for a2a agent. It should have following content,

from google.adk.agents.remote_a2a_agent import RemoteA2aAgent

root_agent = RemoteA2aAgent(
   name="image_scoring",
   description="Agent to give interesting facts.",
   agent_card="http://localhost:8001/a2a/image_scoring/.well-known/agent.json",
  
   # Optional configurations
   timeout=300.0,          # HTTP timeout (seconds)
   httpx_client=None,      # Custom HTTP client
)

Run A2A agent

Now we are ready to run the agent! To run the agent execute following command from inside the top folder image_scoring_adk_a2a_server

#set some environmental variables
export GOOGLE_CLOUD_PROJECT=datapipeline-372305
export GOOGLE_CLOUD_LOCATION=us-central1
export GCS_BUCKET_NAME=haren-genai-bucket

#following command runs the ADK agent as a2a agent
adk api_server --a2a --port 8001 remote_a2a

Test A2A agent

Once the agent is running we can now go and test the agent. First of all, let's go ahead and check the agent card.

#Execute the following 
curl http://localhost:8001/a2a/image_scoring/.well-known/agent.json

Executing the above should show the agent card for our A2A agent, which is mainly the content of agent.json that we created in the previous step.

Let's now send a request to the agent. We can use curl to send request to the agent,

curl -X POST   http://localhost:8001/a2a/image_scoring   -H 'Content-Type: application/json'   -d '{
    "id": "uuid-123",
    "params": {
      "message": {
        "messageId": "msg-456",
        "parts": [{"text": "Create an image of a cat"}],
        "role": "user"
      }
    }
  }'

In the above request, you can change the prompt by changing the "Create an image of a cat" line. Once you run the command, you can check for the output image in the specified google cloud storage.

9. Clean up

Now let's clean up what we just created.

  1. Delete the Agent Engine server we just created. Go to Vertex AI by typing Vertex AI in the search bar of Google Cloud Console. Click on the Agent Engine on the left hand side.You can delete the Agent by clicking delete. c9f95963c4db0d6c.png

Figure 4

  1. Delete the files in Cloud Shell
#Execute the following to delete the files
rm -R imagescoring
  1. Delete the bucket. You can go to the GCP console->Cloud Storage , select and delete your bucket. afb43ad0dda70858.png