Step-by-step guide to building your first AI agent with ADK and deploying it to Cloud Run.
What is the Agent Development Kit?
Agent Development Kit (ADK) is a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and is built for compatibility with other frameworks. ADK was designed to make agent development feel more like software development, to make it easier for developers to create, deploy, and orchestrate agentic architectures that range from simple tasks to complex workflows.
Why ADK Stands Out
ADK isn’t just another library; it’s a comprehensive framework designed for building real-world, production-ready agents.
➡️ Model-Agnostic: Works seamlessly with various LLMs, giving you the flexibility to choose the best model for the job.
➡️ Framework Compatibility: Easily integrates with existing systems and other popular frameworks like LangChain.
➡️ Rich Tool Ecosystem: Provides extensible and customizable capabilities, allowing agents to interact with external APIs and services.
➡️ Deployment-Agnostic: Offers flexible deployment options, from local testing to scalable cloud environments like Google Cloud Run.
➡️ Built-in Memory: Enables context retention and persistence, allowing for stateful, multi-turn conversations and workflows.
➡️ Rapid Development: Build powerful, multi-agent systems with less than 100 lines of code.
➡️ Enterprise-Grade: Designed with security and scalability in mind for production use.
➡️ Multi-Agent Systems: Natively supports the creation and orchestration of complex agent interactions.
➡️ Built-in Evaluation: Comes with tools for performance assessment and testing.
➡️ Versatile Agent Types: Supports LLM Agents, rule-based Workflow Agents, and fully Custom Agents.
Hands-On: Building an Autonomous Receipt Processor
Theory is great, but the best way to understand ADK’s power is to build something. Let’s create an intelligent system that automates expense receipt processing from end to end. This real-world example will showcase how ADK orchestrates multiple specialized agents to perform a complex task: extracting data from an image, classifying it, and logging it into a database.
Our workflow will be handled by a team of three specialized AI agents, all managed by a root “orchestrator” agent:
- OCR Extractor Agent: Analyzes a receipt image to extract structured data (vendor, date, total, line items).
- Category Classifier Agent: Determines the expense category (e.g., Dining, Groceries, Travel).
- Finance Logger Agent: Logs the final, categorized data into a BigQuery table.
This multi-agent approach is a perfect use case for ADK. By breaking down a complex problem into smaller, manageable tasks for specialized agents, we create a solution that is more robust, scalable, and easier to maintain.
Before you Begin
- Clone the project repository
git clone https://github.com/sijohn/build-with-adk.git
cd doc_processor
We’re using uv in this codelab because it’s an extremely fast, all-in-one tool for managing Python packages and virtual environments, often replacing separate tools like pip and venv. If you’re more comfortable with other tools, feel free to use them to create a virtual environment and install the dependencies listed in pyproject.toml.
Initialize a Python virtual environment and install the required dependencies from the pyproject.toml file using uv:
uv sync
Authenticate your local environment by running the following command in your terminal and following the instructions:
gcloud auth application-default login
Set the GCP_PROJECT_ID environment variable. This is crucial for the agent’s tool to know which project to write to in BigQuery. Replace your-gcp-project-id with your actual Project ID.
export GCP_PROJECT_ID="your-gcp-project-id"
Create a .env file in the root of your project directory (doc_processor/.env) and add the following content. This file will configure your agent to use Vertex AI. Remember to replace your-gcp-project-id with your actual Google Cloud Project ID.
# Use Vertex AI as the backend for generative models
GOOGLE_GENAI_USE_VERTEXAI=TRUE# Your Google Cloud project ID
GOOGLE_CLOUD_PROJECT=your-gcp-project-id
# The location for your Vertex AI resources
GOOGLE_CLOUD_LOCATION=us-central1
Understanding the Project Structure
The cloned repository contains a standard project structure inside the doc_processor_agent/ directory. Let’s walk through the key files:
- pydantic_model.py: Defines our custom data structures (schemas) to ensure type safety and clear communication between agents.
- tools.py: Contains the custom tool that allows the agent to interact with Google BigQuery.
- agent.py: The heart of the project. It defines the three specialized LlmAgents and the SequentialAgent that coordinates their execution.
Step 1: Defining the Data Schemas for Reliable Communication
Clear communication is the backbone of any multi-agent system. ADK solves this by using Pydantic models to define strict data schemas, ensuring that agents pass information to each other reliably and predictably.
from pydantic import BaseModel, Field
from typing import List, Optionalclass OcrInput(BaseModel):
"""Input for the OCR agent, containing the image path."""
image_path: str = Field(description="The local path to the receipt image.")
class ClassificationOutput(BaseModel):
"""Output for the classification agent, containing the determined category."""
category: str = Field(description="The classified expense category.")
class LineItem(BaseModel):
"""Represents a single line item on a receipt."""
description: str = Field(description="Description of the item purchased.")
quantity: int = Field(description="Quantity of the item purchased.")
price: float = Field(description="Price of the item purchased.")
class Receipt(BaseModel):
"""Represents the entire structured receipt data."""
vendor_name: str = Field(description="Name of the vendor or store.")
transaction_date: str = Field(description="Date of the transaction in YYYY-MM-DD format.")
total_amount: float = Field(description="Total amount of the transaction.")
line_items: List[LineItem] = Field(description="List of items purchased.")
category: Optional[str] = Field(description="Expense category, to be filled by the classifier.", default=None)
Step 2: Equipping Agents with Tools to Act
Agents become truly powerful when they can interact with the outside world. ADK makes it incredibly simple to give agents “tools” — custom Python functions they can call to perform actions. Our Finance Logger Agent
needs a tool to write data to Google BigQuery, and we provide it with a standard Python function that handles the API interaction.
import os
import json
from google.cloud import bigquery
from .pydantic_model import Receipt
from adk.tools import ToolContextdef log_expense_to_bigquery(receipt: Receipt, tool_context: ToolContext) -> dict:
"""
Logs a receipt's data into a BigQuery table.
It creates the dataset and table if they don't exist.
"""
project_id = os.environ.get("GCP_PROJECT_ID")
if not project_id:
return {"status": "error", "message": "GCP_PROJECT_ID environment variable not set."}
client = bigquery.Client(project=project_id)
dataset_id = f"{project_id}.finance_data"
table_id = f"{dataset_id}.expenses"
# Create dataset if it doesn't exist
try:
client.get_dataset(dataset_id)
except Exception:
dataset = bigquery.Dataset(dataset_id)
client.create_dataset(dataset, timeout=30)
# Create table if it doesn't exist
try:
client.get_table(table_id)
except Exception:
schema = [
bigquery.SchemaField("vendor_name", "STRING", mode="NULLABLE"),
bigquery.SchemaField("transaction_date", "DATE", mode="NULLABLE"),
bigquery.SchemaField("total_amount", "FLOAT", mode="NULLABLE"),
bigquery.SchemaField("category", "STRING", mode="NULLABLE"),
bigquery.SchemaField("line_items", "STRING", mode="NULLABLE"),
]
table = bigquery.Table(table_id, schema=schema)
client.create_table(table, timeout=30)
# Prepare and insert row
row_to_insert = {
"vendor_name": receipt.vendor_name,
"transaction_date": receipt.transaction_date,
"total_amount": receipt.total_amount,
"category": receipt.category,
"line_items": json.dumps([item.dict() for item in receipt.line_items]),
}
errors = client.insert_rows_json(table_id, [row_to_insert])
if not errors:
return {"status": "success", "message": f"Logged expense from {receipt.vendor_name} to BigQuery."}
else:
return {"status": "error", "message": f"Failed to insert row: {errors}"}
Step 3: Building and Orchestrating the Agent Team
This is where it all comes together. We define our three specialized LlmAgent
instances and the SequentialAgent
that orchestrates them. The code is remarkably concise because ADK handles the complex state management and agent-to-agent communication behind the scenes.
from adk.agent import LlmAgent, SequentialAgent
from .pydantic_model import Receipt, OcrInput, ClassificationOutput
from .tools import log_expense_to_bigquery# Agent 1: Extracts structured data from an image (mocked)
ocr_extractor_agent = LlmAgent(
name="ocr_extractor_agent",
model="gemini-2.0-flash",
description="Parses a receipt image and extracts structured data.",
instruction="""You are an OCR (Optical Character Recognition) agent. Given an image path, you must extract key details. For this codelab, you will generate realistic mock data.
You must return the extracted information in a structured JSON format conforming to the Receipt model.
""",
input_schema=OcrInput,
output_schema=Receipt,
output_key="extracted_receipt"
)
# Agent 2: Classifies the expense category
category_classifier_agent = LlmAgent(
name="category_classifier_agent",
model="gemini-2.0-flash",
description="Classifies the expense category based on receipt data.",
instruction="""You are an expense categorization agent.
Analyze the vendor name and line items from the receipt data to determine the best category from the list:
Dining, Groceries, Fuel, Travel, Entertainment, Other.
The receipt data will be available in the session state under the key 'extracted_receipt'.
You must update the 'category' field of the receipt data.
""",
output_schema=ClassificationOutput,
output_key="classified_category"
)
# Agent 3: Logs the final data to BigQuery using a tool
finance_logger_agent = LlmAgent(
name="finance_logger_agent",
model="gemini-2.0-flash",
description="Logs the classified expense into a financial system (BigQuery).",
instruction="""You are a finance logging agent.
Your job is to take the final, categorized receipt data and log it.
The full receipt details are in the session state under 'extracted_receipt'.
The category is in the session state under 'classified_category'.
First, you MUST update the 'category' in the 'extracted_receipt' object with the value from 'classified_category'.
Then, you MUST call the `log_expense_to_bigquery` tool with the updated receipt object.
""",
tools=[log_expense_to_bigquery]
)
# Root Agent: Orchestrates the entire workflow
root_agent = SequentialAgent(
name="expense_tracker_orchestrator",
sub_agents=[
ocr_extractor_agent,
category_classifier_agent,
finance_logger_agent
],
description="Orchestrates the entire expense tracking workflow from OCR to logging."
)
Running and Testing the Agent
What Happens in BigQuery?
When you run the agent for the first time, the log_expense_to_bigquery tool is designed to be idempotent. It will automatically:
- Check if a dataset named finance_data exists in your GCP project. If not, it will create it.
- Check if a table named expenses exists within that dataset. If not, it will create it with the correct schema.
1. Testing with the ADK Web UI
The Google ADK comes with a built-in web server for interactively testing your agents.
Start the web server from your terminal in the root of your doc_processor project directory:
uv run adk web
Open your browser and navigate to the URL provided (usually http://127.0.0.1:8000).
From the dropdown menu, select the doc_processor_agent.
In the input box, upload a receipt from the samples directory or any receipt of your choice. Also please note that in the adk web aUI, you have to send a text message (Eg: “Hi”) for the Send button to be enabled.
Click “Run” to start the workflow.
You will see the outputs from each agent in the sequence. Check your BigQuery console to see the data appear in the finance_data.expenses table.
Deploying the Agent to Google Cloud Run
The Google Agent Development Kit provides a streamlined command to deploy your agent directly to Google Cloud Run, making it accessible as a web service.
Set Environment Variables for Deployment: In your terminal, set the following environment variables. The ADK will use these to configure the Cloud Run deployment.
# Set your Google Cloud Project ID (should match your .env file)
# Set your Google Cloud Project ID
export GOOGLE_CLOUD_PROJECT="your-google-cloud-project"# Set your desired Google Cloud Location
export GOOGLE_CLOUD_LOCATION="us-central1"
# Set the path to your agent code directory
export AGENT_PATH="./doc_processor_agent"
# Set a name for your Cloud Run service (optional)
export SERVICE_NAME="doc-processor-agent-service"
# Set an application name (optional)
export APP_NAME="doc-processor-agent-app"
Run the Deploy Command: Execute the following command to start the deployment process. The — with_ui flag packages the ADK’s web interface along with your agent.
uv run adk deploy cloud_run \
--project=$GOOGLE_CLOUD_PROJECT \
--region=$GOOGLE_CLOUD_LOCATION \
--service_name=$SERVICE_NAME \
--app_name=$APP_NAME \
--with_ui \
$AGENT_PATH
The ADK will containerize your agent, push it to the Google Artifact Registry, and deploy it as a new service on Cloud Run. Once complete, it will provide a URL to access your deployed agent.
Grant BigQuery Permissions to Cloud Run Service Account: After deployment, your Cloud Run service uses a service account to interact with other Google Cloud services. For the agent to log data, you must grant the BigQuery Data Editor role to this service account. You can find the service account’s email in the Cloud Run service details and grant the role in the IAM & Admin section of the Google Cloud Console.
You can test your agent by simply navigating to the Cloud Run service URL provided after deployment in your web browser.
# Example URL format# https://your-service-name-abc123xyz.a.run.app
The ADK dev UI allows you to interact with your agent, manage sessions, and view execution details directly in the browser.
To verify your agent is working as intended, you can:
Select your agent from the dropdown menu.
Upload a file and type a message (Hi) and verify that you receive an expected response from your agent.
Closing Thoughts
The agentic leap isn’t just “better prompts.” It’s software-grade architecture — types, tools, tests, and deploys — wrapped around capable models. ADK gives developers those building blocks without friction. Start with a single agent, add a second, compose a workflow… and before long, you’ve shipped a real, production-ready AI system.
Build once. Orchestrate many. Ship anywhere. That’s ADK.
Author’s note: The patterns and steps above reflect a practical implementation that extracts fields from receipt images, classifies expenses, and persists them to BigQuery with an agentic workflow — designed, tested, and deployable end-to-end.
Source Credit: https://medium.com/google-cloud/fast-track-your-agentic-ai-journey-with-googles-adk-hands-on-from-code-to-cloud-dc0d011069a9?source=rss—-e52cf94d98af—4