Multi-Agenten-Systeme

Erstellen Sie anspruchsvolle Anwendungen, indem Sie spezialisierte Agents zu Teams zusammenstellen.

Was Sie erstellen werden

In diesem Leitfaden erstellen Sie ein Kundendienstsystem, in dem ein coordinator Anfragen an specialists weiterleitet:

                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       Benutzeranfrage  β”‚                     β”‚
      ────────────────▢ β”‚    COORDINATOR      β”‚
                        β”‚  "An Experten weiterleiten"  β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   β”‚                               β”‚
                   β–Ό                               β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  BILLING AGENT   β”‚            β”‚  SUPPORT AGENT   β”‚
        β”‚                  β”‚            β”‚                  β”‚
        β”‚  πŸ’° Zahlungen    β”‚            β”‚  πŸ”§ Technische Probleme  β”‚
        β”‚  πŸ“„ Rechnungen   β”‚            β”‚  πŸ› Bug-Meldungen  β”‚
        β”‚  πŸ’³ Abonnements  β”‚            β”‚  ❓ Anleitungen   β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Wichtige Konzepte:

  • Coordinator - EmpfΓ€ngt alle Anfragen, entscheidet, wer sie bearbeitet
  • Specialists - Fokussierte Agents, die sich in bestimmten DomΓ€nen auszeichnen
  • Transfer - Nahtlose Übergabe vom coordinator an den specialist

Schnellstart

1. Ihr Projekt erstellen

cargo new multi_agent_demo
cd multi_agent_demo

AbhΓ€ngigkeiten zu Cargo.toml hinzufΓΌgen:

[dependencies]
adk-rust = { version = "0.2", features = ["agents", "models", "cli"] }
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15"

Erstellen Sie .env mit Ihrem API-SchlΓΌssel:

echo 'GOOGLE_API_KEY=your-api-key' > .env

2. Kundenservice-Beispiel

Hier ist ein vollstΓ€ndiges, funktionierendes Beispiel:

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.5-flash")?);

    // Specialist: Billing Agent
    let billing_agent = LlmAgentBuilder::new("billing_agent")
        .description("Handles billing questions: payments, invoices, subscriptions, refunds")
        .instruction("You are a billing specialist. Help customers with:\n\
                     - Invoice questions and payment history\n\
                     - Subscription plans and upgrades\n\
                     - Refund requests\n\
                     - Payment method updates\n\
                     Be professional and provide clear information about billing matters.")
        .model(model.clone())
        .build()?;

    // Specialist: Technical Support Agent
    let support_agent = LlmAgentBuilder::new("support_agent")
        .description("Handles technical support: bugs, errors, troubleshooting, how-to questions")
        .instruction("You are a technical support specialist. Help customers with:\n\
                     - Troubleshooting errors and bugs\n\
                     - How-to questions about using the product\n\
                     - Configuration and setup issues\n\
                     - Performance problems\n\
                     Be patient and provide step-by-step guidance.")
        .model(model.clone())
        .build()?;

    // Coordinator: Routes to appropriate specialist
    let coordinator = LlmAgentBuilder::new("coordinator")
        .description("Main customer service coordinator")
        .instruction("You are a customer service coordinator. Analyze each customer request:\n\n\
                     - For BILLING questions (payments, invoices, subscriptions, refunds):\n\
                       Transfer to billing_agent\n\n\
                     - For TECHNICAL questions (errors, bugs, how-to, troubleshooting):\n\
                       Transfer to support_agent\n\n\
                     - For GENERAL greetings or unclear requests:\n\
                       Respond yourself and ask clarifying questions\n\n\
                     When transferring, briefly acknowledge the customer and explain the handoff.")
        .model(model.clone())
        .sub_agent(Arc::new(billing_agent))
        .sub_agent(Arc::new(support_agent))
        .build()?;

    println!("🏒 Customer Service Center");
    println!("   Coordinator β†’ Billing Agent | Support Agent");
    println!();

    Launcher::new(Arc::new(coordinator)).run().await?;
    Ok(())
}

