02/Google Cloud
2026-10-01//20 MIN READ

Understanding Google Agent Development Kit (ADK): A Beginner-to-Intermediate Guide with Agents CLI

EXECUTIVE ABSTRACT // 05:30 WIB BRIEF

A practical beginner-to-intermediate engineering guide to Google Agent Development Kit (ADK) and Agents CLI (google-agents-cli): core primitives, Dialogflow CX mental model mapping, stateful Python tools, multi-agent orchestration, real-time Gemini Live voice streaming, and official codelabs.

DP
Doddi PriyambodoSolutions Consultant, Google Cloud SEA
Enterprise Architecture Blueprint
Understanding Google Agent Development Kit (ADK): A Beginner-to-Intermediate Guide with Agents CLI
FIG. 01 // ARCHITECTURAL DISPATCH PLATE2026-10-01 • BICARA IT

Understanding Google Agent Development Kit (ADK): A Beginner-to-Intermediate Guide with Agents CLI

TL;DR: Google Agent Development Kit (ADK) is Google's open-source, code-first framework (available in Python, TypeScript, Go, and Java) for building, evaluating, and deploying production AI agents—scaling smoothly from a single tool-calling assistant to hierarchical multi-agent systems. Paired with Agents CLI (google-agents-cli), developers can scaffold a working prototype in seconds (agents-cli scaffold create), test interactively in a local web debugger (agents-cli playground), grade multi-turn behavior (agents-cli eval run), and deploy to Cloud Run or Vertex AI Agent Engine with a single command. This guide walks you from beginner fundamentals to intermediate multi-agent orchestration—and shows how visual state-machine concepts from Dialogflow CX map cleanly into Python code.


1. What Is Google Agent Development Kit (ADK)?

If you have built conversational bots, customer support voicebots, or internal AI assistants over the past few years, you have almost certainly encountered two architectural extremes:

  1. Raw Prompt-Loop Scripts: Calling an LLM API directly inside a while loop. These prototypes are fast to demo on a laptop, but they quickly become fragile when your application needs strict business rules, repeatable multi-step diagnostic workflows, deterministic parameter validation, or shared session memory across turns.
  2. Visual Drag-and-Drop Flow Builders: Platforms like Dialogflow CX excel at structured visual state machines, intent routing, and contact-center telephony integrations. However, as an engineering team scales a bot across dozens of interconnected domains—combining technical diagnostics, product add-ons, billing inquiries, and multi-function Cloud Run webhooks—visual canvases can become challenging to diff in Git, unit-test in CI/CD pipelines, or orchestrate dynamically when a user switches topics mid-conversation.

Google Agent Development Kit (ADK) bridges that gap by treating agent development as standard software engineering. Instead of wiring visual nodes by hand or writing brittle prompt wrappers, you define agents, typed Python tools, deterministic workflow controllers, and safety callbacks directly in version-controlled code. You test them locally with pytest and automated trajectory evaluators, and deploy them as standard containers on Google Cloud Run, Google Kubernetes Engine (GKE), or Vertex AI Agent Engine.

The 6 Core Primitives Every Beginner Should Know

