أنظمة متعددة الوكلاء
أنشئ تطبيقات متقدمة من خلال دمج وكلاء متخصصين في فرق.
نظرة عامة على تسلسل الوكلاء
ما ستبنيه
في هذا الدليل، ستنشئ نظام خدمة عملاء يوجّه فيه منسّق الاستعلامات إلى المتخصصين:
┌─────────────────────┐
User Query │ │
────────────────▶ │ COORDINATOR │
│ "Route to expert" │
└──────────┬──────────┘
│
┌───────────────┴───────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ BILLING AGENT │ │ SUPPORT AGENT │
│ │ │ │
│ 💰 Payments │ │ 🔧 Tech Issues │
│ 📄 Invoices │ │ 🐛 Bug Reports │
│ 💳 Subscriptions│ │ ❓ How-To │
└──────────────────┘ └──────────────────┘
المفاهيم الأساسية:
- المنسّق - يستقبل جميع الطلبات ويقرر من سيتولى معالجتها
- المتخصصون - وكلاء يركزون على مجالات محددة ويتفوقون فيها
- النقل - تسليم سلس من المنسّق إلى المتخصص
TeamSpec قابل للنقل
استخدم TeamSpec عندما يجب على الفريق نفسه التنفيذ بطريقة متطابقة في المشاريع المُنشأة، وCLI، ومعاينة Studio، وعمليات النشر في Enterprise. والمواصفة عبارة عن بيانات قابلة للتسلسل؛ إذ يربط 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),
])?;
للاستخدام المباشر للحزمة، فعّل ميزة team-tools في adk-agent عندما تحتوي المواصفة على Delegate. ومع الحزمة الشاملة، فعّل tools (أو فئة standard). تُجمَّع المواصفات التي تقتصر على عمليات التسليم باستخدام مجموعة ميزات adk-agent الأساسية.
| العلاقة | سلوك التحكم | الآلية المُخفَّضة |
|---|---|---|
Handoff | ينقل المتصل التحكم ولا يستأنف التنفيذ | المشغّل transfer_to_agent |
Delegate | يستدعي المتصل عضوًا، ويتلقى نتيجته، ويستأنف التنفيذ | AgentTool |
الأهداف دقيقة لكل عضو. يرفض المصرّف الأعضاء والحواف المكررة، ونقاط النهاية المفقودة، والدورات، والأعضاء غير القابلة للوصول، والحدود غير الصالحة، وارتباطات الوكلاء المفقودة، والارتباطات الإضافية. يمكن أن تحمل حواف التفويض مخططات JSON للإدخال/الإخراج، وإسقاط السياق والسجل، ومفاتيح الحالة الدقيقة، ومتطلبات المهلة والموافقة، وسلوك إعادة المحاولة/البديل، وقاطع الدائرة. تدعم حواف التسليم إعادة المحاولة/البديل عند بدء التشغيل ضمن حدود؛ ويُرفض الحقول الخاصة بالتفويض فقط بدلاً من تجاهلها بصمت. يجب التصريح عن البدائل كحواف منفصلة؛ ولا يؤدي التحقق أبداً إلى توسيع صلاحياتها.
تضع سياسة الفريق حدوداً لعمق التسليم/التفويض، والتزامن، والأحداث، واستدعاءات النموذج والأداة، والرموز، والتكلفة، وعدد العلاقات، والوقت المنقضي. يمكن لقواعد الإنهاء إيقاف التنفيذ عند التصعيد، أو عند مؤلف نهائي محدد بدقة، أو عند علامة نصية. يحمل كل حدث إيصال تنفيذ قابلاً للتسلسل في __adk_team_execution_v1، يتضمن قائمة الأعضاء المجمدة، وحواف التفويض/التسليم السببية، والاستخدام التراكمي، والحالة النهائية. استخدم CompiledTeam::execution_snapshot لفحصه وrestore_execution_snapshot قبل الاستئناف باستخدام معرّف الاستدعاء نفسه.
يُستأنف التسليم النشط عند هدفه المجمد. لا يُعاد تشغيل التفويض غير المحسوم تلقائياً، لأن العقد العام Agent لا يستطيع إثبات أن استدعاء الأداة متكرر التنفيذ بأمان؛ وبدلاً من ذلك، يعيد وقت التشغيل خطأً قابلاً للتنفيذ. استأنف ذلك التفويض عبر آلية نقاط التحقق الخاصة به، أو أفشل العملية/أعد تشغيلها صراحةً.
بالنسبة إلى البنى القابلة لإعادة الاستخدام، تعمل TeamArchitectureTemplate على تحويل الإعدادات المسبقة للمشرف والموجّه والتدرّج الهرمي إلى بيانات TeamSpec صريحة.
تعمل WorkflowArchitectureTemplate على تجميع الإعدادات المسبقة للتنفيذ التسلسلي والمتوازي والتوزيع/الدمج وحلقة المراجعة المحدودة من وكلاء سير العمل الحاليين. يتوفر الحل القائم على القدرات من خلال TeamAgentRegistry؛ ويكون الاختيار حتميًا، ويمكن أن يتطلب تسميات الصحة والإصدار والبصمة والثقة، كما تُجمّد قائمة العناصر المختارة في إيصال التنفيذ.
قدرات مستوى التنفيذ
يتحقق التجميع من AgentCapabilities المعلنة للوكيل المصدر. يجب أن يستهلك مصدر التفويض أدوات وقت التشغيل الخاصة بالاستدعاء، ويجب أن يُصدر مصدر التسليم عمليات نقل، كما يجب أن يدعم التفويض المعتمد تأكيد الاستدعاء الدقيق.
تعلن LlmAgent وCodeActAgent عن قدرات وقت التشغيل التي تدعمانها؛ بينما تحتفظ الوكلاء المخصّصون بالإعدادات الافتراضية المحافظة ويمكنهم تجاوز capabilities().
تحتفظ الفرق بسلوك ADK القياسي: إذ تظل إضافات Runner وعمليات الاستدعاء الخاصة بالوكيل/النموذج/الأداة، وضوابط الحماية، والإلغاء، وهوية الطلب، والذاكرة، والآثار، والجلسات، واستمرارية الأحداث، تغلّف وكلاء الأعضاء الحاليين. تضيف compile_with_hooks عمليات استدعاء TeamLifecycleHook غير متزامنة ومرتبة للفريق والعضو وحدود العلاقة الدقيقة. ويمكن للخطافات مراقبة النجاح/الفشل أو رفض عملية معلّقة من دون توسيع نطاق هدفها. كما يستدعي Runner خطاف govern_transfer غير المتزامن للجذر مباشرة قبل التسليم الذي تم التحقق منه.
تحمل امتدادات التتبع الأصلية team.run وteam.member.run وteam.relationship.execute هوية الفريق/العضو/الحافة، والحالة، ومدة العلاقة، عبر مُصدّر adk-telemetry المعتاد. وتستخدم إخفاقات وقت التشغيل رموزًا منظّمة مستقرة مثل agent.team.policy_denied وagent.team.budget_exceeded وagent.team.resume_unsafe.
تُميّز عقود التفويض بين قراءات الحالة (stateKeys) وعمليات الكتابة
(stateWriteKeys). يرفض stateMerge: rejectConflicts عملية كتابة من عنصر فرعي عندما
تتغير قيمة العنصر الأب أثناء التفويض، بينما يحدّ artifactPrefixes من أسماء
القطع الأثرية. ويكشف AgentTool المستقل عن عناصر التحكم نفسها. ويظل
الافتراضي لديه هو فوز الكاتب الأخير توافقًا مع الإصدارات السابقة؛ أما
علاقات الفريق فافتراضيًا ترفض التعارضات.
يصف 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"
أنشئ .env باستخدام مفتاح API الخاص بك:
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
أمثلة على المطالبات:
- "أنشئ منشور مدونة حول الذكاء الاصطناعي في مجال الرعاية الصحية" → مدير المشروع → منشئ المحتوى → الكاتب
- "أجرِ بحثًا حول المركبات الكهربائية" → مدير المشروع → منشئ المحتوى → الباحث
تكوين الوكيل الفرعي
أضف وكلاء فرعيين إلى أي 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لطلب التوضيح
هرمي:
- "أنشئ منشورًا لمدونة حول الذكاء الاصطناعي في الرعاية الصحية" → مدير المشروع → منشئ المحتوى → الكاتب
- "ابحث في تاريخ المركبات الكهربائية" → مدير المشروع → منشئ المحتوى → الباحث
- "ما حالة مشاريعنا الحالية؟" → ينبغي أن يبقى مع
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()?;
الدمج مع وكلاء سير العمل
تعمل الأنظمة متعددة الوكلاء بشكل جيد مع وكلاء سير العمل (التسلسلي، والمتوازي، والحلقة):
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] - تسليم سلس: يستجيب الوكيل المستهدف مباشرةً بعد التحويل
- سجل المحادثة: يحافظ على السياق عبر عمليات تحويل الوكلاء
اختبار التحويلات
للتحقق من أن نظام الوكلاء المتعددين يعمل بشكل صحيح:
- تحقق من أسماء الوكلاء التي تظهر بين قوسين عند استجابتهم
- ابحث عن مؤشرات التحويل (
🔄) عندما يُسلّم الوكلاء المهمة - تحقق من الاستجابات الفورية من الوكلاء المستهدفين دون إعادة إرسال الطلب
- اختبر أنواعًا مختلفة من الطلبات لضمان التوجيه الصحيح
- تحقق من الحالات الحدّية مثل التحويل إلى وكلاء غير موجودين
تصحيح مشكلات التحويل
إذا لم تعمل التحويلات:
- تحقق من إضافة الوكلاء الفرعيين عبر
.sub_agent() - تحقق من أوصاف الوكلاء - يستخدم LLM هذه الأوصاف لاتخاذ قرارات التحويل
- راجع التعليمات - يجب أن يذكر الوكيل الأب متى ينبغي إجراء التحويل
- تحقق من أسماء الوكلاء - يجب أن تتطابق تمامًا في استدعاءات التحويل
- فعّل التسجيل لرؤية إجراءات التحويل في تدفق الأحداث
أفضل الممارسات
- أوصاف واضحة: اكتب أسماء وأوصافًا وصفية للوكلاء لمساعدة LLM على اتخاذ قرارات تحويل جيدة
- تعليمات محددة: امنح كل وكيل تعليمات واضحة ومركّزة لدوره
- استخدم التعليمات العامة: حدّد شخصية وسياقًا متسقين عبر جميع الوكلاء
- إدارة الحالة: استخدم
output_keyومتغيرات الحالة لتواصل الوكلاء - حدّ من عمق التسلسل الهرمي: حافظ على تسلسلات هرمية ضحلة (مستويين إلى 3 مستويات) لتحسين قابلية الصيانة
- اختبر منطق التحويل: تحقّق من تحويل الوكلاء إلى الوكلاء الفرعيين الصحيحين للطلبات المختلفة
ذو صلة
- الوكيل LLM - إعداد الوكيل الأساسي
- وكلاء سير العمل - وكلاء متسلسلون ومتوازون وحلقيون
- الجلسات - إدارة حالة الجلسة
السابق: ← وكلاء سير العمل | التالي: وكلاء الرسم البياني →