Beispielinteraktion:

You: I have a question about my last invoice

[Agent: coordinator]
Assistant: I'll connect you with our billing specialist to help with your invoice question.

[Agent: billing_agent]
Assistant: Hello! I can help you with your invoice. What specific question do you have about your last invoice?

You: Why was I charged twice?

[Agent: billing_agent]
Assistant: I understand your concern about the duplicate charge. Let me help you investigate this...

Wie Multi-Agenten-Transfer funktioniert

Das Gesamtbild

Wenn Sie sub-agents zu einem parent agent hinzufΓΌgen, erhΓ€lt das LLM die FΓ€higkeit, Aufgaben zu delegieren:

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    User Message    β”‚                     β”‚
   ─────────────────▢    COORDINATOR      β”‚
                    β”‚                     β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
           "This is a billing question..."
                               β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚                                 β”‚
              β–Ό                                 β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  billing_agent   β”‚              β”‚  support_agent   β”‚
   β”‚  πŸ’° Payments     β”‚              β”‚  πŸ”§ Tech Issues  β”‚
   β”‚  πŸ“„ Invoices     β”‚              β”‚  πŸ› Bug Reports  β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Schritt-fΓΌr-Schritt-Transferfluss

Hier ist genau, was passiert, wenn ein Benutzer eine Frage zur Abrechnung stellt:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 1: User sends message                                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                      β”‚
β”‚   User: "Why was I charged twice on my invoice?"                     β”‚
β”‚                                                                      β”‚
β”‚                              ↓                                       β”‚
β”‚                                                                      β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚   β”‚         COORDINATOR AGENT            β”‚                          β”‚
β”‚   β”‚  Receives message first              β”‚                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 2: LLM analyzes and decides to transfer                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                      β”‚
β”‚   🧠 LLM thinks: "This is about an invoice charge..."                β”‚
β”‚                  "Invoice = billing topic..."                        β”‚
β”‚                  "I should transfer to billing_agent"                β”‚
β”‚                                                                      β”‚
β”‚   πŸ“ž LLM calls: transfer_to_agent(agent_name="billing_agent")        β”‚
β”‚                                                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 3: Runner detects transfer and invokes target                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                      β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”     transfer event      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚   β”‚ Runner  β”‚ ─────────────────────▢  β”‚  billing_agent  β”‚           β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   (same user message)   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚                                                                      β”‚
β”‚   β€’ Runner finds "billing_agent" in agent tree                       β”‚
β”‚   β€’ Creates new context with SAME user message                       β”‚
β”‚   β€’ Invokes billing_agent immediately                                β”‚
β”‚                                                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 4: Target agent responds                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                      β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚   β”‚           billing_agent responds        β”‚                       β”‚
β”‚   β”‚                                         β”‚                       β”‚
β”‚   β”‚  "I can help with your duplicate        β”‚                       β”‚
β”‚   β”‚   charge. Let me investigate..."        β”‚                       β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚
β”‚                                                                      β”‚
β”‚   βœ… User sees seamless response - no interruption!                  β”‚
β”‚                                                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Was es funktioniert macht

ComponentRole
.sub_agent()Registriert Spezialisten unter dem parent agent
transfer_to_agent toolWird automatisch injiziert, wenn sub-agents existieren
Agent descriptionsHelfen dem LLM zu entscheiden, welcher agent was bearbeitet
RunnerErkennt transfer events und ruft den target agent auf
Shared sessionStatus und Verlauf bleiben ΓΌber Transfers erhalten

Vor und nach dem HinzufΓΌgen von sub-agents

Ohne sub-agents – Ein agent erledigt alles:

User ──▢ coordinator ──▢ Response (handles billing AND support)

Mit sub-agents – Spezialisten kΓΌmmern sich um ihren Bereich:

