Back
intermediate

Agentic AI Frameworks

Google ADK: build a small tool-using agent

Build an ADK agent around one read-only tool and inspect the difference between tool evidence and an answer.

Lesson 28 of 44About 30 min with practice

Can you make an agent answer a question from a record instead of from memory? We will give Google ADK one small lookup and then deliberately ask something the lookup cannot answer.

Before you begin: Read Agents: who chooses the next step? Know Python functions and environment variables.

Start with the tool's contract

ADK is Google's Agent Development Kit. Its Python agent configuration connects a model, instructions, and tools to a runtime. That runtime manages the interaction; your tool still needs to return honest, well-defined results.

Our fictional catalog contains workshop W1, with a capacity of 12. A lookup can return that record or not_found. It cannot report live remaining seats, because no booking data exists. Naming the field capacity instead of seats_available prevents a misleading inference before the model even sees it.

Before reading the code, predict the answers to “What is W1's capacity?” and “Are there 12 seats left?” They should differ even though both mention 12.

Build the smallest integration

The following is an external integration example reviewed against ADK's official Python quickstart on September 10, 2026. It needs Python 3.10 or later, network access, and a Gemini API account. A paid model call is not claimed as tested here.

In a fresh virtual environment, install google-adk, then run adk create workshop_agent. Keep the generated package files. Configure GOOGLE_API_KEY as described in the quickstart, and set ADK_MODEL to a Gemini model identifier your account can use. Keep keys out of source control.

Replace workshop_agent/agent.py with this complete module:

python
import os
from google.adk.agents.llm_agent import Agent

CATALOG = {"W1": {"title": "Intro to retrieval", "capacity": 12}}

def read_workshop(workshop_id: str) -> dict:
    """Read a fictional workshop's fixed capacity, not remaining seats."""
    record = CATALOG.get(workshop_id)
    if record is None:
        return {"status": "not_found", "workshop_id": workshop_id}
    return {
        "status": "found",
        "workshop_id": workshop_id,
        "record": dict(record),
        "source": "lesson fixture v1",
    }

root_agent = Agent(
    name="workshop_reader",
    model=os.environ["ADK_MODEL"],
    description="Reads a small fictional workshop catalog.",
    instruction=(
        "Use read_workshop for catalog facts. State the workshop ID. "
        "Capacity does not mean remaining seats. "
        "If the record is missing, say it was not found."
    ),
    tools=[read_workshop],
)

From the parent directory, run adk run workshop_agent. Ask the two questions above, then ask about W99. These are test inputs, not promised model outputs. Save the actual tool arguments, tool result, and final answer for comparison. ADK's optional development web interface can help inspect runs; its quickstart explicitly distinguishes it from a production deployment.

Look below the final sentence

There are three separate checks. Did the agent call the intended tool? Did the tool return the right record? Did the answer stay within that record? Passing the second check does not imply the third.

The fixture needs no authentication because it contains invented public data. A real catalog may require per-user access checks inside the data service. A user-supplied workshop ID is not proof of permission. Similarly, a chat session identifier is not a signed-in user identity.

Investigate the misleading answer

Suppose the trace contains a correct capacity of 12 but the final answer says “12 seats are still available.” Which component would you change first?

Compare a useful diagnosis

The lookup is correct; the interpretation is wrong. Keep the clearer field name, strengthen the response contract, and add this case to answer evaluation. If the product needs remaining seats, add an authoritative availability source. Renaming capacity to availability would hide the defect rather than provide the missing data.

For practice, add a second workshop with capacity zero. Ensure the tool distinguishes a found record containing zero from a missing record. Then inspect whether the model preserves that distinction. This is a small experiment you can repeat after changing models or instructions.

Next, implement the same boundary with a different runner. Keeping the task fixed makes the framework differences visible.

Sources

ADK Python quickstart provides the installation, agent entry point, and development commands. ADK sessions describes stateful interaction; verify the selected session service before relying on persistence.

Continue to the next lesson.

Practice for this lesson

Start from the tool contract, not the framework

Build the smallest working agent and look below the final sentence.

About 10 min55 points3 checks and one written task
Loading your lesson progress...