# Google ADK Tutorial: Build Your First AI Agent in Python (2026)

> A Google ADK tutorial that fills the setup gap most tutorials skip: go from an empty folder to a running AI agent in Python, with a validation loop and an MCP connection.

*Source: https://www.infowok.com/google-adk-tutorial-build-ai-agent-python/ · Sukhveer Kaur · Published June 20, 2026*

---

You installed Google ADK, opened your terminal, and hit the part every tutorial skips: where does this project actually live, and how does Google ADK find your agent? That gap is why so many first agents never start. This **Google ADK tutorial** closes it — you'll go from an empty folder to a running agent, with the setup gotchas spelled out instead of glossed over.

Most AI agents tutorials skip straight to the code and leave you stuck at the terminal. By the end of this one you'll have a working agent you can chat with in your browser, a version that checks its own work, and one that reaches into an MCP server for real tools.

<Prerequisites>

- You can write a Python function with a docstring and run a terminal command — see the [Python for AI agents primer](/ai-agents-from-scratch-python-part-0/)
- A free Gemini API key from Google AI Studio (no Google Cloud needed to start)
- New to agents? Skim [what an AI agent is](/what-are-ai-agents-complete-guide-2026/) first

</Prerequisites>

<KeyTakeaways>

- **ADK is a code-first Python toolkit:** you write a `root_agent` with an instruction and tools, and ADK runs the loop for you.
- **The setup that actually works:** `uv` for the environment, `adk create` for the layout, a Gemini key in `.env`, then `adk web`.
- **You'll go beyond "hello agent":** a self-correcting validation loop and a live MCP connection, not just a single prompt.

</KeyTakeaways>

## What Google ADK Is — and Where It Fits

Google ADK (Agent Development Kit) is an open-source Python toolkit for building AI agents, and it hit version 2.0 GA in 2026. The idea is simple: you describe an agent as a normal Python object — a name, a model, an instruction, and a list of tools — and **ADK runs the agent loop, the tool calling, and the session state for you.**

![Where Google ADK sits: your agent.py defines a root_agent with an instruction and tools; the ADK runtime handles the agent loop and tool calling; it connects to a Gemini model and to your tools or MCP servers; and adk web gives you a local chat UI](./google-adk-tutorial-build-ai-agent-python-architecture.svg)

That diagram is the whole mental model. You own the box on the left; ADK owns the runtime in the middle. **Where it fits against other frameworks** comes down to taste: ADK is the most opinionated of the popular options, with a built-in dev UI and first-class Gemini support, where [LangGraph, CrewAI, and AutoGen](/langgraph-vs-crewai-vs-autogen-2026/) trade that polish for more control or a different agent model. If you're already in the Google ecosystem, ADK removes the most setup friction. If you want to understand what any of them do underneath, that's a plain Python loop — which is exactly [what an AI agent is](/what-are-ai-agents-complete-guide-2026/) once you strip the framework away.

## Setup That Actually Works

Here is the setup most tutorials rush past. I use `uv` (a fast Python package manager) because it creates the environment and installs in seconds, but plain `pip` works the same way.

```bash
# 1. Create and activate a virtual environment
uv venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate

# 2. Install ADK
uv pip install google-adk
```

You need **Python 3.10 or newer**. With ADK installed, let it scaffold the project for you instead of guessing the layout:

```bash
adk create my_agent
```

![Five setup steps to a running ADK agent: install google-adk in a uv environment, scaffold with adk create, paste your API key into .env, define root_agent with a tool, then run adk web](./google-adk-tutorial-build-ai-agent-python-flow.svg)

That command creates a small package — the layout that trips up beginners:

```text
my_agent/
├── __init__.py     # makes the folder importable; imports the agent
├── agent.py        # your agent lives here, in a variable named root_agent
└── .env            # your API key, loaded automatically
```