User ──▢ coordinator ──▢ billing_agent ──▢ Response (billing expert)
                    ──▢ support_agent ──▢ Response (tech expert)

Hierarchische Multi-Agenten-Systeme

FΓΌr komplexe Szenarien kΓΆnnen Sie mehrstufige Hierarchien erstellen. Jeder Agent kann seine eigenen Sub-Agenten haben, die einen Baum bilden:

Visualisierung: 3-Stufiges Content-Team

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  PROJECT MANAGER    β”‚  ← Level 1: Top-level coordinator
                    β”‚  "Manage projects"  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  CONTENT CREATOR    β”‚  ← Level 2: Mid-level coordinator  
                    β”‚  "Coordinate R&W"   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚                                 β”‚
              β–Ό                                 β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   RESEARCHER     β”‚              β”‚     WRITER       β”‚  ← Level 3: Specialists
   β”‚                  β”‚              β”‚                  β”‚
   β”‚  πŸ“š Gather facts β”‚              β”‚  ✍️ Write content β”‚
   β”‚  πŸ” Analyze data β”‚              β”‚  πŸ“ Polish text  β”‚
   β”‚  πŸ“Š Find sources β”‚              β”‚  🎨 Style & tone β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Wie Anfragen weitergeleitet werden

User: "Create a blog post about electric vehicles"
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  PROJECT MANAGER: "This is a content task"                  β”‚
β”‚  β†’ transfers to content_creator                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CONTENT CREATOR: "Need research first, then writing"       β”‚
β”‚  β†’ transfers to researcher                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  RESEARCHER: "Here's what I found about EVs..."             β”‚
β”‚  β†’ provides research summary                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

VollstΓ€ndiges Beispiel Code

use adk_rust::prelude::*;
use adk_rust::Launcher;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = Arc::new(GeminiModel::new(&api_key, "gemini-2.5-flash")?);

    // Level 3: Leaf specialists
    let researcher = LlmAgentBuilder::new("researcher")
        .description("Researches topics and gathers comprehensive information")
        .instruction("You are a research specialist. When asked to research a topic:\n\
                     - Gather key facts and data\n\
                     - Identify main themes and subtopics\n\
                     - Note important sources or references\n\
                     Provide thorough, well-organized research summaries.")
        .model(model.clone())
        .build()?;

    let writer = LlmAgentBuilder::new("writer")
        .description("Writes polished content based on research")
        .instruction("You are a content writer. When asked to write:\n\
                     - Create engaging, clear content\n\
                     - Use appropriate tone for the audience\n\
                     - Structure content logically\n\
                     - Polish for grammar and style\n\
                     Produce professional, publication-ready content.")
        .model(model.clone())
        .build()?;

    // Level 2: Content coordinator
    let content_creator = LlmAgentBuilder::new("content_creator")
        .description("Coordinates content creation by delegating research and writing")
        .instruction("You are a content creation lead. For content requests:\n\n\
                     - If RESEARCH is needed: Transfer to researcher\n\
                     - If WRITING is needed: Transfer to writer\n\
                     - For PLANNING or overview: Handle yourself\n\n\
                     Coordinate between research and writing phases.")
        .model(model.clone())
        .sub_agent(Arc::new(researcher))
        .sub_agent(Arc::new(writer))
        .build()?;

    // Level 1: Top-level manager
    let project_manager = LlmAgentBuilder::new("project_manager")
        .description("Manages projects and coordinates with content team")
        .instruction("You are a project manager. For incoming requests:\n\n\
                     - For CONTENT creation tasks: Transfer to content_creator\n\
                     - For PROJECT STATUS or general questions: Handle yourself\n\n\
                     Keep track of overall project goals and deadlines.")
        .model(model.clone())
        .sub_agent(Arc::new(content_creator))
        .build()?;

    println!("πŸ“Š Hierarchical Multi-Agent System");
    println!();
    println!("   project_manager");
    println!("       └── content_creator");
    println!("               β”œβ”€β”€ researcher");
    println!("               └── writer");
    println!();

    Launcher::new(Arc::new(project_manager)).run().await?;
    Ok(())
}