Before writing a single line of code, you only need to learn six foundational primitives from the official ADK architecture:

  1. Agent (LlmAgent vs. Workflow Agents):
    • LlmAgent (aliased as Agent): The core reasoning worker powered by a Gemini model (such as gemini-2.5-flash or gemini-2.5-pro). You give it a clear name, description, system instruction, and a list of tools or sub_agents. It uses the model to interpret user intent, call tools, and collaborate with other agents.
    • Workflow Agents (SequentialAgent, ParallelAgent, LoopAgent): Deterministic execution controllers that do not use an LLM to decide which step runs next. A SequentialAgent runs sub-agents in a strict, guaranteed order (Step 1 $\rightarrow$ Step 2 $\rightarrow$ Step 3); a ParallelAgent executes independent sub-agents concurrently; and a LoopAgent repeats a step until an explicit exit condition is met.
  2. Tool (FunctionTool, AgentTool, MCPToolset, OpenAPIToolset):
    • Tools give agents capabilities beyond conversation—allowing them to query REST or gRPC APIs, inspect databases, search enterprise knowledge bases via VertexAiSearchTool, or connect to Model Context Protocol (MCPToolset) servers. In Python, any standard function with type hints and a clear docstring is automatically wrapped as a FunctionTool.
  3. Session & State (ToolContext.state):
    • Every conversation is tracked by a SessionService (InMemorySessionService for local prototyping or VertexAiSessionService for managed cloud persistence). Inside any tool or callback, tool_context.state exposes a mutable dictionary that persists across turns and across all sub-agents in the session.
  4. Callbacks (before_model_callback, before_tool_callback, after_agent_callback):
    • Lightweight Python hooks that run at exact lifecycle checkpoints. You use callbacks to enforce security policies, block unauthorized tool arguments before a backend API is ever called, or emit structured telemetry after a turn completes.
  5. Event:
    • The immutable record of every action that occurs during a session—whether a user message, a model thought, a tool invocation, a state modification (state_delta), or a final agent reply.
  6. Runner (Runner.run_async & Runner.run_live):
    • The runtime engine that binds your root_agent and SessionService together, drives the event loop, executes tool calls, commits state changes, and streams text or bidirectional audio back to your application.

Advertisement

2. The Mental Model Bridge: From Visual Flows (Dialogflow CX) to Code-First ADK

In a recent architecture session with a senior conversational AI engineer who operates a large production contact-center voicebot in Dialogflow CX—spanning multi-step broadband diagnostics, travel pass activations, billing inquiries, and live human agent handovers—the first question on the table was practical:

"How do the Dialogflow CX concepts my team already knows—Flows, Pages, Form Parameters, Route Conditions, Cloud Run Webhooks, Playbooks, Barge-In, and Live Agent Handover—translate into Google ADK?"

First, it helps to clarify when to use which tool. Dialogflow CX and Google Cloud Customer Engagement Suite (CES) Agent Studio remain an ideal choice when cross-functional conversation designers want a visual canvas with turnkey contact-center telephony integrations. You choose Google ADK when your engineering team wants a code-first architecture: modular Python or TypeScript repositories, clean Git pull requests, zero webhook JSON boilerplate, dynamic multi-agent delegation, and automated unit + trajectory testing in CI/CD.

If you already understand visual state machines, you already understand 80% of ADK. Here is the exact 1-to-1 architectural translation table:

Conversational AI / Dialogflow CX Concept Google ADK Equivalent How It Works in Code
Agent & Default Start Flow Root Coordinator (root_agent: LlmAgent) Exported from app/agent.py. Greets the user, maintains high-level conversation flow, and delegates domain tasks to specialist sub-agents.
Domain Flows & Sub-Flows (e.g., Diagnostics, Add-On Passes, Billing) Multi-Agent Hierarchy (sub_agents=[...] or AgentTool) Each domain lives in its own focused LlmAgent module with scoped instructions and domain-specific tools, keeping prompts small and accurate.
Strict Sequential Diagnostic Flows (e.g., L1 $\rightarrow$ L2 $\rightarrow$ L3 Line Checks) Workflow Agents (SequentialAgent, LoopAgent, ParallelAgent) Enforces deterministic execution order across sub-agents without relying on an LLM to remember which diagnostic step comes next.
Pages, Form Parameters & Conditional Routes (e.g., $session.params.outage_checked = true) ToolContext.state + Python Guard Clauses Tools read and write tool_context.state["outage_checked"] directly and enforce prerequisites using standard Python if/else checks.
Multi-Function Cloud Run Webhooks (Parsing WebhookRequest / sessionInfo.parameters) Native Python FunctionTool / MCPToolset / OpenAPIToolset Standard typed Python functions (def check_modem(account_id: str, tool_context: ToolContext) -> dict:) called in-process with zero JSON serialization boilerplate.
Task Playbooks & Vertex AI Search Data Stores LlmAgent System Instructions + VertexAiSearchTool Pairs natural-language agent instructions with grounded retrieval over enterprise documentation in Vertex AI Search.
Voice Barge-In, endpointerSensitivity & Streaming Audio Runner.run_live() + LiveRequestQueue + Gemini Live API Streams native bidirectional audio over WebSockets with server-side Voice Activity Detection (VAD) and instant interrupted=True audio buffer flushing.
Live Agent Handover Page + Custom Summary Payload Escalation FunctionTool + tool_context.actions.escalate = True Writes a structured JSON summary into tool_context.state["handover_payload"] and sets tool_context.actions.escalate = True so the host application transfers the caller.

