When you need this. A new developer joins your team and asks, “How do I deploy to staging?” The answer is in the documentation, but finding the right command interrupts someone else. Let’s build a small assistant that explains those commands from a guide.
We will use docuctl, a fictional deployment CLI, as our example throughout this module. You do not need to install it or deploy anything. In this first lesson, the assistant reads a small guide and answers questions. Later lessons add tools, session state and checks around tool execution.
The course uses self-contained docs-assistant labs. Later downloads reuse the domain and selected tools, but each owns its agent configuration and run record; they are not patches that all accumulate in this first app.
How ADK runs the assistant
An Agent is a Python object that specifies a model, instructions and available tools. Defining it does not start a conversation. When you launch the app, ADK’s runtime manages a session, sends your message and the agent’s instructions to Gemini, and returns its response.
Here, Gemini uses a bundled guide to explain docuctl commands. We have configured no tools, so the assistant can describe docuctl deploy but has no way to run that command.
The same agent definition works with terminal chat and ADK’s development Web UI. We will start with the terminal so you can focus on the code.
Create the agent project
You need Python 3.12 or later and a Gemini API key. Download the lab using Download code, extract it, and open its adk-first-agent directory. All commands below run from there.
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
cp docs_assistant/.env.example docs_assistant/.envOn Windows PowerShell, activate with .venv\Scripts\Activate.ps1 and use Copy-Item instead of cp. The supplied requirements.txt pins google-adk==2.12.0.
The project has one agent package:
adk-first-agent/
README.md
requirements.txt
sample-questions.json
test_agent.py
docs_assistant/
__init__.py
agent.py
docuctl.md
.env.exampleEdit the copied docs_assistant/.env and replace the placeholder with your key. ADK loads this file when it loads the agent package.
# Copy to .env, then replace the placeholder with your own Gemini API key.
GOOGLE_GENAI_USE_ENTERPRISE=0
GOOGLE_API_KEY=replace-with-your-key
DOCS_MODEL=gemini-3.8-flashThis configuration selects the Gemini API. Keep .env private; the lab’s .gitignore excludes it. Variables already exported in your shell take precedence, so check those if ADK selects an unexpected backend or model. Sending a chat message calls Gemini through your provider account.
Define the agent
Start with the knowledge the assistant needs. This short guide contains two staging commands and a rollback example:
# docuctl: a fictional deployment CLI
Deploy the service in the current directory to staging:
docuctl deploy --env staging
List staging releases, newest first:
docuctl releases --env staging
Roll production back to release r41 without rebuilding it:
docuctl rollback --env production --to r41
A rollback changes the application release. It does not reverse database migrations.Now define the agent. Python reads the guide beside agent.py, and we include its text in the instruction.
"""Answer developer questions from a small, bundled docuctl guide."""
import os
from pathlib import Path
from google.adk.agents import Agent
from google.genai import types
GUIDE = Path(__file__).with_name("docuctl.md").read_text(encoding="utf-8")
root_agent = Agent(
name="docs_assistant",
model=os.environ.get("DOCS_MODEL", "gemini-3.8-flash"),
description="Explains docuctl commands from the bundled guide.",
instruction=(
"Help a developer use docuctl, a fictional deployment CLI. "
"Answer only from the guide below. Copy commands exactly in backticks. "
"If the guide does not answer the question, say that it does not cover it. "
"Keep the answer under 100 words. Explain commands; do not claim to run them.\n\n"
"<guide>\n" + GUIDE + "\n</guide>"
),
generate_content_config=types.GenerateContentConfig(
max_output_tokens=1024,
thinking_config=types.ThinkingConfig(thinking_level="low"),
),
)The important fields are:
| Field | What it does here |
|---|---|
name |
Identifies this agent as docs_assistant. |
model |
Selects Gemini, with an optional DOCS_MODEL environment override. |
description |
Summarizes the agent’s purpose. The detailed answering rules belong in instruction. |
instruction |
Supplies the guide and asks the model to copy commands, stay concise and admit missing information. |
generate_content_config |
Sets LOW thinking and a 1,024-token output limit. A response can still end before it finishes. |
The whole guide goes into the prompt; there is no document search yet. An instruction guides the model’s answer, so you still need to check the commands it suggests.
Finally, expose the agent module from the package:
from . import agentADK’s loader finds root_agent inside that module. Keep the variable name root_agent even if you change the agent’s name.
An agent name with a hyphen. A name such as docs-assistant raises ValueError when ADK constructs the agent. Use a Python identifier such as docs_assistant.
A missing guide file. Loading the module raises FileNotFoundError if docuctl.md is absent. Keep the guide beside agent.py; the path is relative to that file, not to your terminal’s current directory.
Run it from the terminal
From adk-first-agent, start a conversation:
adk run --in_memory docs_assistant--in_memory keeps this CLI conversation in memory. At the user prompt, enter the practice question:
How do I deploy to staging and list its releases?Compare the response with the guide. It should include docuctl deploy --env staging and docuctl releases --env staging, with a short explanation of each. The wording can vary; the command names and flags should match.
Next, ask a question outside the guide:
How do I configure automatic database backups?The guide says nothing about database backups. The assistant should tell you that the guide does not cover them. If it invents a backup command, you have found an answer-quality failure, even though the program ran successfully.
Here is an illustrative exchange showing the behavior to look for. Your model’s wording can differ.
[user]: How do I deploy to staging and list its releases?
[docs_assistant]: Run `shipctl deploy --env staging` to deploy the service.
Then run `shipctl releases --env staging` to list its releases, newest first.
[user]: How do I configure automatic database backups?
[docs_assistant]: The guide does not cover database backups.Type exit to leave chat.
From a question to an answer
Here is what happens when you ask about staging:
- ADK loads
docs_assistant.agent.root_agent. Importing the module readsdocuctl.mdinto the instruction. - The CLI starts a session, which holds the conversation’s messages.
- ADK sends the instruction and your question to Gemini.
- Gemini generates a response. ADK returns events containing the response, and the CLI prints its text.
ADK builds an LlmRequest for the model. In this example, config.system_instruction contains your instruction and its <guide>...</guide> text, plus an identity instruction built from the agent’s name and description; contents carries the conversation messages. The returned ADK Event identifies the speaker through author and carries response text in content.parts.
With a direct client.models.generate_content() call, your application must assemble the messages and manage its conversation loop. Here, ADK manages that loop and session history and exposes the results as events.
A session holds conversation context; it does not give the model access to your machine. This agent has no shell or deployment tool. The commands in its answer are text for a developer to review.
Try changing the instruction
Change “Keep the answer under 100 words” to “Return a numbered list with one sentence per step.” Restart chat and ask the staging question again. Compare the format while checking that the two commands remain correct.
This separates two decisions: the guide supplies the facts, and the instruction asks for a presentation style. Adding more instructions does not add new facts. When the guide grows beyond a small document, a tool can read the relevant page instead of putting everything into every request.
Open the same app in the Web UI
Use ADK Web when you want a browser conversation and a view of the events. Start it from the same adk-first-agent directory:
adk web --host 127.0.0.1 --port 8000 .Open http://127.0.0.1:8000, select docs_assistant, and ask the staging question. The trailing . tells ADK where to find the agent packages. The Web UI starts its own conversation; it does not continue your CLI session.
Both interfaces load the same agent.py, guide and instructions. Switching interfaces adds no tools or knowledge. In Events, select the assistant response and inspect its event details: author should be docs_assistant, and content.parts should contain the answer text. Open the Request detail for that turn and find the system instruction: look for the internal name docs_assistant and the guide text you included in agent.py. This connects your Python configuration to the actual model request.
Press Ctrl+C in the server terminal when you finish. ADK Web is a development interface.
You do not need to write a Python Runner for this lesson. Use one when your own application must create sessions and process events; that is the next lesson.
Check the app before calling the model
Run the bundled offline checks from adk-first-agent:
python -m unittest -v test_agent.pyThe tests load the real ADK agent, check that the guide reaches its instruction, and exercise the invalid-name and missing-guide failures described above. They do not send messages to Gemini. You still need to compare generated answers with the guide when using the app.
If chat cannot authenticate, check the private .env file and your key’s provider access. If adk is not found, activate the environment where you installed requirements.txt. If the app cannot be found, run the command from the directory containing docs_assistant.
Read the explanation
adk run and adk web are two native interfaces to the same imported ADK agent. Its code and configured tools determine its capabilities.
You now have one agent definition that ADK can load through either interface. Continue with Run an agent and read its event stream to read a documentation page through a tool and handle the response in your own Python application.
References
- ADK Python quickstart: package structure, API key and native run commands.
- ADK LLM agents: agent identity, model and instructions.
- ADK command line: terminal runtime options.