Agenten-Hierarchie:

project_manager
└── content_creator
    β”œβ”€β”€ researcher
    └── writer

Beispiel-Prompts:

  • "Create a blog post about AI in healthcare" β†’ PM β†’ Content Creator β†’ Writer
  • "Research electric vehicles" β†’ PM β†’ Content Creator β†’ Researcher

Sub-Agent-Konfiguration

FΓΌgen Sie Sub-Agents zu jedem LlmAgent mit der Builder-Methode sub_agent() hinzu:

let parent = LlmAgentBuilder::new("parent")
    .description("Coordinates specialized tasks")
    .instruction("Route requests to appropriate specialists.")
    .model(model.clone())
    .sub_agent(Arc::new(specialist_a))
    .sub_agent(Arc::new(specialist_b))
    .build()?;

Wichtige Punkte:

  • Jeder Agent kann mehrere Sub-Agents haben
  • Sub-Agents kΓΆnnen eigene Sub-Agents haben (mehrstufige Hierarchien)
  • Agent-Namen mΓΌssen innerhalb der Hierarchie eindeutig sein
  • Beschreibungen helfen dem LLM zu entscheiden, an welchen Agenten ΓΌbergeben werden soll

Effektive Übergabeanweisungen schreiben

FΓΌr erfolgreiche AgentenΓΌbergaben geben Sie klare Anweisungen und Beschreibungen an:

Anweisungen des ΓΌbergeordneten Agenten

let coordinator = LlmAgentBuilder::new("coordinator")
    .description("Main customer service coordinator")
    .instruction("You are a customer service coordinator. Analyze each request:\n\n\
                 - For BILLING questions (payments, invoices, subscriptions):\n\
                   Transfer to billing_agent\n\n\
                 - For TECHNICAL questions (errors, bugs, troubleshooting):\n\
                   Transfer to support_agent\n\n\
                 - For GENERAL greetings or unclear requests:\n\
                   Respond yourself and ask clarifying questions")
    .model(model.clone())
    .sub_agent(Arc::new(billing_agent))
    .sub_agent(Arc::new(support_agent))
    .build()?;

Sub-Agent-Beschreibungen

let billing_agent = LlmAgentBuilder::new("billing_agent")
    .description("Handles billing questions: payments, invoices, subscriptions, refunds")
    .instruction("You are a billing specialist. Help with payment and subscription issues.")
    .model(model.clone())
    .build()?;

let support_agent = LlmAgentBuilder::new("support_agent")
    .description("Handles technical support: bugs, errors, troubleshooting, how-to questions")
    .instruction("You are a technical support specialist. Provide step-by-step guidance.")
    .model(model.clone())
    .build()?;

BewΓ€hrte Vorgehensweisen:

  • Verwenden Sie deskriptive Agent-Namen, die ihren Zweck klar angeben
  • Schreiben Sie detaillierte Beschreibungen – das LLM verwendet diese, um Übergaben zu entscheiden
  • FΓΌgen Sie spezifische SchlΓΌsselwΓΆrter in Beschreibungen ein, die wahrscheinlich Benutzeranfragen entsprechen
  • Geben Sie klare Delegationsregeln in den Anweisungen des ΓΌbergeordneten Agenten an
  • Verwenden Sie konsistente Terminologie ΓΌber alle Agent-Beschreibungen hinweg

Testen Ihres Multi-Agenten-Systems

Beispiele ausfΓΌhren

# Run the customer service example
cargo run --bin customer_service

# Run the hierarchical example  
cargo run --bin hierarchical

Beispiel-Test-Prompts

