Back to Blog
This post is Part 12 of 13 in the series: AI Architect Foundations

Multi-Agent Architecture: Coordinator and Specialist Agents

Why single monolithic agents degrade under complex toolsets, and how to architect a multi-agent system using the Coordinator + Specialist Subagents pattern in Python.

Share Editorial
Multi-Agent Architecture: Coordinator and Specialist Agents

TL;DR: Giving one single agent 20+ tools and a massive 5-page prompt causes severe performance degradation, hallucinated arguments, and tool confusion. In this guide, we decompose complex workflows using the Coordinator + Specialist Subagents architectural pattern β€” isolating tools, context, and permissions into focused child agents.

πŸ“¦ Interactive Notebook: Test and run this code live on GitHub: 12_multi_agent_design.ipynb in the ai-architect-foundation-gemini repository.


What You'll Learn

Why monolithic agents fail in enterprise environments, how the Coordinator pattern organizes subagents, how to pass task boundaries and context between agents, and how to enforce least-privilege security across agent roles.

diagram
Rendering diagram…

The Monolithic Agent Anti-Pattern

When teams first build AI agents, they typically add every tool to a single model instance:

  • lookup_order
  • cancel_order
  • process_refund
  • query_vector_db
  • create_jira_ticket
  • charge_credit_card
  • send_slack_notification

As the toolset grows beyond 8–10 tools, three failure modes emerge:

  1. Tool Confusion: The model calls cancel_order when it only meant to check status.
  2. Context Bloat & Cost: Tool schema definitions consume thousands of input tokens on every single turn.
  3. Security Risk (Privilege Escalation): An inquiry about store hours could theoretically trigger a payment tool if the prompt gets confused.

The Solution: Coordinator + Specialists Pattern

In real organizations, a customer support tier-1 agent does not perform accounting audits, warehouse logistics, and legal reviews simultaneously. They triage the ticket and coordinate with specialized departments.

We mirror this in software:

  1. The Coordinator: Communicates directly with the user. It breaks down multi-faceted requests into sub-tasks, dispatches work to specialists, and synthesizes the final reply. It has no access to destructive tools.
  2. Specialist Subagents: Focused, stateless agents configured with narrow system instructions and only the 2–3 tools required for their specific domain.

Implementing the Multi-Agent System

python
from google import genai
from google.genai import types

client = genai.Client()
model = "gemini-2.5-flash"

# Helper to execute a specialist subagent
def run_subagent(name: str, system_prompt: str, task: str, tools: list[types.Tool] | None = None) -> str:
    """Executes a specialist agent with isolated context and restricted tools."""
    print(f"\nπŸ€– [Specialist: {name}] Activated with task:\n   -> \"{task}\"")
    
    config = types.GenerateContentConfig(
        system_instruction=system_prompt,
        tools=tools,
        temperature=0.0,
        max_output_tokens=600
    )
    
    response = client.models.generate_content(
        model=model,
        contents=task,
        config=config
    )
    
    finding = response.text or "Completed without text output."
    print(f"πŸ“‹ [Specialist: {name}] Findings:\n   {finding.strip()}")
    return finding

Defining Specialist Agent Configurations

python
# Specialist 1: Logistics & Orders
order_specialist_system = """
You are the Order Logistics Specialist.
Your job is to analyze delivery tracking, shipping carriers, and package condition reports.
Be factual, concise, and report the order state.
"""

# Specialist 2: Billing & Payments
billing_specialist_system = """
You are the Billing & Accounts Specialist.
Your job is to audit payment ledgers, detect duplicate charges, and confirm credit card transaction states.
"""

# Specialist 3: Store Policy & Compliance
policy_specialist_system = """
You are the Store Policy Compliance Officer.
Analyze return requests against company guidelines (30-day window, damage waivers).
State clearly whether the claim is approved or rejected under policy.
"""

The Coordinator Workflow

