Google's Agent Development Kit (ADK) is a flexible, modular framework for building production-ready AI agents. While optimized for Gemini models, ADK is model-agnostic and supports multi-agent architectures, rich tool ecosystems, and enterprise deployment. Here's how to build agents that actually work.
What Makes ADK Different
Unlike simple chatbot frameworks, ADK is designed for autonomous agents that can plan, reason, use tools, and coordinate with other agents. The framework provides:
- Multi-Agent Architecture: Build hierarchical systems where specialized agents coordinate complex tasks
- Flexible Orchestration: Use SequentialAgent, ParallelAgent, and LoopAgent for deterministic workflows, or LLM-driven dynamic routing
- Rich Tool Ecosystem: Pre-built tools (Search, Code Exec), custom functions, and other agents as tools
- Session & Memory Management: Short-term state within sessions and long-term memory across sessions
- Built-in Evaluation: Test agents against predefined scenarios before deployment
ADK vs Other Agent Frameworks
The AI agent framework landscape has expanded rapidly. Google ADK is one of several production-grade options, each with different strengths. Here is how they compare across the dimensions that matter most when choosing a framework for your project.
| Framework | Language Support | Orchestration Model | Deployment | Best For |
|---|---|---|---|---|
| Google ADK | Python, TypeScript, Go, Java | Sequential / Parallel / Loop + LLM routing | Vertex AI, Cloud Run, Local | Enterprise multi-agent systems |
| OpenAI Agents SDK | Python, Node.js | Handoffs + Guardrails | Self-hosted, Background mode | OpenAI-native tool pipelines |
| LangGraph | Python, JavaScript | Graph-based state machines | LangSmith, Self-hosted | Complex stateful workflows |
| CrewAI | Python | Role-based crew orchestration | Self-hosted | Rapid prototyping multi-agent teams |
Google ADK stands out for its breadth of language support and first-party Google Cloud integration. If your team already uses Vertex AI or Google Cloud, ADK removes significant deployment friction. The framework also supports mixing deterministic and LLM-driven orchestration within the same system, which is rare among alternatives.
OpenAI's Agents SDK is the natural choice if you are already invested in the OpenAI ecosystem, but it locks you into OpenAI models. LangGraph offers the most fine-grained control over agent state transitions, making it ideal for workflows that require explicit state management. CrewAI is the quickest path to a working multi-agent prototype, though it currently lacks the production tooling of ADK or LangGraph.
For enterprise teams that need multi-language support, managed deployment, and the flexibility to combine deterministic pipelines with LLM-driven decision-making, Google ADK is arguably the most complete package available today.
Core ADK Concepts
1. Agents
The fundamental worker unit. ADK supports two types:
- LlmAgent: Uses language models for complex reasoning and natural language understanding
- Workflow Agents: Deterministic controllers (Sequential, Parallel, Loop) for predictable execution
2. Tools
Tools give agents abilities beyond conversation:
- FunctionTool: Wrap any Python/JS function as a tool
- AgentTool: Use other agents as callable tools
- Built-in: Google Search, Code Execution, Database connectors
3. Callbacks
Custom code that runs at specific points—before/after tool calls, on errors, for logging or guardrails.
4. Sessions & State
Each conversation has a Session with Events (message history) and State (working memory). The framework handles this automatically.
Building Your First ADK Agent
Here's a simple agent that can search the web and analyze results:
from google.adk import Agent, FunctionTool
from google.adk.tools import google_search
# Define a custom analysis tool
def analyze_results(results: str) -> str:
"""Analyze search results and extract key insights."""
# Your analysis logic here
return f"Analysis of: {results}"
# Create the agent
research_agent = Agent(
name="research_agent",
model="gemini-2.0-flash",
instructions="""You are a research assistant.
Search for information, analyze results,
and provide concise summaries.""",
tools=[
google_search,
FunctionTool(analyze_results)
]
)
# Run the agent
response = research_agent.run(
"What are the latest developments in AI agents?"
)Multi-Agent Orchestration
The real power of ADK comes from combining multiple specialized agents:
from google.adk import Agent, SequentialAgent, ParallelAgent
# Specialist agents
researcher = Agent(
name="researcher",
model="gemini-2.0-flash",
instructions="Research and gather information",
tools=[google_search]
)
analyst = Agent(
name="analyst",
model="gemini-2.0-flash",
instructions="Analyze data and identify patterns"
)
writer = Agent(
name="writer",
model="gemini-2.0-flash",
instructions="Write clear, engaging reports"
)
# Orchestrate: research -> analyze -> write
pipeline = SequentialAgent(
name="report_pipeline",
agents=[researcher, analyst, writer]
)
# Or run research tasks in parallel
parallel_research = ParallelAgent(
name="multi_topic_research",
agents=[researcher, researcher, researcher] # Different topics
)Dynamic vs Deterministic Orchestration
One of ADK's most powerful design decisions is that it supports both deterministic and dynamic orchestration in the same system. Understanding when to use each pattern is critical for building reliable agent networks.
Deterministic Orchestration
Use SequentialAgent, ParallelAgent, and LoopAgent when you know the execution path in advance. These workflow agents follow a fixed pattern every time, making them predictable, testable, and easy to debug. They are ideal for:
- ETL pipelines where data flows through fixed stages
- Approval workflows with defined steps
- Batch processing where multiple items need identical treatment
- Quality assurance checks that must run in a specific order
LLM-Driven Dynamic Routing
When the execution path depends on the content of a user request or on intermediate results, use an LLM-powered router agent. The router reads the input, decides which specialist agent should handle it, and delegates accordingly. This pattern uses transfer_to_agent for permanent handoffs and escalate_to_agent when you want the original agent to receive the result back.
from google.adk import Agent
# Specialist agents
billing_agent = Agent(
name="billing_agent",
model="gemini-2.0-flash",
instructions="""You handle billing questions.
You can look up invoices, process refunds,
and explain charges.""",
tools=[lookup_invoice, process_refund]
)
technical_agent = Agent(
name="technical_agent",
model="gemini-2.0-flash",
instructions="""You handle technical support.
You can diagnose issues, check system status,
and guide users through troubleshooting.""",
tools=[check_system_status, run_diagnostics]
)
sales_agent = Agent(
name="sales_agent",
model="gemini-2.0-flash",
instructions="""You handle sales inquiries.
You can provide pricing, schedule demos,
and answer product questions.""",
tools=[get_pricing, schedule_demo]
)
# Router agent — LLM decides which specialist to use
router = Agent(
name="customer_router",
model="gemini-2.0-flash",
instructions="""You are a customer service router.
Analyze the customer's request and transfer to
the appropriate specialist:
- billing_agent: for invoices, payments, refunds
- technical_agent: for bugs, outages, how-to
- sales_agent: for pricing, demos, new features
Use transfer_to_agent to hand off the conversation.""",
sub_agents=[billing_agent, technical_agent, sales_agent]
)The key difference between transfer_to_agent and escalate_to_agent matters for your architecture. A transfer is a permanent handoff — the router steps aside and the specialist takes over the conversation. An escalation is temporary — the specialist processes the request and returns the result to the calling agent, which can then continue its own logic. Use transfers for conversational agents and escalations for tool-like sub-tasks.
Combining Both Patterns
In practice, the best ADK systems combine both approaches. A dynamic router might delegate to a specialist agent that internally uses a SequentialAgent pipeline. For example, the billing agent above could run a deterministic sequence: validate the customer identity, look up the invoice, calculate the refund, then process it. The outer routing is dynamic; the inner execution is deterministic.
Real-World Use Cases
1. Customer Service Agent Network
A router agent that triages requests and delegates to specialized agents (billing, technical support, sales). Each specialist has domain-specific tools and knowledge.
2. Research & Analysis Pipeline
Sequential agents that search → extract → analyze → summarize. Perfect for competitive analysis, market research, or due diligence workflows.
3. Automated Testing Agents
Agents that can navigate applications, execute test scenarios, and report issues. Use the code execution tool for automated QA pipelines.
4. Document Processing Workflows
Parallel agents that process multiple documents simultaneously, extract structured data, and aggregate results into reports.
Deployment Options
ADK agents can be deployed in multiple ways:
- Local Development: CLI and Developer UI for testing and debugging
- Vertex AI Agent Engine: Managed, scalable deployment on Google Cloud
- Custom Infrastructure: Integrate into your existing systems via the Runner API
Production Considerations
Moving ADK agents from a prototype to production requires attention to several infrastructure concerns that are easy to overlook during development.
Session Persistence
During development, ADK defaults to InMemorySessionService, which stores all session state in the application process. This works for testing but loses everything on restart. For production, switch to DatabaseSessionService backed by Firestore, Cloud SQL, or another persistent store. This ensures that long-running conversations survive deployments and that session data is available across multiple instances of your agent service.
Monitoring and Tracing
ADK includes built-in event logging that captures every step of an agent's execution: tool calls, LLM invocations, agent transfers, and state changes. In production, export these events to Cloud Logging or a tracing system like OpenTelemetry. This gives you full visibility into why an agent made a particular decision, which is essential for debugging issues that only appear at scale.
Cost Management
Not every agent needs your most capable model. A common pattern is to use a powerful model like gemini-2.5-pro for complex reasoning agents (analysts, planners) and a faster, cheaper model like gemini-2.0-flash for simple routing, formatting, or extraction tasks. ADK makes this straightforward — each agent specifies its own model independently. In a five-agent system, this strategy can reduce LLM costs by 60-70% with no measurable quality loss on the simpler tasks.
Error Handling and Human Escalation
Production agents must handle failures gracefully. Use ADK callbacks to catch tool errors, LLM refusals, and unexpected outputs. Define explicit escalation paths so that when an agent cannot resolve a request after a set number of attempts, it escalates to a human operator with full context. This prevents agents from looping indefinitely or providing incorrect answers when they are unsure.
Rate Limiting and Retry Strategies
When your agents call external APIs — whether Google Search, database queries, or third-party services — implement rate limiting and exponential backoff. ADK's callback system lets you wrap tool calls with retry logic. For high-traffic deployments, add a queue between user requests and agent processing so that sudden spikes do not overwhelm your downstream services or exhaust API quotas.
Best Practices
- Start Simple: Begin with a single agent, add complexity as needed
- Use Evaluation: Create test datasets before deploying to production
- Implement Guardrails: Use callbacks to validate inputs/outputs and prevent harmful behavior
- Monitor & Iterate: Log events, trace execution, and continuously improve agent prompts
- Design for Failure: Agents will make mistakes—build in human escalation paths
Common Mistakes When Building ADK Agents
After working with dozens of agent systems, we see the same mistakes repeatedly. Avoiding these will save you significant debugging time and produce more reliable agents.
1. Giving Agents Too Many Tools
It is tempting to load an agent with every tool it might conceivably need. In practice, agents with more than 8-10 tools start to exhibit decision paralysis — the LLM struggles to select the right tool and sometimes calls the wrong one or hallucinates tool parameters. Keep each agent focused with 3-5 tools. If you need more capabilities, split them across specialized sub-agents and use a router pattern instead.
2. Not Setting Proper Guardrails
An agent without guardrails is a liability. Use ADK's callback system to validate every tool call before execution and every LLM output before it reaches the user. Check for sensitive data leakage, enforce output format constraints, and block actions that exceed the agent's intended scope. A customer service agent should not be able to execute arbitrary code, even if a creative prompt injection tries to make it.
3. Ignoring Evaluation Before Production
ADK includes a built-in evaluation framework for a reason. Create a test suite of at least 20-30 representative scenarios, including edge cases and adversarial inputs, before deploying any agent. Run these evaluations after every prompt change or tool modification. Agents that pass manual testing during development frequently fail on real-world inputs that you did not anticipate.
4. Using Expensive Models for Simple Routing Tasks
A router agent that reads a user message and picks one of four specialists does not need gemini-2.5-pro. Use gemini-2.0-flash or even a smaller model for routing, classification, and formatting agents. Reserve your most capable (and expensive) model for agents that perform complex reasoning, multi-step analysis, or creative generation. This is not just about cost — faster models also reduce latency for the user.
5. Not Implementing Human-in-the-Loop for Critical Decisions
Agents that process refunds, modify database records, send emails, or take any action with real-world consequences should include a human approval step. ADK's callback system makes it straightforward to pause execution at critical points and wait for human confirmation before proceeding. Skipping this for speed during prototyping is fine, but every production agent that takes consequential actions needs a human gate. The cost of one unchecked mistake almost always exceeds the cost of the approval workflow.
Getting Started
ADK is available in Python, TypeScript, Go, and Java. Install via pip and start building:
pip install google-adk # Or for TypeScript npm install @google/adk
Need Help Building AI Agents?
We help businesses architect, build, and deploy production-ready AI agent systems. From single-purpose agents to complex multi-agent networks—we'll guide you through the entire process.
Book a Consultation