Kundenservice:

  • β€žIch habe eine Frage zu meiner letzten Rechnungβ€œ β†’ Sollte an billing_agent weiterleiten
  • β€žDie App stΓΌrzt stΓ€ndig abβ€œ β†’ Sollte an support_agent weiterleiten
  • β€žWie upgrade ich meinen Plan?β€œ β†’ Sollte an billing_agent weiterleiten
  • β€žHallo, ich brauche Hilfeβ€œ β†’ Sollte zur KlΓ€rung beim coordinator bleiben

Hierarchisch:

  • β€žErstelle einen Blogbeitrag ΓΌber KI im Gesundheitswesenβ€œ β†’ PM β†’ Content Creator β†’ Writer
  • β€žRecherchiere die Geschichte von Elektrofahrzeugenβ€œ β†’ PM β†’ Content Creator β†’ Researcher
  • β€žWie ist der Status unserer aktuellen Projekte?β€œ β†’ Sollte beim project_manager bleiben

Fehlerbehebung bei Übergabeproblemen

Wenn Übergaben nicht wie erwartet funktionieren:

  1. Agent-Namen ΓΌberprΓΌfen – MΓΌssen in Übergabeaufrufen exakt ΓΌbereinstimmen
  2. Beschreibungen ΓΌberprΓΌfen – Machen Sie sie spezifischer und reich an SchlΓΌsselwΓΆrtern
  3. Anweisungen klΓ€ren – Seien Sie explizit, wann ΓΌbergeben werden soll
  4. GrenzfΓ€lle testen – Versuchen Sie mehrdeutige Anfragen, um das Routing-Verhalten zu sehen
  5. Achten Sie auf Übergabeindikatoren – [Agent: name] zeigt an, welcher Agent antwortet

Globale Anweisung

Grundlegende Verwendung

let agent = LlmAgentBuilder::new("assistant")
    .description("A helpful assistant")
    .global_instruction(
        "You are a professional assistant for Acme Corp. \
         Always maintain a friendly but professional tone. \
         Our company values are: customer-first, innovation, and integrity."
    )
    .instruction("Help users with their questions and tasks.")
    .model(model.clone())
    .build()?;

Globale vs. Agenten-Anweisung

  • Global Instruction: Wird auf alle Agents in der Hierarchie angewendet, legt die GesamtpersΓΆnlichkeit/den Kontext fest
  • Agent Instruction: Spezifisch fΓΌr jeden Agent, definiert dessen spezielle Rolle und Verhalten

Beide Anweisungen werden in den Konversationsverlauf aufgenommen, wobei die globale Anweisung zuerst erscheint.

Dynamische globale Anweisungen

FΓΌr fortgeschrittenere Szenarien kΓΆnnen Sie einen global instruction provider verwenden, der die Anweisung dynamisch berechnet:

use adk_core::GlobalInstructionProvider;

let provider: GlobalInstructionProvider = Arc::new(|ctx| {
    Box::pin(async move {
        // Access context information
        let user_id = ctx.user_id();
        
        // Compute dynamic instruction
        let instruction = format!(
            "You are assisting user {}. Tailor your responses to their preferences.",
            user_id
        );
        
        Ok(instruction)
    })
});

let agent = LlmAgentBuilder::new("assistant")
    .description("A personalized assistant")
    .global_instruction_provider(provider)
    .model(model.clone())
    .build()?;

Injektion von Zustandsvariablen

Sowohl globale als auch Agenten-Anweisungen unterstΓΌtzen die Injektion von Zustandsvariablen unter Verwendung der Syntax {variable}:

// Set state in a previous agent or tool
// state["company_name"] = "Acme Corp"
// state["user_role"] = "manager"

let agent = LlmAgentBuilder::new("assistant")
    .global_instruction(
        "You are an assistant for {company_name}. \
         The user is a {user_role}."
    )
    .instruction("Help with {user_role}-level tasks.")
    .model(model.clone())
    .build()?;