3. Level 1 (Beginner): Building Your First Stateful ADK Agent in Python

To see how clean ADK is for beginners, let's build a complete, runnable single-agent application (app/agent.py) that helps a customer troubleshoot their home internet connection.

In Dialogflow CX, preventing a bot from rebooting a customer's router before checking for a neighborhood outage requires wiring separate Pages, Form Parameters, and Conditional Transition Routes. In ADK, as demonstrated in the Build a Multi-Tool Agent tutorial, you simply write plain Python functions that read and write tool_context.state:

# app/agent.py
from google.adk.agents import LlmAgent
from google.adk.tools import ToolContext


def check_area_outage(account_id: str, tool_context: ToolContext) -> dict:
    """Step 1: Checks whether a regional network outage affects the customer's account.

    Args:
        account_id: The customer's broadband account ID (for example, 'ACC-1042').
    """
    # Persist the verified account and diagnostic state in session memory
    tool_context.state["account_id"] = account_id
    tool_context.state["outage_checked"] = True
    tool_context.state["active_outage"] = False

    return {
        "status": "ok",
        "account_id": account_id,
        "active_outage": False,
        "message": "No regional network outage detected for this area.",
    }


def check_modem_telemetry(tool_context: ToolContext) -> dict:
    """Step 2: Queries optical signal levels and packet loss from the customer's modem."""
    if not tool_context.state.get("outage_checked"):
        return {
            "status": "blocked_precondition",
            "action_required": "You MUST call check_area_outage first before querying modem telemetry.",
        }

    if tool_context.state.get("active_outage"):
        return {
            "status": "skipped_due_to_outage",
            "message": "Regional outage is active; individual modem diagnostics are unnecessary.",
        }

    tool_context.state["telemetry_checked"] = True
    tool_context.state["optical_rx_dbm"] = -19.4
    return {
        "status": "ok",
        "optical_rx_dbm": -19.4,
        "packet_loss_pct": 4.2,
        "recommendation": "Optical signal is healthy (-19.4 dBm), but packet loss is elevated. Remote reboot recommended.",
    }


def trigger_remote_reboot(tool_context: ToolContext) -> dict:
    """Step 3: Sends a remote restart command to the customer's modem to clear packet loss."""
    if not tool_context.state.get("outage_checked") or not tool_context.state.get("telemetry_checked"):
        return {
            "status": "blocked_precondition",
            "action_required": "Cannot reboot modem until BOTH check_area_outage and check_modem_telemetry have completed.",
        }

    tool_context.state["reboot_triggered"] = True
    return {
        "status": "reboot_initiated",
        "account_id": tool_context.state.get("account_id"),
        "estimated_recovery_seconds": 90,
    }


root_agent = LlmAgent(
    name="broadband_support_assistant",
    model="gemini-2.5-flash",
    description="Technical support assistant that diagnoses internet connectivity step by step.",
    instruction=(
        "You are a helpful broadband technical support assistant. "
        "Follow a strict diagnostic sequence: "
        "1) Always check for a regional outage with check_area_outage first. "
        "2) Next, inspect signal health with check_modem_telemetry. "
        "3) Only call trigger_remote_reboot if telemetry was checked and recommends a reboot."
    ),
    tools=[check_area_outage, check_modem_telemetry, trigger_remote_reboot],
)

Why This Pattern Clicks Immediately for Engineers

  1. Zero Schema Boilerplate: ADK inspects your Python type annotations (account_id: str) and docstrings to construct the tool declaration for Gemini automatically.Notice that tool_context: ToolContext is injected automatically by the ADK runtime and hidden from the LLM schema.
  2. Shared Session State (tool_context.state): Every value written to tool_context.state is tracked as a state delta in the session history and remains available on subsequent user turns.
  3. Deterministic Safety Guardrails: Even if an impatient caller says "Just reboot my router right now!", trigger_remote_reboot checks tool_context.state in pure Python and refuses to execute until check_area_outage and check_modem_telemetry have both succeeded.

