मल्टी-एजेंट सिस्टम
विशेषीकृत एजेंटों को टीमों में संयोजित करके उन्नत एप्लिकेशन बनाएँ।
एजेंट पदानुक्रम का अवलोकन
आप क्या बनाएँगे
इस गाइड में, आप एक ग्राहक सेवा प्रणाली बनाएँगे, जहाँ एक समन्वयक प्रश्नों को विशेषज्ञों तक भेजता है:
┌─────────────────────┐
User Query │ │
────────────────▶ │ COORDINATOR │
│ "Route to expert" │
└──────────┬──────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ BILLING AGENT │ │ SUPPORT AGENT │
│ │ │ │
│ 💰 Payments │ │ 🔧 Tech Issues │
│ 📄 Invoices │ │ 🐛 Bug Reports │
│ 💳 Subscriptions│ │ ❓ How-To │
└──────────────────┘ └──────────────────┘
मुख्य अवधारणाएँ:
- समन्वयक - सभी अनुरोध प्राप्त करता है और तय करता है कि उन्हें कौन संभालेगा
- विशेषज्ञ - केंद्रित एजेंट, जो विशिष्ट क्षेत्रों में उत्कृष्ट होते हैं
- हस्तांतरण - समन्वयक से विशेषज्ञ को निर्बाध रूप से कार्य सौंपना
पोर्टेबल TeamSpec
जब एक ही टीम को जनरेट किए गए
प्रोजेक्ट्स, CLI, Studio प्रीव्यू और Enterprise डिप्लॉयमेंट्स में समान रूप से निष्पादित करना हो, तब TeamSpec का उपयोग करें। स्पेक क्रमबद्ध किए जा सकने वाले डेटा के रूप में होता है; compile प्रत्येक घोषित नाम को किसी भी मौजूदा Agent
इम्प्लीमेंटेशन से बाइंड करता है और एक निष्पादन योग्य CompiledTeam रूट लौटाता है। यह किसी नए
एटॉमिक एजेंट प्रकार को नहीं जोड़ता।
use adk_agent::{
Agent, RelationshipKind, TeamMemberSpec, TeamRelationship, TeamSpec,
};
use std::sync::Arc;
let spec = TeamSpec {
name: "support_team".into(),
description: "Customer support routing".into(),
coordinator: "coordinator".into(),
members: vec![
TeamMemberSpec::new("coordinator"),
TeamMemberSpec::new("billing_agent"),
TeamMemberSpec::new("research_agent"),
],
relationships: vec![
TeamRelationship::new(
"coordinator", "billing_agent", RelationshipKind::Handoff,
),
TeamRelationship::new(
"coordinator", "research_agent", RelationshipKind::Delegate,
),
],
policy: Default::default(),
};
let root = spec.compile(vec![
Arc::new(coordinator) as Arc<dyn Agent>,
Arc::new(billing_agent),
Arc::new(research_agent),
])?;
सीधे क्रेट उपयोग के लिए, जब स्पेक में Delegate हो, तो adk-agent का team-tools फीचर सक्षम करें। अम्ब्रेला क्रेट के साथ, tools (या standard
टियर) सक्षम करें। केवल हैंडऑफ वाले स्पेक, आधार adk-agent फीचर सेट के साथ कंपाइल होते हैं।
| संबंध | नियंत्रण व्यवहार | निम्नीकृत तंत्र |
|---|---|---|
Handoff | कॉलर नियंत्रण स्थानांतरित करता है और वापस नहीं आता | रनर transfer_to_agent |
Delegate | कॉलर किसी सदस्य को आमंत्रित करता है, उसका परिणाम प्राप्त करता है और वापस आता है | AgentTool |
लक्ष्य प्रत्येक सदस्य के लिए सटीक होते हैं। कंपाइलर डुप्लिकेट सदस्यों और एज, अनुपलब्ध एंडपॉइंट, चक्र, पहुंच से बाहर सदस्यों, अमान्य सीमाओं, अनुपलब्ध एजेंट बाइंडिंग और अतिरिक्त बाइंडिंग को अस्वीकार करता है। डेलीगेट एज इनपुट/आउटपुट JSON स्कीमा, संदर्भ और इतिहास प्रक्षेपण, सटीक स्टेट कुंजियां, टाइमआउट और अनुमोदन आवश्यकताएं, पुनःप्रयास/फ़ॉलबैक व्यवहार तथा सर्किट ब्रेकर ले जा सकते हैं। हैंडऑफ़ एज सीमित स्टार्टअप पुनःप्रयास/फ़ॉलबैक का समर्थन करते हैं; केवल-डेलीगेट फ़ील्ड को चुपचाप अनदेखा करने के बजाय अस्वीकार किया जाता है। फ़ॉलबैक को अलग से घोषित एज के रूप में परिभाषित करना आवश्यक है; सत्यापन कभी भी उनके अधिकार-क्षेत्र का विस्तार नहीं करता।
टीम-व्यापी नीति हैंडऑफ़/डेलीगेशन गहराई, समवर्तीता, इवेंट, मॉडल और टूल कॉल,
टोकन, लागत, संबंधों की संख्या तथा वॉल टाइम की सीमाएं निर्धारित करती है।
समापन नियम एस्केलेशन, किसी सटीक अंतिम लेखक या टेक्स्ट मार्कर पर रुक सकते हैं।
हर इवेंट __adk_team_execution_v1 में एक सीरियलाइज़ करने योग्य निष्पादन रसीद रखता है, जिसमें
स्थिर रोस्टर, कारणात्मक डेलीगेशन/हैंडऑफ़ एज, समेकित उपयोग और टर्मिनल स्थिति
शामिल हैं। इसका निरीक्षण करने के लिए CompiledTeam::execution_snapshot और उसी इनवोकेशन ID के साथ
जारी रखने से पहले restore_execution_snapshot का उपयोग करें।
एक सक्रिय हैंडऑफ़ अपने स्थिर लक्ष्य पर फिर से शुरू होता है। किसी सामान्य
Agent अनुबंध से यह सिद्ध नहीं किया जा सकता कि कोई टूल कॉल इडेम्पोटेंट है,
इसलिए किसी अनसुलझे डेलीगेशन को स्वचालित रूप से दोबारा नहीं चलाया जाता; इसके
बजाय रनटाइम एक कार्रवाई योग्य त्रुटि लौटाता है। उस डेलीगेट को उसके अपने
चेकपॉइंट तंत्र के माध्यम से फिर से शुरू करें या ऑपरेशन को स्पष्ट रूप से
विफल/पुनःआरंभ करें।
पुन: प्रयोज्य आर्किटेक्चर के लिए, TeamArchitectureTemplate supervisor,
router और पदानुक्रमित प्रीसेट को स्पष्ट TeamSpec डेटा में बदलता है।
WorkflowArchitectureTemplate मौजूदा workflow एजेंट से क्रमिक, समानांतर, fan-out/fan-in
और सीमित review-loop प्रीसेट संकलित करता है। क्षमता-आधारित
resolution TeamAgentRegistry के माध्यम से उपलब्ध है; चयन नियतात्मक होता है,
इसमें health, version, digest और trust लेबल आवश्यक किए जा सकते हैं,
और चुना गया roster execution receipt में स्थिर कर दिया जाता है।
Execution-plane क्षमताएँ
संकलन स्रोत एजेंट की घोषित AgentCapabilities की जाँच करता है। delegate
स्रोत को invocation-स्कोप वाले runtime टूल का उपयोग करना चाहिए, handoff
स्रोत को transfers उत्सर्जित करने चाहिए, और स्वीकृत delegate को exact-call
पुष्टि का समर्थन करना चाहिए। LlmAgent और CodeActAgent अपनी समर्थित
runtime क्षमताएँ घोषित करते हैं; custom एजेंट रूढ़िवादी डिफ़ॉल्ट बनाए रखते
हैं और capabilities() को ओवरराइड कर सकते हैं।
Teams मानक ADK व्यवहार बनाए रखते हैं: Runner plugins, एजेंट/मॉडल/टूल कॉलबैक,
guardrails, cancellation, request identity, memory, artifacts, sessions और
event persistence अभी भी मौजूदा सदस्य एजेंट को wrap करते हैं। compile_with_hooks
team, सदस्य और exact संबंध सीमाओं के लिए क्रमबद्ध async TeamLifecycleHook
कॉलबैक जोड़ता है। Hooks सफलता/विफलता को देख सकते हैं या किसी लंबित
ऑपरेशन को उसके target का दायरा बढ़ाए बिना अस्वीकार कर सकते हैं। Runner
validated handoff से ठीक पहले root के async govern_transfer hook को भी कॉल करता है।
Native team.run, team.member.run और team.relationship.execute tracing
spans, सामान्य adk-telemetry exporter के माध्यम से team/सदस्य/edge की पहचान,
स्थिति और संबंध की अवधि वहन करते हैं। Runtime विफलताएँ agent.team.policy_denied,
agent.team.budget_exceeded और agent.team.resume_unsafe जैसे स्थिर structured
codes का उपयोग करती हैं।
डेलीगेट अनुबंध स्थिति पठन (stateKeys) और लेखन
(stateWriteKeys) में अंतर करते हैं। stateMerge: rejectConflicts तब चाइल्ड लेखन को अस्वीकार करता है जब
डेलीगेशन के दौरान पैरेंट मान बदल गया हो, और artifactPrefixes आर्टिफैक्ट
नामों को सीमित करता है। स्टैंडअलोन AgentTool यही नियंत्रण
उपलब्ध कराता है। संगतता के लिए इसका डिफ़ॉल्ट अभी भी
लास्ट-राइटर-विन्स है; Team संबंधों का डिफ़ॉल्ट कॉन्फ्लिक्ट
अस्वीकृति है।
CompiledTeam::resume_plan रसीद पुनर्स्थापित करने के बाद की एकमात्र सुरक्षित अगली कार्रवाई का
वर्णन करता है: कोऑर्डिनेटर, हैंडऑफ़ लक्ष्य, चेकपॉइंट-जागरूक डेलीगेट, या असुरक्षित
फेल-क्लोज़्ड डेलीगेशन। validate_team_replay कारणात्मक रसीद की अखंडता
सत्यापित करता है, जबकि analyze_execution परीक्षणों और मूल्यांकन पाइपलाइनों के लिए
प्रदाता-रहित टोपोलॉजी कवरेज, विफलताओं और अधिकतम कारणात्मक गहराई की
रिपोर्ट करता है।
BlackboardSpec नियंत्रित राउंड-रॉबिन और चयनकर्ता-प्रेरित समूह चैट को कवर करता है। यह
राउंड और ट्रांसक्रिप्ट प्रोजेक्शन की सीमाएँ निर्धारित करता है, और चयनकर्ता
संक्रमण सटीक अनुमति-सूचियों का उपयोग करते हैं। मौजूदा
sub_agent कंपोज़िशन पिछली संगतता के लिए समर्थित रहती है, लेकिन यह
पोर्टेबल टीम परिभाषा के बजाय मेमोरी में मौजूद ट्री है।
त्वरित शुरुआत
1. अपना प्रोजेक्ट बनाएँ
cargo new multi_agent_demo
cd multi_agent_demo
Cargo.toml में डिपेंडेंसीज़ जोड़ें:
[dependencies]
adk-rust = "2.1.0"
tokio = { version = "1", features = ["full"] }
dotenvy = "0.15"
अपनी API कुंजी के साथ .env बनाएँ:
echo 'GOOGLE_API_KEY=your-api-key' > .env
2. ग्राहक सेवा उदाहरण
यह एक पूर्ण कार्यशील उदाहरण है:
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-3.7-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(())
}
उदाहरण इंटरैक्शन:
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...
मल्टी-एजेंट ट्रांसफ़र कैसे काम करता है
समग्र दृष्टिकोण
जब आप किसी पैरेंट एजेंट में सब-एजेंट जोड़ते हैं, तो LLM को नियंत्रण हैंड ऑफ़ करने की क्षमता मिलती है:
┌─────────────────────┐
User Message │ │
─────────────────▶ COORDINATOR │
│ │
└──────────┬──────────┘
│
"This is a billing question..."
│
┌────────────────┴────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ billing_agent │ │ support_agent │
│ 💰 Payments │ │ 🔧 Tech Issues │
│ 📄 Invoices │ │ 🐛 Bug Reports │
└──────────────────┘ └──────────────────┘
चरण-दर-चरण ट्रांसफ़र प्रवाह
जब कोई उपयोगकर्ता बिलिंग संबंधी प्रश्न पूछता है, तो ठीक यही होता है:
┌──────────────────────────────────────────────────────────────────────┐
│ 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! │
│ │
└──────────────────────────────────────────────────────────────────────┘
यह कैसे काम करता है
| घटक | भूमिका |
|---|---|
.sub_agent() | पैरेंट के अंतर्गत विशेषज्ञों को पंजीकृत करता है |
transfer_to_agent टूल | सब-एजेंट मौजूद होने पर स्वचालित रूप से इंजेक्ट किया जाता है |
| एजेंट विवरण | यह तय करने में LLM की सहायता करता है कि कौन-सा एजेंट किस कार्य को संभालता है |
| रनर | स्थानांतरण घटनाओं का पता लगाता है और लक्षित एजेंट को कॉल करता है |
| साझा सत्र | स्थानांतरण के दौरान स्थिति और इतिहास सुरक्षित रखता है |
सब-एजेंट जोड़ने से पहले और बाद में
सब-एजेंट के बिना - एक एजेंट सब कुछ करता है:
User ──▶ coordinator ──▶ Response (handles billing AND support)
सब-एजेंट के साथ - विशेषज्ञ अपने क्षेत्र को संभालते हैं:
User ──▶ coordinator ──▶ billing_agent ──▶ Response (billing expert)
──▶ support_agent ──▶ Response (tech expert)
पदानुक्रमित मल्टी-एजेंट सिस्टम
जटिल परिस्थितियों के लिए, आप बहु-स्तरीय पदानुक्रम बना सकते हैं। प्रत्येक एजेंट के अपने सब-एजेंट हो सकते हैं, जिससे एक ट्री बनता है:
दृश्य: 3-स्तरीय कंटेंट टीम
┌─────────────────────┐
│ 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 │
└──────────────────┘ └──────────────────┘
अनुरोध नीचे कैसे प्रवाहित होते हैं
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 │
└─────────────────────────────────────────────────────────────┘
पूर्ण उदाहरण कोड
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-3.7-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(())
}
एजेंट पदानुक्रम:
project_manager
└── content_creator
├── researcher
└── writer
उदाहरण प्रॉम्प्ट:
- "स्वास्थ्य सेवा में AI के बारे में एक ब्लॉग पोस्ट बनाएँ" → PM → कंटेंट क्रिएटर → लेखक
- "इलेक्ट्रिक वाहनों पर शोध करें" → PM → कंटेंट क्रिएटर → शोधकर्ता
सब-एजेंट कॉन्फ़िगरेशन
किसी भी LlmAgent में sub_agent() बिल्डर मेथड का उपयोग करके सब-एजेंट जोड़ें:
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()?;
मुख्य बिंदु:
- प्रत्येक एजेंट के कई सब-एजेंट हो सकते हैं
- सब-एजेंट के अपने सब-एजेंट हो सकते हैं (बहु-स्तरीय पदानुक्रम)
- एजेंट के नाम पदानुक्रम के भीतर अद्वितीय होने चाहिए
- विवरण LLM को यह तय करने में मदद करते हैं कि किस एजेंट को ट्रांसफ़र करना है
प्रभावी ट्रांसफ़र निर्देश लिखना
सफल एजेंट ट्रांसफ़र के लिए स्पष्ट निर्देश और विवरण दें:
पैरेंट एजेंट के निर्देश
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()?;
सब-एजेंट के विवरण
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()?;
सर्वोत्तम अभ्यास:
- ऐसे वर्णनात्मक एजेंट नामों का उपयोग करें जो उनके उद्देश्य को स्पष्ट रूप से दर्शाते हों
- विस्तृत विवरण लिखें - LLM इनका उपयोग ट्रांसफ़र तय करने के लिए करता है
- विवरण में ऐसे विशिष्ट कीवर्ड शामिल करें जो संभावित उपयोगकर्ता अनुरोधों से मेल खाते हों
- पैरेंट एजेंट के निर्देशों में स्पष्ट प्रत्यायोजन नियम दें
- एजेंट विवरणों में एकसमान शब्दावली का उपयोग करें
अपने मल्टी-एजेंट सिस्टम का परीक्षण
उदाहरण चलाना
cargo run --manifest-path examples/tier_examples/enterprise/Cargo.toml --bin 14-enterprise-multi-agent
उदाहरण परीक्षण प्रॉम्प्ट
ग्राहक सेवा:
- "मेरे पिछले बिल के बारे में मेरा एक प्रश्न है" → इसे
billing_agentको रूट करना चाहिए - "ऐप बार-बार क्रैश हो रहा है" → इसे
support_agentको रूट करना चाहिए - "मैं अपना प्लान कैसे अपग्रेड करूँ?" → इसे
billing_agentको रूट करना चाहिए - "नमस्ते, मुझे सहायता चाहिए" → स्पष्टीकरण के लिए
coordinatorके पास ही रहना चाहिए
पदानुक्रमित:
- "स्वास्थ्य सेवा में AI के बारे में एक ब्लॉग पोस्ट बनाएँ" → PM → Content Creator → Writer
- "इलेक्ट्रिक वाहनों के इतिहास पर शोध करें" → PM → Content Creator → Researcher
- "हमारी वर्तमान परियोजनाओं की स्थिति क्या है?" →
project_managerके पास ही रहना चाहिए
ट्रांसफ़र संबंधी समस्याओं को डीबग करना
यदि ट्रांसफ़र अपेक्षा के अनुसार काम नहीं कर रहे हैं:
- एजेंट नाम जाँचें - ट्रांसफ़र कॉल में बिल्कुल मेल खाने चाहिए
- विवरणों की समीक्षा करें - उन्हें अधिक विशिष्ट और कीवर्ड-समृद्ध बनाएँ
- निर्देश स्पष्ट करें - ट्रांसफ़र कब करना है, इसे स्पष्ट रूप से बताएँ
- एज केस का परीक्षण करें - रूटिंग व्यवहार देखने के लिए अस्पष्ट अनुरोध आज़माएँ
- ट्रांसफ़र संकेतकों को देखें -
[Agent: name]दिखाता है कि कौन-सा एजेंट उत्तर दे रहा है
वैश्विक निर्देश
मूल उपयोग
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()?;
वैश्विक बनाम एजेंट निर्देश
- वैश्विक निर्देश: पदानुक्रम के सभी एजेंटों पर लागू होता है और समग्र व्यक्तित्व/संदर्भ निर्धारित करता है
- एजेंट निर्देश: प्रत्येक एजेंट के लिए विशिष्ट होता है और उसकी विशेष भूमिका तथा व्यवहार निर्धारित करता है
दोनों निर्देश वार्तालाप इतिहास में शामिल होते हैं, जिसमें वैश्विक निर्देश सबसे पहले दिखाई देता है।
गतिशील वैश्विक निर्देश
अधिक उन्नत परिदृश्यों के लिए, आप एक वैश्विक निर्देश प्रदाता का उपयोग कर सकते हैं जो निर्देश की गणना गतिशील रूप से करता है:
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()?;
स्थिति चर इंजेक्शन
वैश्विक और एजेंट दोनों निर्देश {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()?;
फ़्रेमवर्क सत्र की स्थिति से मानों को निर्देश टेम्पलेट में स्वचालित रूप से इंजेक्ट करता है।
सामान्य बहु-एजेंट पैटर्न
समन्वयक/डिस्पैचर पैटर्न
एक केंद्रीय एजेंट अनुरोधों को विशेषीकृत उप-एजेंटों तक भेजता है:
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()?;
उदाहरण वार्तालाप:
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...
मुख्य बिंदु:
- समन्वयक अनुरोध का विश्लेषण करता है और उसे बिलिंग एजेंट को स्थानांतरित करता है
- बिलिंग एजेंट उसी टर्न में तुरंत उत्तर देता है
- बाद के संदेश बिलिंग एजेंट के साथ जारी रहते हैं
- स्थानांतरण संकेतक (
🔄) दिखाते हैं कि हैंडऑफ कब होते हैं
पदानुक्रमित कार्य विघटन
जटिल कार्यों को विभाजित करने के लिए बहु-स्तरीय पदानुक्रम:
// 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()?;
वर्कफ़्लो एजेंटों के साथ संयोजन
बहु-एजेंट प्रणालियाँ वर्कफ़्लो एजेंटों (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()?;
एजेंटों के बीच संचार
पदानुक्रम में एजेंट साझा सेशन स्थिति के माध्यम से संचार करते हैं:
// 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()?;
output_key कॉन्फ़िगरेशन एजेंट की अंतिम प्रतिक्रिया को सेशन स्थिति में स्वचालित रूप से सहेजता है, जिससे वह बाद के एजेंटों के लिए उपलब्ध हो जाती है।
AgentTool स्थिति और आर्टिफैक्ट फ़ॉरवर्डिंग
एजेंटों को टूल के रूप में रैप करने के लिए AgentTool का उपयोग करने पर, उप-एजेंटों से स्थिति में होने वाले परिवर्तन और आर्टिफैक्ट स्वचालित रूप से पैरेंट संदर्भ में फ़ॉरवर्ड हो जाते हैं:
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 उप-एजेंटों को आंतरिक रूप से नॉन-स्ट्रीमिंग मोड (StreamingMode::None) में चलाता है, इसलिए उप-एजेंट पैरेंट को लौटाने से पहले अपनी पूरी प्रतिक्रिया संचित कर लेता है। इससे आंशिक स्ट्रीमिंग चंक्स के कारण खाली परिणाम उत्पन्न होने की समस्याएँ रुकती हैं।
यह AgentTool पैटर्न का उपयोग करते समय पैरेंट और चाइल्ड एजेंटों के बीच निर्बाध डेटा प्रवाह सक्षम करता है।
बहु-एजेंट प्रणालियाँ चलाना
लॉन्चर का उपयोग करना
Launcher बहु-एजेंट प्रणालियों को चलाने और परीक्षण करने का एक आसान तरीका प्रदान करता है:
use adk_rust::Launcher;
let coordinator = /* your multi-agent setup */;
Launcher::new(Arc::new(coordinator))
.run()
.await?;
रन मोड:
# 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
विशेषताएँ:
- एजेंट संकेतक: दिखाता है कि कौन-सा एजेंट उत्तर दे रहा है
[Agent: coordinator] - स्थानांतरण दृश्यांकन: स्थानांतरण घटनाएँ प्रदर्शित करता है
🔄 [Transfer requested to: billing_agent] - निर्बाध हैंडऑफ़: स्थानांतरण के तुरंत बाद लक्षित एजेंट उत्तर देता है
- वार्तालाप इतिहास: एजेंट स्थानांतरणों के दौरान संदर्भ बनाए रखता है
स्थानांतरणों का परीक्षण
यह सत्यापित करने के लिए कि आपका multi-agent system सही ढंग से काम करता है:
- एजेंट नाम जाँचें कि उनके उत्तर देने पर वे कोष्ठकों में दिखाई देते हैं
- स्थानांतरण संकेतकों को देखें (
🔄) जब एजेंट हैंडऑफ़ करते हैं - तत्काल उत्तरों को सत्यापित करें कि लक्षित एजेंट बिना दोबारा प्रॉम्प्ट किए उत्तर देते हैं
- विभिन्न अनुरोध प्रकारों का परीक्षण करें ताकि उचित रूटिंग सुनिश्चित हो सके
- एज केस जाँचें, जैसे ऐसे एजेंट को स्थानांतरित करना जो मौजूद नहीं है
स्थानांतरण संबंधी समस्याओं का डीबगिंग
यदि स्थानांतरण काम नहीं कर रहे हैं:
- सत्यापित करें कि sub-agents जोड़े गए हैं
.sub_agent()के माध्यम से - एजेंट विवरण जाँचें - LLM स्थानांतरण तय करने के लिए इनका उपयोग करता है
- निर्देशों की समीक्षा करें - parent को यह बताना चाहिए कि कब स्थानांतरण करना है
- एजेंट नाम जाँचें - स्थानांतरण कॉल में उनका बिल्कुल सही मिलान होना चाहिए
- लॉगिंग सक्षम करें ताकि event stream में स्थानांतरण क्रियाएँ दिखाई दें
सर्वोत्तम प्रथाएँ
- स्पष्ट विवरण: LLM को अच्छे स्थानांतरण निर्णय लेने में सहायता करने के लिए वर्णनात्मक एजेंट नाम और विवरण लिखें
- विशिष्ट निर्देश: प्रत्येक एजेंट को उसकी भूमिका के लिए स्पष्ट, केंद्रित निर्देश दें
- Global Instruction का उपयोग करें: सभी एजेंटों में एकसमान व्यक्तित्व और संदर्भ निर्धारित करें
- स्थिति प्रबंधन: एजेंट संचार के लिए
output_keyऔर स्थिति चर का उपयोग करें - पदानुक्रम की गहराई सीमित करें: बेहतर रखरखाव के लिए पदानुक्रम को उथला (2-3 स्तर) रखें
- स्थानांतरण तर्क का परीक्षण करें: सत्यापित करें कि एजेंट विभिन्न अनुरोधों के लिए सही sub-agents को स्थानांतरित करते हैं
संबंधित
- LLM एजेंट - मुख्य एजेंट कॉन्फ़िगरेशन
- वर्कफ़्लो एजेंट - क्रमिक, समानांतर और लूप एजेंट
- सत्र - सत्र स्थिति प्रबंधन
पिछला: ← वर्कफ़्लो एजेंट | अगला: ग्राफ़ एजेंट →