Multi-Agenten-Systeme

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

Übersicht der Agenten-Hierarchie

Rendering architecture…

Was Sie erstellen werden

In diesem Leitfaden erstellen Sie ein Kundendienstsystem, bei dem ein Koordinator Anfragen an Spezialisten weiterleitet:

                        ┌─────────────────────┐
       User Query       │                     │
      ────────────────▶ │    COORDINATOR      │
                        │  "Route to expert"  │
                        └──────────┬──────────┘
                                   │
                   ┌───────────────┴───────────────┐
                   │                               │
                   ▼                               ▼
        ┌──────────────────┐            ┌──────────────────┐
        │  BILLING AGENT   │            │  SUPPORT AGENT   │
        │                  │            │                  │
        │  💰 Payments     │            │  🔧 Tech Issues  │
        │  📄 Invoices     │            │  🐛 Bug Reports  │
        │  💳 Subscriptions│            │  ❓ How-To       │
        └──────────────────┘            └──────────────────┘

Schlüsselkonzepte:

  • Koordinator – Empfängt alle Anfragen, entscheidet, wer sie bearbeitet
  • Spezialisten – Fokussierte Agents, die sich in bestimmten Domänen auszeichnen
  • Übergabe – Nahtlose Übergabe vom Koordinator an den Spezialisten

Schnellstart

1. Erstellen Sie Ihr Projekt

cargo new multi_agent_demo
cd multi_agent_demo

Fügen Sie Abhängigkeiten zu Cargo.toml hinzu:

[dependencies]
adk-rust = "2.0.0"
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. Kundendienst-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 die Multi-Agenten-Übergabe funktioniert

Das Gesamtbild

Wenn Sie Sub-Agents zu einem Parent-Agent hinzufügen, erhält der 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 Abrechnungsfrage 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!                  │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

Wie es funktioniert

KomponenteRolle
.sub_agent()Registriert Spezialisten unter dem übergeordneten Element
transfer_to_agent WerkzeugAutomatisch injiziert, wenn Unter-Agents existieren
AgentenbeschreibungenHilft dem LLM zu entscheiden, welcher Agent was bearbeitet
RunnerErkennt Übertragungsereignisse und ruft den Ziel-Agenten auf
Geteilte SitzungZustand und Verlauf bleiben bei Übertragungen erhalten

Vorher vs. Nachher beim 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 ihr Fachgebiet:

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-Agents haben, die einen Baum bilden:

Visuell: 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ändiger Beispielcode

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:

  • "Erstelle einen Blogbeitrag über KI im Gesundheitswesen" → PM → Content Creator → Writer
  • "Recherchiere Elektrofahrzeuge" → PM → Content Creator → Researcher

Sub-Agent-Konfiguration

Fügen Sie Sub-Agents zu jedem LlmAgent mit der sub_agent() Builder-Methode 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 ihre eigenen 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 Transferanweisungen schreiben

Für erfolgreiche Agent-Transfers sind klare Anweisungen und Beschreibungen erforderlich:

Anweisungen für den ü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()?;

Beschreibungen der Sub-Agents

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 Verfahren:

  • Verwenden Sie deskriptive Agent-Namen, die ihren Zweck klar angeben
  • Schreiben Sie detaillierte Beschreibungen – das LLM verwendet diese, um Transfers zu entscheiden
  • Fügen Sie spezifische Schlüsselwörter in Beschreibungen ein, die wahrscheinlichen Benutzeranfragen entsprechen
  • Geben Sie klare Delegationsregeln in den Anweisungen des übergeordneten Agenten an
  • Verwenden Sie konsistente Terminologie in allen Agent-Beschreibungen

Testen Ihres Multi-Agenten-Systems

Beispiele ausführen

cargo run --manifest-path examples/tier_examples/enterprise/Cargo.toml --bin 14-enterprise-multi-agent

Beispiel-Test-Prompts

Kundenservice:

  • "Ich habe eine Frage zu meiner letzten Rechnung" → Should route to billing_agent
  • "Die App stürzt ständig ab" → Should route to support_agent
  • "Wie kann ich meinen Plan upgraden?" → Should route to billing_agent
  • "Hallo, ich brauche Hilfe" → Should stay with coordinator zur Klärung

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?" → Should stay with project_manager

Fehlerbehebung bei Transferproblemen