Das Framework injiziert automatisch Werte aus dem Session-Zustand in die Anweisungsvorlagen.

GΓ€ngige Multi-Agenten-Muster

Koordinator-/Dispatcher-Muster

Ein zentraler Agent leitet Anfragen an spezialisierte Sub-Agents weiter:

let billing = LlmAgentBuilder::new("billing")
    .description("Handles billing and payment questions")
    .model(model.clone())
    .build()?;

let support = LlmAgentBuilder::new("support")
    .description("Provides technical support")
    .model(model.clone())
    .build()?;

let coordinator = LlmAgentBuilder::new("coordinator")
    .instruction("Route requests to billing or support agents as appropriate.")
    .sub_agent(Arc::new(billing))
    .sub_agent(Arc::new(support))
    .model(model.clone())
    .build()?;

Beispiel-Konversation:

User: I have a question about my last invoice

[Agent: coordinator]
Assistant: I'll connect you with our billing specialist.
πŸ”„ [Transfer requested to: billing]

[Agent: billing]
Assistant: Hello! I can help you with your invoice. 
What specific question do you have?

User: Why was I charged twice?

[Agent: billing]
Assistant: Let me investigate that duplicate charge for you...

Wichtige Punkte:

  • Der coordinator analysiert die Anfrage und leitet sie an den billing agent weiter.
  • Der billing agent antwortet sofort in derselben Runde.
  • Nachfolgende Nachrichten werden mit dem billing agent fortgesetzt.
  • Transferindikatoren (πŸ”„) zeigen an, wann Übergaben stattfinden.

Hierarchische Aufgabenzerlegung

Mehrstufige Hierarchien zur AufschlΓΌsselung komplexer Aufgaben:

// Low-level specialists
let researcher = LlmAgentBuilder::new("researcher")
    .description("Researches topics and gathers information")
    .model(model.clone())
    .build()?;

let writer = LlmAgentBuilder::new("writer")
    .description("Writes content based on research")
    .model(model.clone())
    .build()?;

// Mid-level coordinator
let content_creator = LlmAgentBuilder::new("content_creator")
    .description("Creates content by coordinating research and writing")
    .sub_agent(Arc::new(researcher))
    .sub_agent(Arc::new(writer))
    .model(model.clone())
    .build()?;

// Top-level manager
let project_manager = LlmAgentBuilder::new("project_manager")
    .description("Manages content creation projects")
    .sub_agent(Arc::new(content_creator))
    .model(model.clone())
    .build()?;

Kombination mit Workflow-Agents

Multi-Agenten-Systeme funktionieren gut mit Workflow-Agents (Sequential, Parallel, Loop):

use adk_agent::workflow::{SequentialAgent, ParallelAgent};

// Create specialized agents
let validator = LlmAgentBuilder::new("validator")
    .instruction("Validate the input data.")
    .output_key("validation_result")
    .model(model.clone())
    .build()?;

let processor = LlmAgentBuilder::new("processor")
    .instruction("Process data if {validation_result} is valid.")
    .output_key("processed_data")
    .model(model.clone())
    .build()?;

// Combine in a sequential workflow
let pipeline = SequentialAgent::new(
    "validation_pipeline",
    vec![Arc::new(validator), Arc::new(processor)]
);

// Use the pipeline as a sub-agent
let coordinator = LlmAgentBuilder::new("coordinator")
    .description("Coordinates data processing")
    .sub_agent(Arc::new(pipeline))
    .model(model.clone())
    .build()?;

Kommunikation zwischen Agents

Agents in einer Hierarchie kommunizieren ΓΌber einen gemeinsamen session state:

// Agent A saves data to state
let agent_a = LlmAgentBuilder::new("agent_a")
    .instruction("Analyze the topic and save key points.")
    .output_key("key_points")  // Automatically saves output to state
    .model(model.clone())
    .build()?;