4. Supercharging Development with agents-cli (google-agents-cli)

While you can create ADK files manually and run adk web, Google provides the Agents CLI (google-agents-cli)—a unified command-line toolkit and AI coding skill bundle documented at google.github.io/agents-cli that streamlines the entire engineering workflow: Scaffold $\rightarrow$ Run & Playground $\rightarrow$ Evaluate $\rightarrow$ Enhance $\rightarrow$ Deploy.

Just as importantly, running uvx google-agents-cli setup installs official ADK development skills directly into AI coding assistants such as Antigravity, Claude Code, and Cursor (Coding with AI guide). This equips your IDE assistant with authoritative knowledge of ADK patterns, evaluation datasets, and Cloud Run / Vertex AI Agent Engine deployment configurations.

flowchart LR
    subgraph Step1["1. Scaffold (Prototype-First)"]
        S1["agents-cli scaffold create my-agent<br/>--agent adk --prototype"]
    end

    subgraph Step2["2. Run & Visual Debug"]
        S2["agents-cli run '...'<br/>agents-cli playground"]
    end

    subgraph Step3["3. Two-Layer Verification"]
        S3["uv run pytest (Unit Tests)<br/>agents-cli eval run (Trajectories)"]
    end

    subgraph Step4["4. Enhance & Deploy"]
        S4["agents-cli scaffold enhance .<br/>agents-cli deploy"]
    end

    Step1 --> Step2 --> Step3 --> Step4

The Prototype-First agents-cli Workflow

A core best practice in agents-cli is prototype-first scaffolding: start with --prototype so you get a clean, minimal directory (app/agent.py, tests/, pyproject.toml) without premature Terraform or CI/CD clutter. Once your agent behaves properly in the local playground, you run agents-cli scaffold enhance to add production deployment files non-destructively.

# 1. Install google-agents-cli and configure ADK skills for your AI IDE
uv tool install google-agents-cli
uvx google-agents-cli setup

# 2. Scaffold a lightweight ADK prototype project
agents-cli scaffold create customer-concierge --agent adk --prototype
cd customer-concierge

# 3. Run a quick single-turn smoke test directly from your terminal
agents-cli run "Check if there is an outage for account ACC-1042"

# 4. Launch the interactive Web Playground (inspect events, tool calls, and session.state live)
agents-cli playground

# 5. Run fast, hermetic unit tests on your deterministic Python tool functions
uv run pytest tests/unit

# 6. Generate an evaluation dataset and grade multi-turn agent trajectories
agents-cli eval generate --agent-module app.agent
agents-cli eval run

# 7. When ready for cloud deployment, layer in Cloud Run or Vertex AI Agent Engine infrastructure
agents-cli scaffold enhance . --deployment-target cloud_run

# 8. Deploy to Google Cloud
agents-cli deploy

How pytest and agents-cli eval Complement Each Other

Engineers moving from visual flow builders often ask how to prevent regressions when updating prompts or adding new tools. agents-cli establishes a clean two-layer testing pyramid:

  • Layer 1 — Deterministic Unit Tests (uv run pytest): Call your Python functions (check_area_outage, trigger_remote_reboot) directly with a mocked or in-memory ToolContext. These tests execute in milliseconds, cost zero LLM tokens, and verify that your precondition guards, data transformations, and error handlers are rock-solid.
  • Layer 2 — Behavioral Trajectory Evaluation (agents-cli eval run): Feeds multi-turn golden test cases into the full ADK Runner and grades two metrics:
    1. Tool Trajectory Score: Did the agent call check_area_outage before check_modem_telemetry?
    2. Response Quality Score (LLM-as-Judge): Did the final response accurately reflect the tool output without hallucinating?

5. Level 2 (Intermediate): Scaling to a Multi-Agent Team

As your assistant grows from a single domain into a full enterprise concierge—handling technical troubleshooting, travel data passes, billing inquiries, and human escalations—putting 25 tools inside a single LlmAgent degrades accuracy and bloats your system prompt.