Wenn Transfers nicht wie erwartet funktionieren:

  1. Agentennamen überprüfen - Müssen in Transfer-Aufrufen exakt übereinstimmen
  2. Beschreibungen überprüfen - Machen Sie sie spezifischer und schlüsselwortreicher
  3. Anweisungen präzisieren - Seien Sie explizit, wann ein Transfer erfolgen soll
  4. Grenzfälle testen - Versuchen Sie mehrdeutige Anfragen, um das Routing-Verhalten zu sehen
  5. Suchen Sie nach Transfer-Indikatoren - [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

  • Globale Anweisung: Wird auf alle Agenten in der Hierarchie angewendet, legt die Gesamtpersönlichkeit/den Kontext fest
  • Agenten-Anweisung: Spezifisch für jeden Agenten, definiert dessen besondere Rolle und Verhalten

Beide Anweisungen sind im Konversationsverlauf enthalten, wobei die globale Anweisung zuerst erscheint.

Dynamische globale Anweisungen

Für fortgeschrittenere Szenarien können Sie einen globalen Anweisungs-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 {variable}-Syntax:

// 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 Sitzungszustand in die Anweisungsvorlagen.

Gängige Multi-Agenten-Muster

Koordinator/Dispatcher-Muster

Ein zentraler Agent leitet Anfragen an spezialisierte Sub-Agenten 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()?;

Beispielkonversation:

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 Koordinator analysiert die Anfrage und übergibt sie an den Abrechnungsagenten
  • Der Abrechnungsagent antwortet sofort im selben Zug
  • Nachfolgende Nachrichten werden mit dem Abrechnungsagenten fortgesetzt
  • Transferindikatoren (🔄) zeigen an, wann Übergaben stattfinden

Hierarchische Aufgabenzerlegung

Mehrstufige Hierarchien zur Zerlegung 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-Agenten

Multi-Agenten-Systeme funktionieren gut mit Workflow-Agenten (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 Agenten

Agenten in einer Hierarchie kommunizieren über einen gemeinsamen Session-Zustand:

// 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-Zustand, wodurch sie für nachfolgende Agenten verfügbar wird.

AgentTool Zustand und Artefakt-Weiterleitung

Bei der Verwendung von AgentTool, um Agenten als Tools zu umschließen, werden Zustandsänderungen und Artefakte von Sub-Agenten automatisch an den übergeordneten Kontext weitergeleitet:

use adk_tool::AgentTool;

// Create a sub-agent that modifies state
let data_processor = LlmAgentBuilder::new("data_processor")
    .instruction("Process the data and save results.")
    .output_key("processed_data")
    .model(model.clone())
    .build()?;

// Wrap as a tool - state_delta and artifact_delta are forwarded
let processor_tool = AgentTool::new(Arc::new(data_processor));

// Parent agent can use the tool and see state changes
let coordinator = LlmAgentBuilder::new("coordinator")
    .instruction("Use the data_processor tool, then access {processed_data}.")
    .model(model.clone())
    .tool(Arc::new(processor_tool))
    .build()?;

AgentTool führt Sub-Agenten intern im Nicht-Streaming-Modus (StreamingMode::None) aus, sodass der Sub-Agent seine vollständige Antwort akkumuliert, bevor er sie an den übergeordneten Agenten zurückgibt. Dies verhindert Probleme, bei denen partielle Streaming-Chunks leere Ergebnisse liefern könnten.

Dies ermöglicht einen nahtlosen Datenfluss zwischen übergeordneten und untergeordneten Agenten bei Verwendung des AgentTool-Musters.

Ausführen von Multi-Agenten-Systemen

Verwenden 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 --manifest-path examples/tier_examples/enterprise/Cargo.toml --bin 14-enterprise-multi-agent

# Use a generated API project when you need HTTP serving
cargo adk new multi_agent_api --template api

Funktionen:

  • Agenten-Indikatoren: Zeigt an, welcher Agent antwortet [Agent: coordinator]
  • Transfer-Visualisierung: Zeigt Transfer-Ereignisse an 🔄 [Transfer requested to: billing_agent]
  • Nahtlose Übergaben: Ziel-Agent antwortet sofort nach der Übergabe
  • 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. Agentennamen überprüfen, die in Klammern erscheinen, wenn sie antworten
  2. Achten Sie auf Transfer-Indikatoren (🔄), 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 Grenzfälle wie die Übergabe an nicht existierende Agenten

Debugging von Transfer-Problemen

Wenn Transfers nicht funktionieren:

  • Überprüfen Sie, ob Sub-Agents hinzugefügt wurden über .sub_agent()
  • Überprüfen Sie die Agent-Beschreibungen – der LLM verwendet diese, um Transfers zu entscheiden
  • Überprüfen Sie die Anweisungen – der übergeordnete Agent sollte erwähnen, wann ein Transfer erfolgen soll
  • Überprüfen Sie die Agent-Namen – müssen in Transfer-Aufrufen exakt übereinstimmen
  • Aktivieren Sie die Protokollierung – um Transfer-Aktionen im Event-Stream zu sehen

Bewährte Verfahren

  1. Klare Beschreibungen: Schreiben Sie aussagekräftige Agentennamen und Beschreibungen, um dem LLM bei guten Transferentscheidungen zu helfen
  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 einen konsistenten 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

Zurück: ← Workflow Agents | Weiter: Graph Agents →