3.1 Single-Agent Design, Prompting & ADK Parameters
1. Key Concept Definitions: Inside an ADK LlmAgent
Section titled “1. Key Concept Definitions: Inside an ADK LlmAgent”Before wiring multiple agents together, review the six core configuration primitives of ADK’s fundamental building block—the LlmAgent (also aliased as Agent):
1. description vs. instruction
description is external routing metadata read by parent/coordinator agents to decide task delegation. instruction is read by this agent’s own LLM to govern its reasoning, persona, and tool use.
2. Dynamic {state_key} Templates
Placing
{var_name} inside instruction automatically interpolates session.state[‘var_name’] at runtime. Adding a trailing question mark ({var_name?}) safely ignores missing keys.3. output_schema vs. output_key
output_schema takes a Pydantic
BaseModel to force strict JSON output (disabling tool calls on that agent turn). output_key automatically writes the final output into session.state[output_key].4. include_contents=‘none’
Strips prior conversation history from the model call so a stateless worker or formatting sub-agent processes only its
instruction (including any injected {state_key} variables).5. Built-In & ReAct Planners
Attaching
BuiltInPlanner (with Gemini ThinkingConfig) or PlanReActPlanner instructs the agent to generate an explicit multi-step reasoning plan before calling tools or answering.6. Model Tiering & Transfer Bounds
Pair Gemini Flash (for low-latency routers/extractors) with Gemini Pro (for complex reasoning), and prevent premature handoffs using
disallow_transfer_to_parent / peers.2. Interactive Architecture Decision Engine: Inside an ADK LlmAgent
Section titled “2. Interactive Architecture Decision Engine: Inside an ADK LlmAgent”Switch between the 3 LlmAgent Design Scenarios below and click the 4 stages to inspect how parameters flow through Rosku Bank’s Loan Intake Agent:
3. Visual Parameter Reference Table: ADK LlmAgent Inputs & Outputs
Section titled “3. Visual Parameter Reference Table: ADK LlmAgent Inputs & Outputs”Review this complete Input/Output Parameter Matrix for LlmAgent:
LlmAgent Parameter |
Expected Input Type | Runtime Output / Effect | Core Architecture Rule |
|---|---|---|---|
name |
str (Unique identifier, e.g., "loan_intake_agent") |
Identifies the agent in logs, traces, and transfer calls (transfer_to_agent). |
Must be unique across the agent hierarchy; avoid spaces or special characters. |
description |
str (Capability summary) |
Read by parent/coordinator LLMs to decide task delegation. | Never put internal formatting rules here; put routing capabilities here! |
instruction |
str (Supports {state_var} templates) or Callable |
Guides this agent’s own LLM behavior, persona, and tool usage. | Automatically injects values from session.state when {key} syntax is used. |
model |
str (e.g., "gemini-2.5-flash" or "gemini-2.5-pro") |
Selects the underlying reasoning engine for this specific agent. | Use Flash for low-latency routers/extractors; use Pro for deep reasoning sub-agents. |
tools |
list of Functions, BaseTool, or MCPToolset |
Exposes callable actions to the LLM during its reasoning loop. | LLM uses function docstrings and type hints to decide when and how to call each tool. |
output_schema |
Pydantic BaseModel class |
Forces the final response to conform strictly to a JSON schema. | Important Constraint: Enabling output_schema disables tool calling and agent transfers for that agent! |
output_key |
str (e.g., "dti_result") |
Saves the agent’s final text/JSON output into session.state["dti_result"]. |
Primary mechanism for passing outputs to the next agent in a pipeline! |
include_contents |
'default' or 'none' |
Controls whether prior conversation history is sent to the LLM. | Set to 'none' for stateless worker agents that only need {state_key} inputs to save tokens! |
generate_content_config |
GenerateContentConfig object |
Sets temperature, top_p, max_output_tokens, and safety settings. |
Use temperature=0.0 for deterministic routing and structured data extraction. |
disallow_transfer_to_parent / peers |
bool (True or False) |
Restricts whether the sub-agent can autonomously transfer control back up or sideways. | Set to True when a specialist sub-agent must complete its assigned step without bouncing early. |
planner |
BuiltInPlanner or PlanReActPlanner |
Enables explicit step-by-step reasoning/thinking plans prior to tool execution. | Use BuiltInPlanner(thinking_config=...) for Gemini thinking models or PlanReActPlanner for structured Plan-Act-Observe loops. |
4. Real-World Deep Dive: LlmAgent Parameter Brain-Twisters
Section titled “4. Real-World Deep Dive: LlmAgent Parameter Brain-Twisters”| Architect Question | How It Works Under the Hood in Production |
|---|---|
“Why does an LlmAgent configured with BOTH tools=[credit_check] AND output_schema=LoanJSON fail to call its tool, and how do we solve it?” |
Two-Step Sequential Split: In ADK, setting output_schema constrains the model’s decoding output strictly to that JSON schema, preventing intermediate function-calling turns on that agent. Solve this with a 2-step SequentialAgent: Agent 1 calls credit_check and saves to output_key="raw_credit"; Agent 2 (with no tools and include_contents='none') reads {raw_credit} and applies output_schema=LoanJSON! |
“If we set include_contents='none' on Agent 2 so prior chat history is excluded, how does Agent 2 still receive the data from Agent 1?” |
State Interpolation Still Runs on instruction! Even when include_contents='none' strips the conversation history list, ADK still resolves {raw_credit} placeholders inside Agent 2’s instruction from session.state['raw_credit']—giving Agent 2 the exact structured input it needs at a fraction of the token cost! |
“How do we inject dynamic context into instruction if we do NOT want ADK’s automatic {brace} interpolation to parse literal curly braces (like JSON examples) in our prompt?” |
Pass a Callable InstructionProvider Function: Instead of passing a static str to instruction, pass a Python function def build_instruction(ctx: ReadonlyContext) -> str:. When instruction is a callable function, ADK uses your function’s return string verbatim and skips automatic {brace} parsing! |