In ADK, you solve this using the Coordinator + Specialist Sub-Agents pattern taught in the Build an Agent Team tutorial and detailed on the Google Cloud AI Blog. You decompose your application into small, specialized LlmAgent modules and attach them to a root coordinator via sub_agents=[...].

flowchart TB
    subgraph ClientChannels["Caller & Developer Channels"]
        WebPlayground["ADK Web Playground / REST Client"]
        VoiceGateway["Gemini Live Audio Stream<br/>(Runner.run_live + LiveRequestQueue)"]
    end

    subgraph MultiAgentTeam["Google ADK Multi-Agent Hierarchy (app/agent.py)"]
        RootConcierge["Root Coordinator LlmAgent<br/>(support_concierge_root)"]
        DiagnosticsSub["Diagnostics Specialist Agent<br/>(State-Guarded L1-L3 Tools)"]
        AddOnPassSub["Plan & Pass Specialist Agent<br/>(Confirmation-Guarded Tools)"]
        BillingSub["Billing & Contract Specialist Agent<br/>(Invoice Lookup + Grounded Policy RAG)"]
    end

    subgraph SharedRuntime["Shared Session State & Enterprise Handover"]
        SessionStore["SessionService<br/>(Shared ToolContext.state Memory)"]
        EscalationTool["Structured Human Handover Tool<br/>(escalate_to_human_agent)"]
    end

    WebPlayground --> RootConcierge
    VoiceGateway --> RootConcierge

    RootConcierge -->|"Internet / Modem Issues"| DiagnosticsSub
    RootConcierge -->|"Travel Data Passes"| AddOnPassSub
    RootConcierge -->|"Invoices & Contract Renewal"| BillingSub
    RootConcierge -->|"Complex Dispute / Escalation"| EscalationTool

    DiagnosticsSub <--> SessionStore
    AddOnPassSub <--> SessionStore
    BillingSub <--> SessionStore
    EscalationTool <--> SessionStore

Code Walkthrough: Multi-Agent Delegation, Confirmation Guards & Human Handover

Below is an intermediate multi-agent implementation that demonstrates three essential production patterns:

  1. Explicit User Confirmation Guards before executing a billable transaction (activate_travel_pass).
  2. Structured Live Human Agent Handover (escalate_to_human_agent) that packages the session state into a clean JSON summary payload and triggers tool_context.actions.escalate = True.
  3. Hierarchical Sub-Agent Routing where all specialists share the same ToolContext.state.
# app/multi_agent_concierge.py
from google.adk.agents import LlmAgent
from google.adk.tools import ToolContext
from app.agent import (
    check_area_outage,
    check_modem_telemetry,
    trigger_remote_reboot,
)


def activate_travel_pass(
    pass_sku: str,
    customer_confirmed: bool,
    tool_context: ToolContext,
) -> dict:
    """Activates an international travel data pass after explicit user confirmation.

    Args:
        pass_sku: Identifier of the travel pass (e.g., 'ROAM_7D_ASIA').
        customer_confirmed: Set to True ONLY if the user explicitly agreed to the price.
    """
    price_map = {"ROAM_7D_ASIA": 15.0, "ROAM_14D_GLOBAL": 35.0}
    if pass_sku not in price_map:
        return {"status": "error", "message": f"Unknown pass SKU: {pass_sku}"}

    price_usd = price_map[pass_sku]

    # Guardrail: Never charge the customer unless the price was quoted and confirmed
    if not customer_confirmed or tool_context.state.get("quoted_pass_sku") != pass_sku:
        tool_context.state["quoted_pass_sku"] = pass_sku
        return {
            "status": "confirmation_required",
            "pass_sku": pass_sku,
            "price_usd": price_usd,
            "instruction": f"Quote ${price_usd:.2f} for {pass_sku} and ask the user to confirm before activating.",
        }

    tool_context.state["active_travel_pass"] = pass_sku
    return {
        "status": "activated",
        "pass_sku": pass_sku,
        "billed_usd": price_usd,
    }


def lookup_contract_and_balance(account_id: str, tool_context: ToolContext) -> dict:
    """Retrieves current invoice balance and contract end date for an account."""
    tool_context.state["account_id"] = account_id
    return {
        "status": "ok",
        "account_id": account_id,
        "current_balance_usd": 64.50,
        "contract_end_date": "2027-03-15",
        "early_termination_fee_usd": 120.00,
    }


