You have made it through the fundamentals. You understand what agents are, how they think, how they use tools, how they remember things, and how to evaluate whether they are doing a good job. Now it is time to build one.
In this lesson, we will walk through building a practical agent using Google’s Agent Development Kit (ADK). By the end, you will understand how to set up a project, define an agent, give it tools, test it locally, and even build a small team of agents that work together.
We are going to keep this conceptual and link to the official quickstart for exact code samples - that way you always have up-to-date syntax, and we can focus on the ideas that matter.
Our goal is a practical agent that can:
Think of this as a “hello world” for agents - simple enough to understand in one sitting, but real enough to show how everything connects.
Before you start, make sure you have:
pip install google-adk)Get set up: Follow the official setup guide at ADK Getting Started for detailed installation instructions.
Building your first agent is like assembling a Lego kit. You have a baseplate (the project structure), a minifigure brain (the language model), some tool accessories (search, custom functions), and an instruction manual (system instructions) that tells the minifigure how to behave.
Each piece snaps together in a specific way. The brain decides what to do. The tools let it do things. The instructions keep it focused. And the baseplate holds everything in place so it does not fall apart.
The beautiful thing is that once you understand how the pieces fit, you can swap them out, add more, or rearrange them to build something completely different.
Let us walk through the process of building your first agent. We will cover the concepts at each step and point you to the official quickstart for the exact code.
ADK expects a specific project layout. At its simplest, you need a folder for your agent with two files inside:
my_first_agent/
__init__.py
agent.py
The folder name becomes your agent’s module name. The __init__.py file tells Python this is a package and exports your agent. The agent.py file is where you define the agent itself.
This structure matters because ADK tooling (like adk web and adk eval) discovers your agent by looking for this pattern. Keep it clean and consistent from the start.
Tip: You can also use
adk create my_first_agentto scaffold this structure automatically.
Every ADK agent needs three things at minimum:
Here is what this looks like conceptually:
from google.adk.agents import Agent
my_agent = Agent(
name="my_first_agent",
model="gemini-2.5-flash",
instruction="You are a helpful assistant that answers questions clearly and concisely.",
)
The model parameter determines which Gemini model handles the reasoning. For learning and prototyping, gemini-2.5-flash is a great choice - it is fast and cost-effective. For more complex reasoning tasks, you might upgrade to gemini-2.5-pro.
The instruction parameter is your agent’s system prompt. This is where you define its personality, capabilities, and boundaries. We will cover how to write good instructions later in this lesson.
Tools are what separate an agent from a chatbot. Let us give our agent a custom function it can call.
A tool in ADK is simply a Python function with a clear docstring. The docstring matters because ADK uses it to tell the model what the tool does and when to use it.
def get_weather(city: str) -> dict:
"""Get 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 a real agent, this would call a weather API
# For now, return mock data
return {
"city": city,
"temperature": "72F",
"conditions": "Sunny",
}
Key things to notice:
city: str, -> dict) help the model understand what parameters to pass and what to expect backYou then attach the tool to your agent:
my_agent = Agent(
name="my_first_agent",
model="gemini-2.5-flash",
instruction="You are a helpful assistant. Use the get_weather tool when asked about weather.",
tools=[get_weather],
)
ADK comes with several built-in tools. One of the most useful is Google Search grounding, which lets your agent search the web for current information.
from google.adk.tools import google_search
my_agent = Agent(
name="my_first_agent",
model="gemini-2.5-flash",
instruction="You are a helpful assistant. Use search for current events and get_weather for weather.",
tools=[get_weather, google_search],
)
Now your agent can both search the web and check the weather. The model decides which tool to use based on the user’s question. Ask about the news and it searches. Ask about the weather and it calls your custom function.
ADK includes a local development server that gives you a web UI to interact with your agent:
adk web
This starts a local server (typically at http://localhost:8000) with a chat interface. You can:
You can also test from the command line:
adk run my_first_agent
This is your fastest feedback loop. Make a change, refresh, test. Repeat until the agent behaves the way you want.
Once your agent is working, you want to make sure it keeps working as you make changes. ADK includes an evaluation framework for this:
adk eval my_first_agent eval_data.json
Evaluation lets you define test cases - pairs of inputs and expected behaviors - and automatically check whether your agent handles them correctly. This is the agent equivalent of unit testing.
We covered evaluation concepts in depth in Lesson 9. The key idea here is to start writing eval cases early, even for your first agent. It saves you from regressions later.
Full quickstart: Follow along with the complete code at ADK Quickstart
ADK provides four agent types, each designed for a different kind of task. Picking the right type is like picking the right data structure - it shapes everything that follows.
This is the agent type you will use most often. It uses a language model to make decisions about what to do next.
When to use it:
How it works: The model receives the user’s message, the available tools, and the conversation history. It decides whether to call a tool, ask a clarifying question, or respond directly. This is the ReAct loop in action.
from google.adk.agents import Agent
researcher = Agent(
name="researcher",
model="gemini-2.5-flash",
instruction="You research topics thoroughly using search.",
tools=[google_search],
)
A SequentialAgent runs a fixed list of sub-agents one after another, like a pipeline.
When to use it:
Example: A content creation pipeline where one agent researches, the next writes a draft, and the third edits for grammar and style.
from google.adk.agents import SequentialAgent
pipeline = SequentialAgent(
name="content_pipeline",
sub_agents=[researcher, writer, editor],
)
Analogy: Think of a SequentialAgent like an assembly line in a factory. Each station does one job and passes the result to the next station.
A ParallelAgent runs multiple sub-agents concurrently and collects their results.
When to use it:
Example: Evaluating a piece of code by running a security reviewer, a performance reviewer, and a style reviewer all at the same time.
from google.adk.agents import ParallelAgent
review_team = ParallelAgent(
name="code_review",
sub_agents=[security_reviewer, perf_reviewer, style_reviewer],
)
Analogy: Think of a ParallelAgent like a team brainstorm where everyone works on their part simultaneously and then presents their findings.
A LoopAgent runs its sub-agents in a cycle until a termination condition is met.
When to use it:
Example: A writing agent that drafts content, evaluates it against criteria, and revises until the quality score exceeds a threshold.
from google.adk.agents import LoopAgent
refiner = LoopAgent(
name="iterative_writer",
sub_agents=[drafter, evaluator, reviser],
max_iterations=5,
)
Analogy: Think of a LoopAgent like a code review cycle - you write, get feedback, revise, and repeat until the reviewer approves.
| Agent Type | Use When | Example |
|---|---|---|
| LlmAgent | Flexible reasoning needed | Chatbot, research assistant |
| SequentialAgent | Fixed pipeline of steps | ETL, content creation |
| ParallelAgent | Independent parallel tasks | Multi-reviewer systems |
| LoopAgent | Iterative refinement | Quality improvement loops |
You can also combine these types. A SequentialAgent might have an LlmAgent as one of its steps. A LoopAgent might contain a ParallelAgent inside it. This composability is one of ADK’s strengths.
Learn more: ADK Agent Types
Most real agents need more than one tool. Let us look at how to combine multiple capabilities.
from google.adk.agents import Agent
from google.adk.tools import google_search
def look_up_product(product_id: str) -> dict:
"""Look up product details by ID.
Args:
product_id: The unique product identifier.
Returns:
Product details including name, price, and availability.
"""
# Call your product database/API here
return {"id": product_id, "name": "Widget Pro", "price": 29.99}
def calculate_discount(price: float, discount_percent: float) -> float:
"""Calculate the discounted price.
Args:
price: The original price.
discount_percent: The discount percentage (e.g., 20 for 20%).
Returns:
The price after discount.
"""
return price * (1 - discount_percent / 100)
shopping_agent = Agent(
name="shopping_assistant",
model="gemini-2.5-flash",
instruction="""You are a shopping assistant. You can:
- Search the web for product reviews and comparisons
- Look up specific products in our catalog by ID
- Calculate discounts on prices
Always look up the product first before calculating discounts.""",
tools=[google_search, look_up_product, calculate_discount],
)
The key to multi-tool agents is clear instruction about when to use each tool. Without guidance, the model might search the web when it should query your database, or vice versa.
When building tools for your agent, follow these guidelines:
One tool, one job. Each tool should do one thing well. Do not create a mega-tool that handles five different operations.
Descriptive names and docstrings. The model picks tools based on their names and descriptions. get_order_status is better than fetch_data.
Clear parameter types. Use type hints. The model needs to know whether to pass a string, number, or object.
Graceful error handling. Return helpful error messages instead of crashing. The model can often recover if it understands what went wrong.
Deterministic when possible. Tools that return consistent results for the same inputs are easier for the model to reason about.
Sometimes one agent cannot handle everything. You might need specialists - one agent for research, another for writing, a third for fact-checking. ADK lets you build agent teams with a root agent that delegates to sub-agents.
from google.adk.agents import Agent
# Specialist agents
researcher = Agent(
name="researcher",
model="gemini-2.5-flash",
instruction="You research topics using web search. Return factual findings.",
tools=[google_search],
)
writer = Agent(
name="writer",
model="gemini-2.5-flash",
instruction="You write clear, engaging content based on research findings.",
)
fact_checker = Agent(
name="fact_checker",
model="gemini-2.5-flash",
instruction="You verify claims by searching for supporting evidence.",
tools=[google_search],
)
# Root agent that orchestrates
coordinator = Agent(
name="content_team",
model="gemini-2.5-pro",
instruction="""You coordinate a content creation team. For any content request:
1. Ask the researcher to gather information
2. Ask the writer to create content based on the research
3. Ask the fact_checker to verify key claims
Delegate tasks to your team members and synthesize their work.""",
sub_agents=[researcher, writer, fact_checker],
)
| Approach | Best For | Trade-offs |
|---|---|---|
| One agent, many tools | Tasks where a single reasoning chain works | Simpler, but the agent might struggle with too many tools |
| Multiple sub-agents | Tasks that benefit from specialization | More flexible, but adds coordination overhead |
Rule of thumb: If your single agent has more than 10-15 tools and starts getting confused about which to use, consider splitting into sub-agents with focused tool sets.
Sub-agents in ADK share a session state, which acts as a shared workspace. The root agent can pass context to sub-agents, and sub-agents can store results that other agents can access.
Think of it like a shared document in a team project. The coordinator writes the brief, the researcher adds findings, and the writer uses those findings to draft content.
The system instruction (prompt) is the single most important factor in how your agent behaves. Here are practical guidelines.
Weak:
You are a helpful assistant.
Better:
You are a customer support agent for Acme Corp. You help customers
with order tracking, returns, and product questions. You have access
to the order database and can look up orders by ID or email.
Tell the agent what it should and should not do:
You ONLY handle questions about orders, returns, and products.
For billing questions, tell the customer to contact billing@acme.com.
Never make promises about delivery dates unless the tracking system confirms them.
Never share internal pricing or cost information.
Show the agent how you want it to behave:
When a customer asks about their order status, follow this pattern:
1. Ask for their order ID if they have not provided one
2. Look up the order using the get_order tool
3. Summarize the status in plain language
4. If the order is delayed, apologize and offer to escalate
Example:
Customer: "Where is my order?"
You: "I'd be happy to help track your order. Could you share your order ID? It should start with ORD- and you can find it in your confirmation email."
If you want structured responses, say so:
Always respond in this format:
- Start with a one-sentence summary
- Provide details in bullet points
- End with a suggested next step
| Mistake | Why It Is a Problem | Fix |
|---|---|---|
| Too vague (“be helpful”) | The model has no specific guidance | Define the role, scope, and behavior |
| Too long (2000+ words) | Key instructions get lost in noise | Keep it focused, use structure |
| No tool guidance | The model guesses when to use tools | Explain when each tool is appropriate |
| No error handling | The agent does not know what to do when things fail | Add fallback instructions |
| No boundaries | The agent tries to handle everything | Define what is out of scope |
You do not need a multi-agent system with 10 tools on day one. Start with one agent and one tool. Get that working perfectly before adding complexity.
Many beginners focus on tools and code but write a one-line system instruction. The instruction is your primary lever for controlling agent behavior. Invest time in it.
Your agent is only as reliable as its tools. Test each tool function independently before wiring it into the agent. If get_weather("London") throws an exception, your agent will too.
Tools fail. APIs time out. Data is missing. Your agent needs instructions for what to do when things go wrong. Add error handling in both your tool code and your system instructions.
Not every task needs the most powerful model. For simple routing and tool-calling, a lighter model like Flash works well and saves money. Reserve larger models for tasks that genuinely require complex reasoning.
If you do not have eval cases, you do not know whether your changes improve or break things. Write at least 5-10 test cases before you start iterating on prompts.
Never hardcode API keys or credentials in your agent code. Use environment variables or a secrets manager. This is standard software engineering practice, but it is easy to forget when prototyping.
Here is a mental model for the entire process of building an ADK agent:
1. Define the goal
"What should this agent accomplish?"
|
v
2. Choose the agent type
LlmAgent? Sequential? Parallel? Loop?
|
v
3. Write the system instruction
Role, scope, boundaries, examples
|
v
4. Define the tools
What actions does the agent need?
|
v
5. Wire it together
Agent + model + instruction + tools
|
v
6. Test locally
adk web / adk run
|
v
7. Write eval cases
Input -> expected behavior
|
v
8. Iterate
Improve instructions, add tools, refine
|
v
9. Deploy
Agent Engine or your own infrastructure
Each step feeds the next. And steps 6-8 are a loop - you will go around multiple times before moving to step 9.
| Command | What It Does |
|---|---|
pip install google-adk |
Install ADK |
adk create <name> |
Scaffold a new agent project |
adk web |
Start the local dev server with web UI |
adk run <agent> |
Run an agent from the command line |
adk eval <agent> <data> |
Run evaluation cases against your agent |
adk deploy |
Deploy your agent to Agent Engine |
An ADK agent needs three things: a name, a model, and system instructions. Tools are optional but are what make agents genuinely useful.
Start with LlmAgent. It handles most use cases. Reach for SequentialAgent, ParallelAgent, or LoopAgent only when you have a clear structural reason.
System instructions are your primary control lever. Be specific about the role, set boundaries, provide examples, and include error handling guidance.
Test early and often. Use adk web for interactive testing and adk eval for automated regression checks.
Build incrementally. One agent, one tool, one eval case. Get each piece working before adding the next.
Now that you can build an agent, you need to understand how agents communicate with the wider world. In the next lesson, we will explore two important protocols - MCP and A2A - that let agents talk to tools and to each other using open standards.