Now the one step most guides leave out: the API key. Create a free key in [Google AI Studio](https://aistudio.google.com/apikey), then put it in `my_agent/.env` — inside the package, not next to it:

```bash
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY=your_key_here
```

**ADK loads that `.env` automatically when the agent runs**, so you never call `load_dotenv` yourself. The `USE_VERTEXAI=FALSE` line tells ADK to use the simple AI Studio key path rather than a full Google Cloud project — that one line is the difference between "works in five minutes" and "fights IAM for an hour."

<Callout type="warning" title=".env in the wrong folder fails silently">
If you place `.env` next to `my_agent/` instead of inside it, you won't get a "file not found" error — ADK simply won't find the key and will fall through to default credential lookup. What you'll see is a generic API authentication error (`PermissionDenied` or `INVALID_API_KEY`) with no mention of the `.env` location. The error gives you zero signal that the file is in the wrong place. Move `.env` inside `my_agent/` and it resolves immediately.
</Callout>

<Callout type="note" title="Your IDE doesn't matter">
ADK is a command-line tool. VS Code, PyCharm, or a bare terminal all work identically — the agent runs from the CLI, not from an editor's run button. If a tutorial implies you need a specific IDE, you don't.
</Callout>

## Your First Agent: Instruction, a Tool, and the Web UI

Open `my_agent/agent.py` and replace it with a real agent. A **tool in ADK is just a Python function with a docstring** — ADK reads the docstring and type hints to tell the model what the tool does.

```python
from google.adk.agents import Agent

def get_exchange_rate(base: str, target: str) -> dict:
    """Get the exchange rate between two currencies.

    Args:
        base: The 3-letter code to convert from, e.g. "USD".
        target: The 3-letter code to convert to, e.g. "INR".
    """
    rates = {("USD", "INR"): 83.4, ("USD", "EUR"): 0.92}
    rate = rates.get((base, target))
    if rate is None:
        return {"status": "error", "message": f"No rate for {base} to {target}."}
    return {"status": "success", "base": base, "target": target, "rate": rate}

root_agent = Agent(
    name="currency_agent",
    model="gemini-2.5-flash",
    description="Answers questions about currency exchange rates.",
    instruction="Convert currencies for the user. Always call get_exchange_rate; never invent a rate.",
    tools=[get_exchange_rate],
)
```

Two details matter. The variable **must** be named `root_agent` — that exact name is how ADK discovers your agent. And returning a `dict` with a `status` field is the ADK convention: it gives the model a clean signal for success or failure. Now run the dev UI from the **parent** folder (the one that contains `my_agent`, not inside it):

```bash
adk web
```

Open `http://localhost:8000`, pick `my_agent` from the dropdown, and ask "What's 100 USD in INR?" You'll watch the model call your function and answer **8,340** — and the web UI shows the tool call and its result, which is the fastest way to see what your agent is actually doing.

<Callout type="warning" title="The model name will change">
`gemini-2.5-flash` is cheap and reliable, but it retires on **2026-10-16**, and ADK's new built-in default is `gemini-3-flash-preview`. Set the model explicitly in code so a changed default never silently alters your agent's behavior.
</Callout>

## Add a Validation Loop (an Agent That Self-Corrects)

A single agent answers once. The pattern that makes ADK worth learning is the **`LoopAgent`** — a write → review → fix → repeat loop where one agent produces work and another checks it until it passes. This is how you get output that corrects itself instead of shipping the first draft.

```python
from google.adk.agents import Agent, LoopAgent
from google.adk.tools import ToolContext

def exit_loop(tool_context: ToolContext) -> dict:
    """Call this only when the draft is approved, to stop the loop."""
    tool_context.actions.escalate = True   # signal: we're done
    return {"status": "approved"}

writer = Agent(
    name="writer",
    model="gemini-2.5-flash",
    instruction="Write or revise a one-line product tagline using any feedback in the session.",
    output_key="draft",                    # saves the result into shared state
)

critic = Agent(
    name="critic",
    model="gemini-2.5-flash",
    instruction=(
        "Read the latest draft. If it is punchy and under 10 words, call exit_loop. "
        "Otherwise reply with one concrete improvement."
    ),
    tools=[exit_loop],
)

root_agent = LoopAgent(
    name="tagline_refiner",
    sub_agents=[writer, critic],
    max_iterations=4,
)
```

Here is the mechanism. The `writer` saves its draft to shared session state via `output_key`; the `critic` reads it and either approves or returns a fix; the loop repeats. **The loop ends when the critic calls `exit_loop`** — which sets `escalate = True` — or when `max_iterations` is hit. That `max_iterations` guard is not optional: without it, a critic that's never satisfied loops forever and burns tokens. I cap every loop agent, every time.

The first time I built one of these, I forgot the `output_key` and the critic kept reviewing an empty draft. If your loop behaves strangely, check that each agent is reading and writing the same state key — that's the usual culprit.

## Connect It to MCP Servers

Most ADK tutorials stop right before this step — connecting to MCP servers. Here's that step. **MCP (Model Context Protocol) is a standard way to give an agent prebuilt tools** — file access, GitHub, a database — without writing each integration yourself. If the term is new, the [complete guide to MCP servers](/what-is-mcp-server-complete-guide-2026/) covers the why; here we just plug one in.

ADK connects through `McpToolset`. This example wires in the official filesystem server so your agent can read local files:

```python
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset, StdioServerParameters

filesystem = McpToolset(
    connection_params=StdioServerParameters(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-filesystem", "./project"],
    ),
    tool_filter=["read_file", "list_directory"],   # expose only what you need
)

root_agent = Agent(
    name="file_agent",
    model="gemini-2.5-flash",
    instruction="Help the user read and list files in their project folder.",
    tools=[filesystem],
)
```

The `tool_filter` is the part I'd insist on. An MCP server can expose dozens of tools, and every tool definition costs tokens on every request — so I filter down to the two or three the agent actually needs. Run `adk web` again and your agent can now list and read files, using tools you never had to write.

## Quick Recap

Everything you just built, in five points:

- **Setup:** `uv venv` → `uv pip install google-adk` → `adk create my_agent` → key in `.env` → `adk web`.
- **A tool** is a Python function with a docstring; the agent variable must be `root_agent`.
- **`adk web`** gives you a local chat UI and a live view of every tool call.
- **`LoopAgent`** adds a writer/critic self-correction loop, always capped with `max_iterations`.
- **`McpToolset`** plugs in prebuilt MCP tools — filter them down to save tokens.

## Conclusion

You went from an empty folder to a running Google ADK agent, then added a self-correcting loop and a real MCP connection — the two steps most first tutorials never reach. ADK's job is to handle the plumbing so you spend your time on the instruction and the tools, which is where an agent's quality actually lives.

Before you go, the four mistakes that account for most "it won't run" messages:

- **Agent doesn't appear in `adk web`:** you ran it from inside the package — run it from the parent folder.
- **"Where does the project live?":** anywhere you like, as long as it's a package with `__init__.py` and a `root_agent` in `agent.py`.
- **Key errors:** the `.env` must sit *inside* the agent package, and keep `GOOGLE_GENAI_USE_VERTEXAI=FALSE` for the AI Studio path.
- **Behavior changed overnight:** you didn't pin the model — set `model=` explicitly.

**What's the first tool you'd give your ADK agent — a database query, a web search, a file reader?** Tell me in the comments; I'm collecting the ones people reach for first.

**Read next: [The AI Agent Loop in Python](/ai-agents-from-scratch-python-part-3/)** — build the exact loop ADK runs for you, by hand, so the framework holds no mysteries.

<NextSteps>

- **New to agents?** Start with [What are AI agents?](/what-are-ai-agents-complete-guide-2026/), then the [from-scratch series](/ai-agents-from-scratch-python-part-0/).
- **Understand the runtime:** [build the agent loop by hand](/ai-agents-from-scratch-python-part-3/) that ADK runs for you.
- **Comparing frameworks?** [LangGraph vs CrewAI vs AutoGen](/langgraph-vs-crewai-vs-autogen-2026/) puts ADK's choices in context.

</NextSteps>