def escalate_to_human_agent(
    reason: str,
    conversation_summary: str,
    tool_context: ToolContext,
) -> dict:
    """Transfers the conversation to a live human specialist with a structured context payload.

    Args:
        reason: Short category code (e.g., 'BILLING_DISPUTE', 'UNRESOLVED_LINE_FAULT').
        conversation_summary: Concise 2-sentence summary of the customer's issue and steps taken.
    """
    handover_payload = {
        "escalation_reason": reason,
        "summary": conversation_summary,
        "account_id": tool_context.state.get("account_id", "UNVERIFIED"),
        "diagnostics_completed": bool(tool_context.state.get("telemetry_checked", False)),
        "reboot_triggered": bool(tool_context.state.get("reboot_triggered", False)),
        "active_travel_pass": tool_context.state.get("active_travel_pass"),
    }
    tool_context.state["handover_payload"] = handover_payload
    # Signal the ADK Runner to stop autonomous execution and hand off to the CCaaS queue
    tool_context.actions.escalate = True
    return {"status": "handover_ready", "handover_payload": handover_payload}


# --- Specialist Sub-Agents ---
diagnostics_specialist = LlmAgent(
    name="diagnostics_specialist",
    model="gemini-2.5-flash",
    description="Diagnoses home internet issues, checks area outages, inspects modem telemetry, and reboots modems.",
    instruction=(
        "Handle all internet connectivity issues. Enforce the strict sequence: "
        "check_area_outage -> check_modem_telemetry -> trigger_remote_reboot."
    ),
    tools=[check_area_outage, check_modem_telemetry, trigger_remote_reboot],
)

travel_pass_specialist = LlmAgent(
    name="travel_pass_specialist",
    model="gemini-2.5-flash",
    description="Quotes and activates international travel data passes.",
    instruction=(
        "Help customers choose and activate travel data passes. Always quote the price "
        "first and wait for explicit confirmation before setting customer_confirmed=True."
    ),
    tools=[activate_travel_pass],
)

billing_contract_specialist = LlmAgent(
    name="billing_contract_specialist",
    model="gemini-2.5-flash",
    description="Answers invoice balance, contract renewal, and billing dispute questions.",
    instruction=(
        "Use lookup_contract_and_balance to answer billing and contract questions. "
        "If the customer wants to dispute a fee or waive an early termination charge, "
        "call escalate_to_human_agent with a complete summary."
    ),
    tools=[lookup_contract_and_balance, escalate_to_human_agent],
)

# --- Root Coordinator Agent ---
root_agent = LlmAgent(
    name="support_concierge_root",
    model="gemini-2.5-flash",
    description="Primary customer support concierge routing across diagnostics, travel passes, and billing.",
    instruction=(
        "You are the primary customer concierge. Delegate internet connectivity issues "
        "to diagnostics_specialist, travel pass requests to travel_pass_specialist, and "
        "billing or contract questions to billing_contract_specialist."
    ),
    sub_agents=[
        diagnostics_specialist,
        travel_pass_specialist,
        billing_contract_specialist,
    ],
    tools=[escalate_to_human_agent],
)

6. Intermediate Voice Pattern: Real-Time Streaming & Barge-In (Runner.run_live)

For engineers building voicebots, ADK's Streaming & Gemini Live API integration replaces the traditional multi-hop Speech-to-Text (STT) $\rightarrow$ Webhook $\rightarrow$ Text-to-Speech (TTS) waterfall with native, low-latency bidirectional audio streaming.

By passing a LiveRequestQueue and a RunConfig into runner.run_live(), your same multi-agent hierarchy can converse in real-time audio and handle caller interruptions (barge-in) automatically:

# app/voice_runner.py
from google.adk.agents.live_request_queue import LiveRequestQueue
from google.adk.agents.run_config import RunConfig, StreamingMode
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
from app.multi_agent_concierge import root_agent