python
def handle_customer_inquiry(customer_message: str) -> str:
    print(f"πŸ“₯ Received Customer Case: \"{customer_message}\"")
    
    # 1. Step A: Dispatch to Logistics Specialist
    order_findings = run_subagent(
        name="LogisticsAgent",
        system_prompt=order_specialist_system,
        task=f"Customer message: '{customer_message}'. Summarize shipment and delivery facts."
    )
    
    # 2. Step B: Dispatch to Billing Specialist
    billing_findings = run_subagent(
        name="BillingAgent",
        system_prompt=billing_specialist_system,
        task=f"Customer message: '{customer_message}'. Check if there is an apparent duplicate charge or invoice discrepancy."
    )
    
    # 3. Step C: Dispatch to Policy Specialist
    policy_findings = run_subagent(
        name="PolicyAgent",
        system_prompt=policy_specialist_system,
        task=f"Customer message: '{customer_message}'. Findings from logistics: {order_findings}. Does this qualify for replacement/refund?"
    )
    
    # 4. Coordinator Synthesizes Final Customer Response
    coordinator_prompt = f"""
    You are the Customer Support Coordinator.
    Write a helpful, empathetic, and unified response to the customer based on these specialist findings:

    Customer Message: "{customer_message}"
    Logistics Findings: {order_findings}
    Billing Findings: {billing_findings}
    Policy Findings: {policy_findings}

    Provide a clear, single cohesive response addressing all their concerns.
    """
    
    response = client.models.generate_content(
        model=model,
        contents=coordinator_prompt,
        config=types.GenerateContentConfig(temperature=0.2, max_output_tokens=500)
    )
    
    return response.text

Running a Complex Multi-Issue Query

python
case = "Hi, my jacket arrived yesterday with a torn pocket (ORD-77819), and I also see two charges of $149 on my credit card. I want this resolved!"
final_reply = handle_customer_inquiry(case)

print(f"\n================ FINAL CUSTOMER REPLY ================\n{final_reply}")

# --- Execution Output ---
# πŸ€– [Specialist: LogisticsAgent] Activated with task:
#    -> "Customer message: 'Hi, my jacket arrived yesterday...'. Summarize shipment and delivery facts."
# πŸ“‹ [Specialist: LogisticsAgent] Findings:
#    Order ORD-77819 was delivered yesterday. Item: Blue Winter Jacket ($149.00). Torn pocket reported.
#
# πŸ€– [Specialist: BillingAgent] Activated with task:
#    -> "Customer message: 'Hi, my jacket arrived yesterday...'. Check if there is an apparent duplicate charge."
# πŸ“‹ [Specialist: BillingAgent] Findings:
#    Two charges of $149.00 detected. The second transaction appears to be a temporary authorization hold.
#
# πŸ€– [Specialist: PolicyAgent] Activated with task:
#    -> "Customer message: 'Hi, my jacket arrived yesterday...'. Does this qualify for replacement/refund?"
# πŸ“‹ [Specialist: PolicyAgent] Findings:
#    Approved. Damaged items reported within 7 days of delivery qualify for full refund or replacement.
#
# ================ FINAL CUSTOMER REPLY ================
# Dear Customer,
#
# I have investigated both issues regarding your order ORD-77819:
# 1. Torn Pocket (Blue Winter Jacket): Your jacket arrived damaged within the return window,
#    making you eligible for an immediate replacement or full refund.
# 2. Duplicate $149 Charge: The second charge is a pending authorization hold that will
#    expire and drop off your statement within 48 hours.
#
# Would you like me to process a replacement jacket or issue a return label for a full refund?

Architectural Advantages

DimensionMonolithic AgentMulti-Agent Architecture
Tool Selection AccuracyDegrades with >8 toolsHigh (each agent has 2–4 tools max)
Testing & DebuggingDifficult to reproduceEasy (unit test each specialist with mock inputs)
Security & PermissionsAll tools accessible to modelLeast-privilege isolation by role
Latency OptimizationSerial execution onlySubagents can run in parallel via asyncio

Key Takeaways

  1. Decompose by Domain: Group tools by functional boundary (orders, billing, policy) rather than bundling them into one agent.
  2. Isolate Context: Subagents only receive the context required for their specific sub-task.
  3. Single Point of User Contact: The Coordinator manages customer conversation and synthesizes findings into a unified voice.

What's Next

In Part 13: End-to-End Autonomous Support Agent in Production, we bring every foundational concept together into a complete, production-ready enterprise support system.