ADK basics: build agents¶
In one sentence: the Agent Development Kit (ADK) is a Python framework to build agents from a model, an instruction and tools, and to connect agents in workflows.
The problem it solves: a model alone only writes text. An agent must also do things: call APIs, read data, and work with other agents. ADK runs this loop for you: it gives the model the tools, runs the tool calls that the model asks for, and keeps the history.
The key elements¶
1. Agent¶
An agent is a model, an instruction and (optionally) tools. From
sre_agent/src/sre_agent/sre_workflow.py:
log_correlator = AdkAgent(
name="log_correlator",
model=MODEL,
instruction=LOG_CORRELATOR_INSTRUCTION,
tools=[query_metrics, list_metric_descriptors, analyze_trace_cascade, generate_post_mortem],
)
2. Tool¶
A tool is a plain Python function. ADK reads its type hints and its docstring, and gives the model a description of the tool. When the model asks for the tool, ADK runs the function and gives the result back to the model.
async def query_metrics(filter_expression: str, duration_minutes: int = 15, project_id: str | None = None) -> str:
"""Queries GCP Cloud Monitoring for time series metrics. ..."""
The docstring is the documentation for the model. A bad docstring gives bad tool calls.
3. Model¶
The model is a name ("gemini-3.8-flash") or any BaseLlm object. You can change the model
without a change to the agent. This project has a scripted model, SimulatedLlm
(sre_agent/src/sre_agent/simulated_llm.py), for use without an API key:
MODEL = GEMINI_MODEL if os.environ.get("GEMINI_API_KEY") else SimulatedLlm()
4. Workflow¶
A workflow is a graph of nodes. A node is an agent or a Python function. Edges connect
the nodes. A tuple in edges is a chain: each node gets the output of the node before it.
AdkWorkflow(name="sre_diagnostics_workflow", edges=[(START, trace_analyzer, fetch_telemetry, log_correlator)])
Use a Python function for each step that does not need a model. It is faster, it costs nothing, and it does not make mistakes.
5. Runner, session and events¶
The Runner runs an agent or a workflow. A session keeps the history and a state dictionary. Each run gives events: text, tool calls and tool results.
runner = Runner(node=sre_diagnostics_workflow, app_name="sre_diagnostics", session_service=session_service)
async for event in runner.run_async(user_id="sre_user", session_id=session.id, new_message=msg):
...
6. Session state and output_key¶
An agent with output_key="name" writes its final answer into the session state, under that
name. A later node can read it with ctx.state["name"]. Thus, nodes can share values without
a chain of outputs.
7. Serve the agent: to_a2a()¶
to_a2a(agent, agent_card=...) makes an ADK agent an A2A server. See A2A basics.
Try it¶
uv run workshop/basics/try_adk.py
The script runs the log correlator alone, and shows each event:
🧠 The model asks for a tool: query_metrics({"filter_expression": "metric.type=..."})
🔧 ADK ran query_metrics, and gives the result to the model: '[ { "metric": ...'
💬 The model answers:
## 🔍 Root Cause Analysis ...
📦 Session state after the run: {}
Run it one time without GEMINI_API_KEY (scripted model) and one time with a key (Gemini).
Compare the tool calls.
In the workshop¶
- Step 1 connects the nodes in a workflow.
- Step 2 builds the log correlator: model, instruction and tools.
- Stretch (step 2) passes a value through the session state with
output_key.