Google ADK — The Complete Guide to Building AI Agents with the Agent Development Kit
Summary
Google released the Agent Development Kit — ADK — and it is not just another AI framework. It is a full production-grade system for building, debugging, and deploying AI agents that actually work in the real world. Open source, multi-language, and designed to scale from a single agent on your laptop to a fleet of coordinated agents on Google Cloud.
If you have been building agents with CrewAI or rolling your own with raw API calls, ADK is worth paying attention to. It solves problems that most frameworks ignore — context management, safety guardrails, multi-agent delegation, and seamless deployment.
Let us break down everything you need to know.
What is Google ADK
The Agent Development Kit is an open-source framework for building AI agents. Not chatbots. Not simple prompt wrappers. Autonomous agents that can reason, use tools, maintain memory, delegate tasks to other agents, and recover from failures.
ADK supports four languages — Python, TypeScript, Go, and Java — with consistent APIs across all of them. You write agents the same way regardless of your stack.
What sets ADK apart from other frameworks:
- Context as structured code — ADK does not just concatenate strings. It automatically filters irrelevant events, summarizes older conversation turns, lazy-loads artifacts, and tracks token usage to stay efficient within context windows
- Built-in safety layer — callbacks for validating inputs and tool usage before execution, not as an afterthought
- Model-agnostic — works with Gemini, Claude, GPT, Gemma, Ollama, vLLM, and anything LiteLLM supports
- Production deployment built in — same code runs locally and on Cloud Run, GKE, or the managed Agent Runtime
The official site is adk.dev and the source lives on GitHub.
Why Google Built It
Building an AI agent sounds simple until you actually try to run one in production. You quickly hit problems that no LLM API can solve on its own:
Context window management. Agents that run for extended sessions blow through context limits. You need intelligent summarization, event filtering, and artifact management. ADK handles this automatically.
Multi-step reliability. A real agent makes dozens of decisions in sequence. Each one can fail. You need retry logic, failure recovery, and deterministic workflow control for the parts that should not be left to LLM reasoning.
Tool orchestration. Agents need to call APIs, read files, search the web, and interact with external services. Each tool needs authentication, error handling, and validation. ADK provides a structured tool system with built-in and custom tools.
Safety at scale. When agents make autonomous decisions, you need guardrails. Input validation before the model sees the prompt. Tool argument checking before execution. ADK provides callback hooks for both.
Deployment gap. Most frameworks work great in a Jupyter notebook and fall apart in production. ADK was designed from the start to deploy to Cloud Run, GKE, or managed infrastructure with zero code changes.
Google built ADK because they needed it for their own products. That is usually a good sign for a framework’s long-term viability.
The Three Types of Agents
ADK organizes agents into three categories. Understanding these is the foundation of everything else.
LLM Agents
The core agent type. Uses a large language model as its reasoning engine to understand input, decide what to do, pick which tools to use, and generate responses. This is what most people think of when they hear “AI agent.”
1
2
3
4
5
6
7
8
9
from google.adk import Agent
from google.adk.tools import google_search
agent = Agent(
name="researcher",
model="gemini-flash-latest",
instruction="You help users research topics thoroughly.",
tools=[google_search],
)
LLM agents are non-deterministic — they reason about each request dynamically. Use them for tasks that require understanding natural language, making judgment calls, and adapting to different inputs.
Workflow Agents
These control the execution flow of other agents in deterministic, predictable patterns — without using an LLM for the flow control itself. Three types:
- SequentialAgent — runs agents one after another in order
- ParallelAgent — runs agents simultaneously
- LoopAgent — repeats agents until a condition is met
Use workflow agents when you need guaranteed execution order. SEO research → content writing → social media posting is a perfect sequential workflow. Running a grammar check and a fact check at the same time is a parallel workflow.
Custom Agents
For when neither LLM nor workflow agents fit. You extend BaseAgent directly and implement your own logic. Custom agents are useful for specialized integrations, unique control flows, or hybrid approaches.
The real power comes from combining all three types. LLM agents handle the intelligent, language-based tasks. Workflow agents manage the process flow. Custom agents fill in the gaps.
| Aspect | LLM Agent | Workflow Agent | Custom Agent |
|---|---|---|---|
| Engine | Large Language Model | Predefined logic | Your code |
| Determinism | Flexible, non-deterministic | Deterministic, predictable | Variable |
| Best for | Language tasks, dynamic decisions | Structured processes, orchestration | Tailored requirements |
Building Your First Agent
Here is a minimal agent in Python. Install ADK first:
1
pip install google-adk
Create a weather agent with a custom tool:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from google.adk import Agent
def get_weather(city: str) -> dict:
"""Fetches the current weather for a given city.
Args:
city: The name of the city to get weather for.
Returns:
A dictionary with weather information.
"""
# In production, call a real weather API
weather_data = {
"New York": {"temp": "22°C", "condition": "Sunny"},
"London": {"temp": "15°C", "condition": "Cloudy"},
"Tokyo": {"temp": "28°C", "condition": "Humid"},
}
return weather_data.get(city, {"temp": "Unknown", "condition": "No data"})
agent = Agent(
name="weather_agent",
model="gemini-flash-latest",
instruction="""You are a helpful weather assistant.
When users ask about weather, use the get_weather tool
to fetch current conditions. Provide clear, concise answers.""",
tools=[get_weather],
)
A few things to notice. The tool is a plain Python function — no special decorator, no class to extend. ADK reads the docstring and type hints to understand what the tool does and how to use it. The agent’s instruction tells it when and how to use the tool.
Running the Agent
ADK provides a session system for managing conversations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from google.adk import Agent, Runner
from google.adk.sessions import InMemorySessionService
import asyncio
# Set up session management
session_service = InMemorySessionService()
async def main():
session = await session_service.create_session(
app_name="weather_app",
user_id="user_1",
session_id="session_1",
)
runner = Runner(
agent=agent,
app_name="weather_app",
session_service=session_service,
)
response = await runner.run(input="What's the weather in Tokyo?")
print(response)
asyncio.run(main())
The Runner handles the execution loop — sending the user input to the agent, processing tool calls, and returning the final response. The SessionService tracks conversation history so the agent remembers context across turns.
Multi-Agent Teams — Where ADK Shines
Single agents are useful. Teams of specialized agents are transformative. ADK handles multi-agent delegation natively through the sub_agents parameter.
Here is a team with three specialized agents and one root agent that routes requests:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from google.adk import Agent
# Specialist agents
greeting_agent = Agent(
name="greeting_agent",
model="gemini-flash-latest",
description="Handles greetings and casual conversation.",
instruction="You are friendly and welcoming. Handle hellos and casual chat.",
)
weather_agent = Agent(
name="weather_agent",
model="gemini-flash-latest",
description="Provides weather information for any city.",
instruction="Use the get_weather tool to answer weather questions.",
tools=[get_weather],
)
research_agent = Agent(
name="research_agent",
model="gemini-flash-latest",
description="Researches topics using web search.",
instruction="Use Google Search to find accurate, up-to-date information.",
tools=[google_search],
)
# Root agent — the orchestrator
root_agent = Agent(
name="coordinator",
model="gemini-flash-latest",
instruction="""You are a helpful assistant. Route user requests
to the most appropriate specialist agent. Use greeting_agent for
casual conversation, weather_agent for weather queries, and
research_agent for information requests.""",
sub_agents=[greeting_agent, weather_agent, research_agent],
)
The root agent reads the description of each sub-agent and automatically decides who should handle each request. User says “hello” — routes to greeting agent. User asks “what is the weather in London” — routes to weather agent. User asks “what is the latest news about AI” — routes to research agent.
This is the same pattern we explored in the AI business team post, but with ADK handling all the delegation plumbing. No manual routing logic needed.
Tools and Integrations
ADK gives agents capabilities through tools. There are several ways to add them.
Built-in Tools
Google Search comes out of the box:
1
2
3
4
5
6
7
from google.adk.tools import google_search
agent = Agent(
name="researcher",
model="gemini-flash-latest",
tools=[google_search],
)
Custom Function Tools
Any Python function with type hints and a docstring becomes a tool:
1
2
3
4
5
6
7
8
9
10
11
12
def search_database(query: str, limit: int = 10) -> list:
"""Searches the product database for matching items.
Args:
query: The search term to look for.
limit: Maximum number of results to return.
Returns:
A list of matching products with name, price, and availability.
"""
# Your database logic here
return results
The docstring is critical. The LLM reads it to understand when to use the tool and what arguments to pass. Vague docstrings produce vague tool usage.
MCP Tools
ADK supports Model Context Protocol tools, so you can connect to any MCP server:
1
2
3
4
from google.adk.tools.mcp import MCPTool
# Connect to an MCP server for database access
mcp_tool = MCPTool(server_url="http://localhost:3000")
OpenAPI Tools
Generate tools automatically from OpenAPI specifications. Point ADK at your API’s OpenAPI spec and it creates tools for every endpoint — no manual wrapping needed.
Multi-Model Support
ADK is not locked to Gemini. Use any model through LiteLLM:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from google.adk import Agent
from google.adk.models import LiteLlm
# Use Claude
agent = Agent(
name="analyst",
model=LiteLlm(model="anthropic/claude-sonnet-4-20250514"),
instruction="You analyze data and provide insights.",
)
# Use a local Ollama model
agent = Agent(
name="local_agent",
model=LiteLlm(model="ollama/llama3"),
instruction="You run completely locally with no API costs.",
)
This means you can mix models within a team — use Gemini Flash for fast routing in the root agent, Claude for complex analysis in a sub-agent, and a local Ollama model for cost-sensitive tasks.
Session State and Memory
Agents that forget everything between turns are useless for real applications. ADK provides session state so agents can remember context.
Reading and Writing State in Tools
Tools can access session state through the ToolContext parameter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from google.adk.tools import ToolContext
def get_weather(city: str, tool_context: ToolContext = None) -> dict:
"""Fetches weather for a city, respecting user's unit preference."""
weather = fetch_weather_api(city)
# Read user preference from session state
unit = tool_context.state.get("temp_unit", "celsius")
if unit == "fahrenheit":
weather["temp"] = celsius_to_fahrenheit(weather["temp"])
# Save last searched city to state
tool_context.state["last_city"] = city
return weather
Auto-Saving Agent Output
Use output_key to automatically save an agent’s final response to session state:
1
2
3
4
5
6
7
agent = Agent(
name="weather_agent",
model="gemini-flash-latest",
instruction="Provide weather information.",
tools=[get_weather],
output_key="last_weather_report", # Auto-saved to session state
)
After the agent runs, session.state["last_weather_report"] contains its response. Other agents in the team can read this — enabling data flow between agents without explicit piping.
Safety and Guardrails
This is where ADK separates itself from most frameworks. Safety is not an add-on. It is built into the agent lifecycle with two callback hooks.
Input Guardrails — before_model_callback
Intercepts the user’s input before the LLM sees it. Use this for content filtering, injection detection, or policy enforcement:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from google.adk.agents.callback_context import CallbackContext
from google.genai import types
def safety_check(callback_context: CallbackContext,
llm_request: types.GenerateContentConfig) -> None:
"""Block requests that contain prohibited content."""
user_input = llm_request.contents[-1].parts[0].text
blocked_terms = ["hack", "exploit", "bypass security"]
for term in blocked_terms:
if term.lower() in user_input.lower():
# Return a response instead of letting it reach the model
return types.GenerateContentResponse(
text="I cannot assist with that request."
)
return None # Allow the request to proceed
agent = Agent(
name="safe_agent",
model="gemini-flash-latest",
before_model_callback=safety_check,
)
Tool Guardrails — before_tool_callback
Validates tool arguments before execution. Prevents the agent from making unauthorized API calls or accessing restricted data:
1
2
3
4
5
6
7
8
9
10
11
12
13
def validate_tool_args(tool_name: str, args: dict) -> bool:
"""Prevent the agent from querying restricted databases."""
if tool_name == "search_database":
restricted_tables = ["users", "payments", "credentials"]
if args.get("table") in restricted_tables:
return False # Block this tool call
return True # Allow execution
agent = Agent(
name="restricted_agent",
model="gemini-flash-latest",
before_tool_callback=validate_tool_args,
)
This two-layer approach — validate input before the model, validate tool usage before execution — gives you fine-grained control over what the agent can do. In production, this is not optional.
Deployment Options
ADK supports four deployment paths, from fully managed to fully custom.
Agent Runtime (Agent Platform)
Google’s fully managed solution. Auto-scaling, monitoring, and infrastructure handled for you. Best for teams that want zero ops overhead.
Cloud Run
Serverless containers. You package your agent as a Docker container and deploy it. Auto-scales to zero when idle, scales up under load. Most practical option for small teams.
Google Kubernetes Engine (GKE)
Full Kubernetes control. Use this when you need custom model hosting (like running Ollama alongside your agents), complex networking, or multi-region deployment.
Self-Hosted Containers
Package your agent in Docker and run it anywhere — your own servers, AWS, Azure, or a VPS. No Google Cloud dependency required.
The key selling point: your code does not change between environments. The same agent that runs on your laptop with Runner deploys to Cloud Run or GKE without modification.
What Can You Build With ADK
ADK is general-purpose, but here are the use cases where it excels:
Customer support agents — Multi-agent teams where a router agent triages incoming requests and delegates to specialized agents for billing, technical support, and account management. Session state tracks the customer’s history across the conversation.
Research assistants — Agents with web search, document reading, and summarization tools that can independently research a topic and produce structured reports.
Business automation — The same SEO, content, and marketing agents we discussed, but built on a framework that handles deployment, scaling, and safety out of the box.
Retail and e-commerce — Product recommendation agents, inventory checkers, and order tracking agents working as a team. ADK’s sample repository includes a reference retail agent.
Travel planning — Multi-step agents that search flights, hotels, and activities, then coordinate bookings. Another reference implementation in the ADK samples.
Internal developer tools — Agents that review pull requests, generate documentation, run tests, and report results. The tool system makes it easy to integrate with GitHub, Jira, and CI/CD pipelines.
ADK vs Other Frameworks
How does ADK compare to the alternatives?
| Feature | Google ADK | CrewAI | LangGraph | AutoGPT |
|---|---|---|---|---|
| Languages | Python, TypeScript, Go, Java | Python | Python, TypeScript | Python |
| Multi-agent | Native delegation with routing | Role-based crews | Graph-based orchestration | Single autonomous agent |
| Model support | Any (via LiteLLM) | Any (via LiteLLM) | Any | OpenAI-focused |
| Safety | Built-in callbacks | Manual | Manual | Minimal |
| Deployment | Cloud Run, GKE, Agent Runtime | Self-managed | Self-managed | Self-managed |
| Context management | Automatic summarization and filtering | Basic | Manual | Basic |
| Production readiness | High — Google-backed | Medium | Medium | Low |
| Learning curve | Moderate | Low | High | Low |
Use ADK when: you need production deployment, multi-language support, safety guardrails, or Google Cloud integration.
Use CrewAI when: you want the simplest possible multi-agent setup in Python and deployment is not a concern yet.
Use LangGraph when: you need complex branching workflows with conditional logic that goes beyond sequential or parallel patterns.
Getting Started
Here is the fastest path from zero to running agent:
- Install ADK:
pip install google-adk - Get a Gemini API key from Google AI Studio — free tier gives you 1,000 requests per day
- Build a single agent with one tool
- Test it locally with the built-in web interface
- Add a second agent and wire up delegation
- Deploy to Cloud Run when you are ready for production
The official documentation at adk.dev includes full tutorials for multi-tool agents, agent teams with delegation, streaming agents, and sample applications for retail and travel.
ADK is still evolving — Python 2.0 Beta introduced workflows and agent teams, and TypeScript 1.0 just went production-ready. If you are building agents that need to go beyond prototypes and into production, this framework is worth your time.
Start with one agent. Add tools. Add teammates. Deploy. That is the path.