async def stream_voice_conversation(user_id: str, session_id: str):
    session_service = InMemorySessionService()
    await session_service.create_session(
        app_name="voice_concierge",
        user_id=user_id,
        session_id=session_id,
    )

    runner = Runner(
        app_name="voice_concierge",
        agent=root_agent,
        session_service=session_service,
    )

    # Configure native bidirectional audio and Voice Activity Detection (VAD) sensitivity
    run_config = RunConfig(
        streaming_mode=StreamingMode.BIDI,
        response_modalities=["AUDIO"],
        realtime_input_config=types.RealtimeInputConfig(
            automatic_activity_detection=types.AutomaticActivityDetection(
                disabled=False,
                start_of_speech_sensitivity=types.StartSensitivity.START_SENSITIVITY_LOW,
                end_of_speech_sensitivity=types.EndSensitivity.END_SENSITIVITY_LOW,
                silence_duration_ms=500,
            )
        ),
    )

    live_request_queue = LiveRequestQueue()

    async for event in runner.run_live(
        user_id=user_id,
        session_id=session_id,
        live_request_queue=live_request_queue,
        run_config=run_config,
    ):
        # When the caller interrupts mid-sentence, ADK flags event.interrupted = True
        if getattr(event, "interrupted", False):
            print("Caller barged in — flushing outbound telephony audio buffer immediately.")

        # When escalate_to_human_agent sets actions.escalate = True, transfer to CCaaS
        if event.actions and event.actions.escalate:
            session = await session_service.get_session(
                app_name="voice_concierge", user_id=user_id, session_id=session_id
            )
            print("Transferring call with handover payload:", session.state.get("handover_payload"))
            break

7. Real-World Use Cases: Where This Moves the Needle in the Field

Whether you are modernizing a telecommunications voicebot, an e-commerce support assistant, or an internal IT helpdesk, combining ADK's code-first primitives with agents-cli unlocks three high-impact operational patterns:

1. Step-by-Step Hardware Diagnostics Without Premature Actions

  • The Everyday Problem: In purely prompt-driven bots, an LLM may hallucinate diagnostic results or trigger a disruptive device reset before verifying whether a regional outage is active.
  • How It Works in Practice: By storing diagnostic checkpoints (outage_checked, telemetry_checked) in ToolContext.state and validating them at the top of trigger_remote_reboot, Python code—not LLM probability—enforces the exact troubleshooting sequence.
  • The Business & User Impact: Customers receive fast, accurate root-cause diagnostics, and network operations teams eliminate unnecessary hardware reboots during area-wide outages.

2. Multi-Intent Conversations Across Domain Boundaries

  • The Everyday Problem: Real customers rarely call with a single, neatly isolated intent. A caller might start by checking why their home Wi-Fi is slow, then ask to activate a 7-day travel data pass, and finally ask when their contract expires.
  • How It Works in Practice: Instead of trapping the user inside a rigid sub-flow, the root LlmAgent routes each turn to the appropriate specialist (diagnostics_specialist $\rightarrow$ travel_pass_specialist $\rightarrow$ billing_contract_specialist) while keeping tool_context.state["account_id"] shared across the entire session.
  • The Business & User Impact: Callers resolve multiple requests in a single natural conversation without re-authenticating or navigating back to a main menu.

3. Zero-Repeat Warm Handover to Human Specialists

  • The Everyday Problem: Few experiences frustrate customers more than spending five minutes troubleshooting with an automated bot, getting transferred to a human agent, and hearing: "Can I get your account number and how can I help you today?"
  • How It Works in Practice: Calling escalate_to_human_agent snapshots every verified parameter (account_id, diagnostics_completed, reboot_triggered, and a concise 2-sentence summary) into tool_context.state["handover_payload"] and sets tool_context.actions.escalate = True.
  • The Business & User Impact: Contact-center agents see the complete diagnostic history on their screen-pop immediately, cutting average handle time (AHT) and improving first-contact resolution.

8. Official References, Google Cloud Blogs & Easy Codelabs to Follow

Ready to build your first ADK agent? Bookmark this structured learning roadmap of official documentation, architectural blog posts, and progressive hands-on labs:

