Skip to content
Blog

Building a Dispatcher Agent with Specialized Subagents

Implement dynamic triage and intent-based routing using Google ADK dispatcher agents and specialized subagents for billing, tech support, and beyond.

Published on 2026-07-30

AI Assistant

Real-world user requests rarely follow a single fixed pipeline. In customer support systems, an incoming user query might require processing an invoice refund, resetting an account password, or looking up shipping status.

Rather than giving one giant agent access to dozens of tools and instructions, Google ADK provides the Dispatcher Pattern. In this pattern, a root dispatcher agent acts as an intelligent triage router, classifying incoming intent and delegating execution to specialized subagents.

The Dispatcher Architecture

The root dispatcher agent receives the incoming user message and evaluates the request against its registered subagents:

  1. Intent Classification: The dispatcher analyzes user input against the descriptive roles of available subagents.
  2. Dynamic Delegation: The dispatcher forwards execution to the appropriate subagent.
  3. Isolated Tool Execution: The subagent executes domain tools in its own scoped context.
  4. Response Relay: The subagent returns its output through the dispatcher to the user.
flowchart TD
    A["Customer Dispatcher<br/>(Root Triage Agent)"]

    B["Billing Subagent<br/><hr/>- process_refund tool"]
    C["Tech Support Subagent<br/><hr/>- reset_password tool"]

    A --> B
    A --> C

    classDef orchestrator fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a;
    classDef worker fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#0f172a;

    class A orchestrator;
    class B,C worker;

Architectural Benefits

  • Scoped Tooling: Subagents only see tools relevant to their domain, dramatically reducing tool selection errors.
  • Granular Security & IAM: Sensitive tools (such as refund API credentials) are restricted to the billing agent.
  • Maintainable Codebase: Adding support for a new category (e.g., shipping updates) requires creating a new subagent without modifying existing domain logic.

Recipe: Customer Support Dispatcher System

Below is a complete implementation of a customer service dispatcher harness built with Google ADK Python SDK:

import asyncio
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService

# Domain Tool 1: Billing Refund Logic
def process_refund(invoice_id: str, amount: float) -> dict:
    """Processes a monetary refund for a given customer invoice ID.

    Args:
        invoice_id: The unique invoice identifier string.
        amount: The refund monetary amount in USD.
    """
    return {
        "status": "SUCCESS", 
        "invoice_id": invoice_id, 
        "refunded_amount": amount,
        "message": f"Successfully processed ${amount:.2f} refund for invoice {invoice_id}."
    }

# Domain Tool 2: Tech Support Account Reset Logic
def reset_user_password(username: str) -> dict:
    """Triggers an account password reset link email for a user.

    Args:
        username: The target account username or email address.
    """
    return {
        "status": "RESET_LINK_SENT", 
        "username": username,
        "message": f"Password reset instructions emailed to {username}."
    }

billing_tool = FunctionTool(func=process_refund)
tech_tool = FunctionTool(func=reset_user_password)

# Subagent 1: Specialized Billing Agent
billing_agent = Agent(
    name="billing_agent",
    model="gemini-2.5-flash",
    instruction="You process customer invoice inquiries and monetary refunds using `process_refund`.",
    tools=[billing_tool]
)

# Subagent 2: Specialized Tech Support Agent
tech_support_agent = Agent(
    name="tech_support_agent",
    model="gemini-2.5-flash",
    instruction="You resolve technical account lockouts and password resets using `reset_user_password`.",
    tools=[tech_tool]
)

# Root Dispatcher Agent
dispatcher_agent = Agent(
    name="customer_dispatcher",
    model="gemini-2.5-flash",
    instruction=(
        "You are the customer support triage operator. "
        "Analyze the user's intent and delegate execution to `billing_agent` for financial queries "
        "or `tech_support_agent` for account and technical issues."
    ),
    sub_agents=[billing_agent, tech_support_agent]
)

async def main():
    session_service = InMemorySessionService()
    runner = Runner(agent=dispatcher_agent, session_service=session_service)

    print("--- Scenario 1: Billing Intent ---")
    res1 = await runner.run_async(
        session_id="disp-session-01",
        message="I need a $50 refund for invoice INV-8821."
    )
    print("Dispatcher Output:\n", res1.text)

    print("\n--- Scenario 2: Technical Support Intent ---")
    res2 = await runner.run_async(
        session_id="disp-session-02",
        message="I am locked out of my account for alex@example.com."
    )
    print("Dispatcher Output:\n", res2.text)

if __name__ == "__main__":
    asyncio.run(main())

How ADK Handles Routing Internally

When the root dispatcher agent receives a message, the LLM evaluates the request based on three key elements:

  1. The dispatcher’s system instruction (“delegate to billing_agent or tech_support_agent”)
  2. Each subagent’s name and stated instruction boundaries
  3. The function tools registered on each subagent

ADK manages the context transfer and execution delegation automatically — eliminating manual regex matching or hardcoded if/else intent routing.

Hierarchical Multi-Tier Dispatching

For large enterprise applications, dispatcher agents can be nested hierarchically to create multi-tier organization charts:

Executive Dispatcher
  ├── Customer Support Router
  │   ├── Billing Subagent
  │   ├── Account Support Subagent
  │   └── Returns Subagent
  └── DevOps Operations Router
      ├── Monitoring Subagent
      └── Deployment Subagent

Summary

The Dispatcher Pattern allows you to scale agent applications horizontally. Adding new domain capabilities is as simple as registering a new specialized subagent with dedicated instructions and tools, keeping your codebase clean, modular, and secure.