// Agent B reads data from state
let agent_b = LlmAgentBuilder::new("agent_b")
    .instruction("Expand on the key points: {key_points}")
    .model(model.clone())
    .build()?;

Die output_key-Konfiguration speichert die endgΓΌltige Antwort eines Agenten automatisch im session state und macht sie so fΓΌr nachfolgende Agents verfΓΌgbar.

AusfΓΌhren von Multi-Agenten-Systemen

Verwendung des Launchers

Der Launcher bietet eine einfache MΓΆglichkeit, Multi-Agenten-Systeme auszufΓΌhren und zu testen:

use adk_rust::Launcher;

let coordinator = /* your multi-agent setup */;

Launcher::new(Arc::new(coordinator))
    .run()
    .await?;

AusfΓΌhrungsmodi:

# Interactive console mode
cargo run --example multi_agent -- chat

# Web server mode with UI
cargo run --example multi_agent -- serve
cargo run --example multi_agent -- serve --port 3000

Funktionen:

  • Agentenanzeigen: Zeigt an, welcher Agent antwortet [Agent: coordinator]
  • Transfer-Visualisierung: Zeigt Transfer-Ereignisse an πŸ”„ [Transfer requested to: billing_agent]
  • Nahtlose Übergaben: Der Ziel-Agent antwortet sofort nach dem Transfer
  • Konversationsverlauf: BehΓ€lt den Kontext ΓΌber Agenten-Transfers hinweg bei

Testen von Transfers

Um zu ΓΌberprΓΌfen, ob Ihr Multi-Agenten-System korrekt funktioniert:

  1. Überprüfen Sie, ob Agentennamen in Klammern erscheinen, wenn sie antworten
  2. Suchen Sie nach Transferindikatoren (πŸ”„), wenn Agenten ΓΌbergeben
  3. Überprüfen Sie sofortige Antworten von Ziel-Agenten ohne erneute Aufforderung
  4. Testen Sie verschiedene Anfragetypen, um eine korrekte Weiterleitung sicherzustellen
  5. Überprüfen Sie RandfÀlle, wie das Übertragen an nicht existierende Agenten

Fehlerbehebung bei Transferproblemen

Wenn Transfers nicht funktionieren:

  • Stellen Sie sicher, dass Sub-Agents hinzugefΓΌgt wurden ΓΌber .sub_agent()
  • ÜberprΓΌfen Sie Agentenbeschreibungen – der LLM nutzt diese, um Transfers zu entscheiden
  • ÜberprΓΌfen Sie Anweisungen – der Parent sollte erwΓ€hnen, wann ein Transfer erfolgen soll
  • ÜberprΓΌfen Sie Agentennamen – diese mΓΌssen in Transferaufrufen exakt ΓΌbereinstimmen
  • Aktivieren Sie Logging, um Transferaktionen im Event-Stream zu sehen

BewΓ€hrte Praktiken

  1. Klare Beschreibungen: Schreiben Sie beschreibende Agentennamen und Beschreibungen, um dem LLM zu helfen, gute Transferentscheidungen zu treffen
  2. Spezifische Anweisungen: Geben Sie jedem Agenten klare, fokussierte Anweisungen fΓΌr seine Rolle
  3. Globale Anweisung verwenden: Legen Sie eine konsistente PersΓΆnlichkeit und Kontext fΓΌr alle Agenten fest
  4. Zustandsverwaltung: Verwenden Sie output_key und Zustandsvariablen fΓΌr die Agentenkommunikation
  5. Hierarchietiefe begrenzen: Halten Sie Hierarchien flach (2-3 Ebenen) fΓΌr bessere Wartbarkeit
  6. Transferlogik testen: Überprüfen Sie, ob Agenten für verschiedene Anfragen an die richtigen Sub-Agents übertragen

Verwandt


Vorheriges: ← Workflow Agents | NΓ€chstes: Graph Agents β†’