A. Official Documentation & agents-cli Guides

  1. Agent Development Kit (ADK) Official Documentation (adk.dev) — The canonical reference covering LlmAgent, workflow agents (SequentialAgent, ParallelAgent, LoopAgent), ToolContext.state, callbacks, and session services.
  2. ADK Python Quickstart (adk.dev/get-started/python/) — Install google-adk, configure your Gemini API key or Vertex AI credentials, and run your first agent in under five minutes.
  3. Agents CLI Quickstart (adk.dev/get-started/agents-cli/) & Agents CLI Reference (google.github.io/agents-cli/) — Complete guide to google-agents-cli (scaffold create, run, playground, eval, scaffold enhance, and deploy).
  4. Coding with AI & ADK Docs MCP Server (adk.dev/tutorials/coding-with-ai/) — How to wire uvx google-agents-cli setup and the https://adk.dev/llms.txt MCP server into Antigravity, Cursor, and Claude Code.
  5. Vertex AI Agent Engine Overview (cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/overview) — Production deployment guide for running stateful ADK agents with managed VertexAiSessionService, Memory Bank, and Cloud Trace telemetry.

B. Official Google Cloud Blogs & Architecture Guides

  1. Build Multi-Agent Systems with Google Agent Development Kit (Google Cloud Blog) — Deep architectural overview of why Google created ADK, how hierarchical multi-agent delegation works, and how ADK connects with Model Context Protocol (MCP) and Agent-to-Agent (A2A) ecosystems.
  2. Gemini Enterprise Agent Platform — Build with ADK (docs.cloud.google.com) — How enterprise teams govern, evaluate, and scale ADK agents across Cloud Run, GKE, and managed runtimes.

C. Easy Hands-On Tutorials & Step-by-Step Codelabs

Follow these four progressive labs in order to go from beginner to intermediate in a single afternoon:

  1. Step 1 (Beginner — 15 mins): Build a Multi-Tool Agent (adk.dev/tutorials/multi-tool-agent/) — Create your first Python LlmAgent, attach custom functions as tools, and inspect live execution traces in the Developer UI.
  2. Step 2 (Beginner-to-Intermediate — 30 mins): Build an Agent Team (adk.dev/tutorials/agent-team/) — Build a multi-agent coordinator with specialist sub-agents, persistent ToolContext.state session memory, and before_model_callback / before_tool_callback guardrails.
  3. Step 3 (Intermediate — 25 mins): Build a Streaming Voice & Video Agent (adk.dev/live/get-started/) — Add real-time bidirectional voice streaming and barge-in handling with Runner.run_live().
  4. Step 4 (Self-Paced Google Codelabs & Sample Repository):

Responsible AI Disclosure & Disclaimer

This article is an autonomous dispatch synthesized by DO-AI (the AI Avatar of Doddi Priyambodo), engineered to write in Doddi's first-person architectural voice and mental models. Although all writing passes automated deterministic verification gates, generative AI models can occasionally introduce hallucinations or factual inaccuracies. Readers should always cross-reference official documentation and conduct independent architectural due diligence before relying on this content. This material is published solely for exploratory insights and architectural discussion.

MORNING WIRE SUBSCRIPTION // 05:30 WIBRSS /FEED

Curated Signal for Builders & Architects

Daily news teardowns, Gemini enterprise blueprints, and breakout OSS tools delivered straight to your inbox every morning. Zero spam.

Select Your Editorial Pillars:
Advertisement

Primary References & Citations

DP

Doddi Priyambodo

Author & Curator

Solutions Consultant, Google Cloud Southeast Asia

#ThinkBIG//#StayGRIT//#BeKind

Two decades architecting enterprise data and cloud platforms at Google, AWS, VMware, and IBM. Blending cutting-edge AI engineering with a storyteller's perspective to deliver mission-critical, production-tested blueprints.

Discussion (0)

Markdown formatted • Spam protected
Loading conversation...

Related Deep-Dives & Analysis

View all
#Google ADK#Agents CLI#Dialogflow CX#Vertex AI Agent Engine#Multi-Agent Systems#Gemini Live API
All Dispatches
Found this helpful?
Understanding Google Agent Development Kit (ADK): A Beginner-to-Intermediate Guide with Agents CLI | Bicara IT - Enterprise Cloud Architecture & Safe AI Implementation