Cours Python · Module 11: RAG et systèmes multi-agents
Subagents et hiérarchies d'agents
Dans cette leçon8
L'expédition grandit : quelqu'un repère l'itinéraire, quelqu'un compte les provisions, quelqu'un vérifie les permis, quelqu'un surveille la qualité. Quand chacun parle avec tout le monde, au bout d'une semaine plus personne ne sait qui a décidé quoi. Il te faut un chef d'expédition qui distribue les tâches et rassemble les rapports.
Les subagents sont un modèle d'architecture dans lequel l'agent principal (l'orchestrateur) délègue des tâches à des sous-agents spécialisés. C'est comme l'organigramme d'une entreprise - le PDG délègue des tâches aux managers, qui délèguent à leur tour.
Architecture des subagents
Le schéma montre trois niveaux de hiérarchie, du chef jusqu'aux outils :
1┌─────────────────────────────────────────────────────────────┐
2│ Agent Hierarchy │
3├─────────────────────────────────────────────────────────────┤
4│ │
5│ ┌───────────────┐ │
6│ │ Orchestrator │ │
7│ │ (Main AI) │ │
8│ └───────┬───────┘ │
9│ │ │
10│ ┌────────────────┼────────────────┐ │
11│ │ │ │ │
12│ ▼ ▼ ▼ │
13│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
14│ │ Research │ │ Analysis │ │ Execution │ │
15│ │ Subagent │ │ Subagent │ │ Subagent │ │
16│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
17│ │ │ │ │
18│ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ │
19│ │ Tools │ │ Tools │ │ Tools │ │
20│ └───────────┘ └───────────┘ └───────────┘ │
21│ │
22└─────────────────────────────────────────────────────────────┘En haut, l'orchestrateur, qui coordonne le travail et délègue les tâches. En dessous, les subagents spécialisés, et tout en bas, les outils qu'ils utilisent. L'orchestrateur ne touche jamais directement aux outils.
Implémentation de base des subagents
D'abord les types de données : les rôles dans un Enum, et la tâche et le résultat dans une @dataclass :
1from openai import OpenAI
2from abc import ABC, abstractmethod
3from dataclasses import dataclass
4from typing import Optional
5from enum import Enum
6
7client = OpenAI()
8
9class SubagentRole(Enum):
10 RESEARCHER = "researcher"
11 ANALYST = "analyst"
12 EXECUTOR = "executor"
13 VALIDATOR = "validator"
14
15@dataclass
16class SubagentTask:
17 """Tâche pour un subagent."""
18 description: str
19 context: str
20 expected_output: str
21 priority: int = 1
22
23@dataclass
24class SubagentResult:
25 """Résultat du travail d'un subagent."""
26 success: bool
27 output: str
28 metadata: dictSubagentTask transporte une description, un contexte et un résultat attendu, tout ce dont un spécialiste a besoin pour ne pas redemander des détails au chef.
La classe de base Subagent hérite de ABC et impose system_prompt via @abstractmethod, comme BaseAgent dans la leçon sur les systèmes multi-agents :
1class Subagent(ABC):
2 """Classe de base des subagents."""
3
4 def __init__(self, name: str, role: SubagentRole, model: str = "gpt-4o-mini"):
5 self.name = name
6 self.role = role
7 self.model = model
8 self.tools: list[dict] = []
9 self.memory: list[str] = []
10
11 @property
12 @abstractmethod
13 def system_prompt(self) -> str:
14 """System prompt du subagent."""
15 pass
16
17 def add_tool(self, tool: dict) -> None:
18 """Ajoute un outil au subagent."""
19 self.tools.append(tool)Chaque subagent a sa propre liste d'outils et sa mémoire. add_tool ajoute une définition d'outil au format OpenAI, et memory rassemble des résumés des tâches effectuées.
La méthode execute construit un prompt à partir des trois champs de la tâche et appelle le modèle :
1 async def execute(self, task: SubagentTask) -> SubagentResult:
2 """Exécute une tâche."""
3 messages = [
4 {"role": "system", "content": self.system_prompt},
5 {"role": "user", "content": f"""
6Task: {task.description}
7Context: {task.context}
8Expected output: {task.expected_output}
9"""}
10 ]
11
12 response = client.chat.completions.create(
13 model=self.model,
14 messages=messages,
15 tools=self.tools if self.tools else None
16 )
17
18 output = response.choices[0].message.content
19 self.memory.append(f"Task: {task.description} -> Result: {output[:100]}...")
20
21 return SubagentResult(
22 success=True,
23 output=output,
24 metadata={"model": self.model, "role": self.role.value}
25 )La méthode est async, mais elle utilise un client synchrone, donc elle bloque la boucle d'événements. En production, utilise AsyncOpenAI et await. Attention aussi aux outils : quand le modèle appelle un outil au lieu de répondre par du texte, content vaut None et output[:100] lève une erreur.
Subagents spécialisés
Comme avant, les spécialistes ne diffèrent que par leur prompt. Le chercheur et l'analyste :
1class ResearchSubagent(Subagent):
2 """Subagent de recherche - rassemble des informations."""
3
4 @property
5 def system_prompt(self) -> str:
6 return """You are a specialized research agent.
7
8Your tasks:
91. Gather information from available sources
102. Verify facts
113. Structure knowledge
124. Identify information gaps
13
14Always:
15- Provide information sources
16- Flag uncertainties
17- Suggest further research directions"""
18
19
20class AnalysisSubagent(Subagent):
21 """Subagent analytique - analyse les données."""
22
23 @property
24 def system_prompt(self) -> str:
25 return """You are a specialized analytical agent.
26
27Your tasks:
281. Analyze provided data
292. Identify patterns and trends
303. Formulate conclusions
314. Assess risks and opportunities
32
33Always:
34- Use numerical data
35- Present alternative interpretations
36- Highlight key discoveries"""Chaque prompt dit ce que fait le subagent et ce qu'il doit toujours surveiller. La section "Always" fonctionne comme le règlement du campement pour ce spécialiste.
L'exécutant et le validateur complètent l'équipe :
1class ExecutorSubagent(Subagent):
2 """Subagent exécuteur - réalise les tâches."""
3
4 @property
5 def system_prompt(self) -> str:
6 return """You are a specialized executor agent.
7
8Your tasks:
91. Carry out planned actions
102. Use tools to complete tasks
113. Report progress
124. Handle errors
13
14Always:
15- Execute tasks step by step
16- Verify the results of each action
17- Report problems immediately"""
18
19
20class ValidatorSubagent(Subagent):
21 """Subagent validateur - vérifie la qualité."""
22
23 @property
24 def system_prompt(self) -> str:
25 return """You are a specialized validation agent.
26
27Your tasks:
281. Verify result correctness
292. Check compliance with requirements
303. Identify errors and shortcomings
314. Suggest corrections
32
33Always:
34- Be critical but constructive
35- Use specific criteria
36- Propose solutions to problems"""Le validateur relit les résultats des autres, donc l'erreur d'un spécialiste a une chance d'être repérée.
Orchestrateur - gérer les subagents
L'orchestrateur tient un registre des subagents et un historique des tâches :
1from typing import Dict, List
2import asyncio
3
4class AgentOrchestrator:
5 """Orchestrateur principal gérant les subagents."""
6
7 def __init__(self, model: str = "gpt-4o-mini"):
8 self.model = model
9 self.subagents: Dict[str, Subagent] = {}
10 self.task_history: List[dict] = []
11
12 def register_subagent(self, subagent: Subagent) -> None:
13 """Enregistre un subagent."""
14 self.subagents[subagent.name] = subagent
15 print(f"Registered subagent: {subagent.name} ({subagent.role.value})")
16
17 def get_available_subagents(self) -> str:
18 """Renvoie une description des subagents disponibles."""
19 return "\n".join([
20 f"- {name}: {agent.role.value}"
21 for name, agent in self.subagents.items()
22 ])get_available_subagents construit une liste textuelle des spécialistes, qu'on montrera au modèle dans un instant.
Les étapes de l'orchestrateur suivent toujours cet ordre : plan_execution, le choix d'un subagent, subagent.execute et synthesize_results. La planification demande au modèle un plan en JSON :
1 async def plan_execution(self, task: str) -> List[SubagentTask]:
2 """Planifie l'exécution de la tâche via les subagents appropriés."""
3 planning_prompt = f"""You have a task to execute: {task}
4
5Available subagents:
6{self.get_available_subagents()}
7
8Plan the task execution. For each step specify:
91. Which subagent should execute the step
102. Task description for the subagent
113. Expected output
124. Priority (1-5)
13
14Reply in JSON format:
15{{"steps": [{{"subagent": "name", "task": "description", "expected_output": "...", "priority": 1}}, ...]}}"""
16
17 response = client.chat.completions.create(
18 model=self.model,
19 messages=[
20 {"role": "system", "content": "You are a task planner. Reply only in JSON."},
21 {"role": "user", "content": planning_prompt}
22 ],
23 response_format={"type": "json_object"}
24 )
25
26 import json
27 plan = json.loads(response.choices[0].message.content)
28
29 tasks = []
30 for step in plan.get("steps", plan):
31 tasks.append(SubagentTask(
32 description=step["task"],
33 context=task,
34 expected_output=step["expected_output"],
35 priority=step.get("priority", 1)
36 ))
37
38 return tasksLe mode response_format={"type": "json_object"} garantit un objet JSON valide, mais pas un tableau. C'est pourquoi le prompt demande un objet avec une clé steps, et le code lit plan.get("steps", plan).
execute_task relie la planification, l'exécution et la synthèse :
1 async def execute_task(self, task: str) -> str:
2 """Exécute une tâche à l'aide des subagents."""
3 # 1. Planification
4 planned_tasks = await self.plan_execution(task)
5 print(f"Planned {len(planned_tasks)} steps")
6
7 # 2. Exécution
8 results = []
9 for i, subtask in enumerate(planned_tasks):
10 # Trouve le subagent approprié
11 subagent = self._select_subagent(subtask)
12
13 if subagent:
14 print(f"Step {i+1}: {subagent.name} executing: {subtask.description[:50]}...")
15 result = await subagent.execute(subtask)
16 results.append({
17 "step": i + 1,
18 "subagent": subagent.name,
19 "task": subtask.description,
20 "result": result.output
21 })
22
23 # 3. Synthèse
24 final_result = await self._synthesize_results(task, results)
25
26 return final_resultLes résultats vont dans une liste de dictionnaires, donc la synthèse sait quel subagent a fait quoi.
Le choix d'un subagent repose sur une simple heuristique de mots-clés :
1 def _select_subagent(self, task: SubagentTask) -> Optional[Subagent]:
2 """Sélectionne le meilleur subagent pour la tâche."""
3 # Heuristique simple - peut être étendue avec du ML
4 keywords = {
5 "researcher": ["research", "find", "search", "information"],
6 "analyst": ["analyze", "evaluate", "compare", "conclusions"],
7 "executor": ["execute", "do", "create", "implement"],
8 "validator": ["check", "verify", "validate", "test"]
9 }
10
11 task_lower = task.description.lower()
12
13 for subagent_type, kws in keywords.items():
14 if any(kw in task_lower for kw in kws):
15 for agent in self.subagents.values():
16 if agent.role.value == subagent_type:
17 return agent
18
19 # Par défaut, le premier disponible
20 return list(self.subagents.values())[0] if self.subagents else NoneLes clés du dictionnaire doivent être égales aux valeurs des rôles, c'est pourquoi la première clé est "researcher" et non "research", sinon le chercheur ne serait jamais choisi. Le champ subagent du plan est ignoré ici, ce qui mérite d'être amélioré.
Pour finir, la synthèse fusionne les résultats en une seule réponse :
1 async def _synthesize_results(self, original_task: str, results: List[dict]) -> str:
2 """Synthétise les résultats de tous les subagents."""
3 results_summary = "\n\n".join([
4 f"Step {r['step']} ({r['subagent']}): {r['result']}"
5 for r in results
6 ])
7
8 synthesis_prompt = f"""Original task: {original_task}
9
10Subagent results:
11{results_summary}
12
13Create a coherent, final answer based on the results of all subagents."""
14
15 response = client.chat.completions.create(
16 model=self.model,
17 messages=[
18 {"role": "system", "content": "You are a synthesizer. You combine results into a coherent whole."},
19 {"role": "user", "content": synthesis_prompt}
20 ]
21 )
22
23 return response.choices[0].message.contentC'est le troisième appel au modèle pour une seule tâche, avec la planification et le travail des subagents.
Utiliser l'orchestrateur
On enregistre quatre spécialistes et on demande un plan de Safari :
1import asyncio
2
3async def main():
4 # Crée l'orchestrateur
5 orchestrator = AgentOrchestrator()
6
7 # Enregistre les subagents
8 orchestrator.register_subagent(
9 ResearchSubagent("safari_researcher", SubagentRole.RESEARCHER)
10 )
11 orchestrator.register_subagent(
12 AnalysisSubagent("data_analyst", SubagentRole.ANALYST)
13 )
14 orchestrator.register_subagent(
15 ExecutorSubagent("task_executor", SubagentRole.EXECUTOR)
16 )
17 orchestrator.register_subagent(
18 ValidatorSubagent("quality_checker", SubagentRole.VALIDATOR)
19 )
20
21 # Exécute une tâche complexe
22 result = await orchestrator.execute_task(
23 "Prepare a complete 7-day Safari plan in the Serengeti for 4 people"
24 )
25
26 print("\n" + "="*50)
27 print("FINAL RESULT:")
28 print("="*50)
29 print(result)
30
31asyncio.run(main())asyncio.run lance la coroutine principale, et l'orchestrateur planifie, délègue et assemble le résultat tout seul. Le spécialiste qui reçoit une étape dépend des mots dans les descriptions générées par le planificateur, pas dans la tâche elle-même.
Hiérarchie à plusieurs niveaux
Une grande expédition a des chefs d'équipe. Un orchestrateur peut avoir d'autres orchestrateurs sous ses ordres :
1class HierarchicalOrchestrator:
2 """Orchestrateur avec hiérarchie multi-niveaux."""
3
4 def __init__(self, name: str, level: int = 0):
5 self.name = name
6 self.level = level
7 self.subagents: Dict[str, Subagent] = {}
8 self.sub_orchestrators: Dict[str, "HierarchicalOrchestrator"] = {}
9
10 def add_sub_orchestrator(self, orchestrator: "HierarchicalOrchestrator") -> None:
11 """Ajoute un sous-orchestrateur (pour une hiérarchie plus profonde)."""
12 orchestrator.level = self.level + 1
13 self.sub_orchestrators[orchestrator.name] = orchestrator
14
15 async def delegate_task(self, task: str) -> str:
16 """Délègue la tâche au niveau de hiérarchie approprié."""
17 # Vérifie si la tâche nécessite un sous-orchestrateur
18 complexity = self._assess_complexity(task)
19
20 if complexity > 3 and self.sub_orchestrators:
21 # Délègue au sous-orchestrateur
22 sub_orch = self._select_sub_orchestrator(task)
23 return await sub_orch.delegate_task(task)
24 else:
25 # Exécute via ses propres subagents
26 return await self._execute_locally(task)delegate_task transmet la tâche vers le bas quand le score de complexité dépasse 3.
Les méthodes utilitaires évaluent la complexité et exécutent la tâche en local :
1 def _assess_complexity(self, task: str) -> int:
2 """Évalue la complexité de la tâche (1-5)."""
3 # Heuristique simple
4 complexity_indicators = [
5 "complete", "detailed", "multi-step",
6 "comprehensive", "elaborate"
7 ]
8 return sum(1 for ind in complexity_indicators if ind in task.lower()) + 1
9
10 def _select_sub_orchestrator(self, task: str) -> "HierarchicalOrchestrator":
11 """Sélectionne le sous-orchestrateur pour la tâche."""
12 # Peut être étendu avec une sélection intelligente
13 return list(self.sub_orchestrators.values())[0]
14
15 async def _execute_locally(self, task: str) -> str:
16 """Exécute la tâche localement."""
17 # Utilise ses propres subagents
18 results = []
19 for subagent in self.subagents.values():
20 subtask = SubagentTask(
21 description=task,
22 context=f"Level {self.level}",
23 expected_output="Task result"
24 )
25 result = await subagent.execute(subtask)
26 results.append(result.output)
27
28 return "\n".join(results)La complexité est le nombre de mots indicateurs plus un, et _select_sub_orchestrator prend pour l'instant toujours la première équipe.
L'exemple construit deux équipes sous l'orchestrateur principal :
1# Exemple d'utilisation de la hiérarchie
2async def hierarchical_example():
3 # Orchestrateur principal
4 main_orchestrator = HierarchicalOrchestrator("Main Orchestrator")
5
6 # Sous-orchestrateur pour la recherche
7 research_orchestrator = HierarchicalOrchestrator("Research Team")
8 research_orchestrator.subagents["researcher"] = ResearchSubagent(
9 "researcher", SubagentRole.RESEARCHER
10 )
11
12 # Sous-orchestrateur pour l'analyse
13 analysis_orchestrator = HierarchicalOrchestrator("Analysis Team")
14 analysis_orchestrator.subagents["analyst"] = AnalysisSubagent(
15 "analyst", SubagentRole.ANALYST
16 )
17
18 # Ajoute à la hiérarchie
19 main_orchestrator.add_sub_orchestrator(research_orchestrator)
20 main_orchestrator.add_sub_orchestrator(analysis_orchestrator)
21
22 # Exécute une tâche complexe
23 result = await main_orchestrator.delegate_task(
24 "Conduct a complete market research on Safari in East Africa"
25 )
26 print(result)Repère le piège : la tâche contient trop peu de mots indicateurs, donc elle reste chez l'orchestrateur principal, qui n'a pas de subagents à lui et renvoie un texte vide. Baisse le seuil ou donne-lui un subagent.
Communication entre subagents
Parfois, un spécialiste doit questionner un collègue. D'abord les types de messages :
1from dataclasses import dataclass, field
2from typing import Optional, List
3from datetime import datetime
4from enum import Enum
5
6class MessageType(Enum):
7 TASK = "task"
8 RESULT = "result"
9 QUERY = "query"
10 RESPONSE = "response"
11 ERROR = "error"
12
13@dataclass
14class AgentMessage:
15 """Message entre agents."""
16 sender: str
17 receiver: str
18 content: str
19 message_type: MessageType
20 timestamp: datetime = field(default_factory=datetime.now)
21 correlation_id: Optional[str] = None
22 metadata: dict = field(default_factory=dict)correlation_id relie une question à sa réponse, et field(default_factory=...) donne à chaque message son propre horodatage.
Un Message Bus est le canal par lequel les agents se parlent sans dépendances directes :
1class MessageBus:
2 """Bus de communication pour les agents."""
3
4 def __init__(self):
5 self.messages: List[AgentMessage] = []
6 self.subscribers: Dict[str, List[callable]] = {}
7
8 def publish(self, message: AgentMessage) -> None:
9 """Publie un message."""
10 self.messages.append(message)
11
12 # Notifie les abonnés
13 if message.receiver in self.subscribers:
14 for callback in self.subscribers[message.receiver]:
15 callback(message)
16
17 def subscribe(self, agent_name: str, callback: callable) -> None:
18 """Abonne un agent aux messages."""
19 if agent_name not in self.subscribers:
20 self.subscribers[agent_name] = []
21 self.subscribers[agent_name].append(callback)
22
23 def get_messages_for(self, agent_name: str) -> List[AgentMessage]:
24 """Récupère les messages d'un agent."""
25 return [m for m in self.messages if m.receiver == agent_name]Un agent s'abonne à son propre nom, et publish appelle les callbacks du destinataire. L'expéditeur n'a pas besoin de l'objet du destinataire, seulement de son nom, et c'est exactement ce que signifie un couplage faible.
Un subagent communicant répond aux requêtes et envoie des messages :
1class CommunicatingSubagent(Subagent):
2 """Subagent avec des capacités de communication."""
3
4 def __init__(self, name: str, role: SubagentRole, message_bus: MessageBus):
5 super().__init__(name, role)
6 self.message_bus = message_bus
7 self.message_bus.subscribe(name, self._handle_message)
8 self.pending_responses: Dict[str, str] = {}
9
10 def _handle_message(self, message: AgentMessage) -> None:
11 """Gère les messages entrants."""
12 if message.message_type == MessageType.QUERY:
13 # Répond à la requête
14 response = self._process_query(message.content)
15 self.send_message(
16 message.sender,
17 response,
18 MessageType.RESPONSE,
19 correlation_id=message.correlation_id
20 )
21 elif message.message_type == MessageType.RESPONSE:
22 # Enregistre la réponse
23 if message.correlation_id:
24 self.pending_responses[message.correlation_id] = message.content
25
26 def send_message(
27 self,
28 receiver: str,
29 content: str,
30 message_type: MessageType,
31 correlation_id: Optional[str] = None
32 ) -> None:
33 """Envoie un message à un autre agent."""
34 import uuid
35 message = AgentMessage(
36 sender=self.name,
37 receiver=receiver,
38 content=content,
39 message_type=message_type,
40 correlation_id=correlation_id or str(uuid.uuid4())
41 )
42 self.message_bus.publish(message)
43
44 def _process_query(self, query: str) -> str:
45 """Traite une requête provenant d'un autre agent."""
46 # L'implémentation dépend du rôle
47 return f"Response to: {query}"La réponse revient avec le même correlation_id, donc celui qui a posé la question sait à quoi elle répond.
Poser une question et attendre la réponse :
1 async def ask_other_agent(self, agent_name: str, question: str) -> str:
2 """Interroge un autre agent et attend une réponse."""
3 import uuid
4 correlation_id = str(uuid.uuid4())
5
6 self.send_message(
7 agent_name,
8 question,
9 MessageType.QUERY,
10 correlation_id
11 )
12
13 # Attend la réponse (avec timeout)
14 import asyncio
15 for _ in range(10):
16 if correlation_id in self.pending_responses:
17 return self.pending_responses.pop(correlation_id)
18 await asyncio.sleep(0.1)
19
20 return "Timeout - no response"Le bus appelle les callbacks de façon synchrone, donc la réponse est généralement déjà là à la première vérification, et la limite est d'une seconde.
Bonnes pratiques pour les subagents
Les principes de l'architecture des subagents réunis au même endroit :
1"""
2Best Practices for subagent architecture:
3
41. SEPARATION OF CONCERNS
5 - Each subagent has one clearly defined responsibility
6 - Avoid "god agents" that do everything
7
82. LOOSE COUPLING
9 - Subagents communicate through message bus
10 - No direct dependencies between subagents
11
123. SINGLE SOURCE OF TRUTH
13 - The orchestrator is the sole source of truth about task state
14 - Subagents report results to the orchestrator
15
164. GRACEFUL DEGRADATION
17 - System works even when one subagent fails
18 - Implement fallback strategies
19
205. OBSERVABILITY
21 - Log all interactions between agents
22 - Implement metrics and monitoring
23
246. SCALABILITY
25 - Subagents should be stateless
26 - Easy to add more instances of the same type
27
287. TESTING
29 - Test subagents in isolation
30 - Test orchestrator integration with subagents
31"""Fais attention au point sur l'absence d'état : nos subagents ont une memory, donc pour passer à l'échelle, déplace-la vers un stockage externe.
Le dernier élément est un orchestrateur tolérant aux erreurs :
1class RobustOrchestrator(AgentOrchestrator):
2 """Orchestrateur avec gestion des erreurs et fallback."""
3
4 async def execute_with_fallback(self, task: str) -> str:
5 """Exécute la tâche avec gestion des erreurs."""
6 try:
7 return await self.execute_task(task)
8 except Exception as e:
9 print(f"Main execution error: {e}")
10
11 # Fallback - approche plus simple
12 return await self._simple_execution(task)
13
14 async def _simple_execution(self, task: str) -> str:
15 """Exécution simple en fallback."""
16 response = client.chat.completions.create(
17 model=self.model,
18 messages=[
19 {"role": "system", "content": "You are a helpful assistant."},
20 {"role": "user", "content": task}
21 ]
22 )
23 return response.choices[0].message.contentQuand le pipeline complet échoue, le fallback interroge directement le modèle. Je te conseille de concevoir la hiérarchie à plat dès le départ et de n'ajouter des niveaux que lorsqu'il y a un vrai besoin.
Les subagents et les hiérarchies d'agents sont des modèles d'architecture puissants qui permettent de construire des systèmes d'IA complexes et évolutifs. Félicitations - tu as découvert des techniques d'IA avancées ! Dans le dernier module, tu vas créer un projet complet qui réunit toutes les compétences acquises !
Retiens : un bon orchestrateur, c'est un chef d'expédition qui distribue les tâches, rassemble les rapports et ne porte pas tous les sacs à dos lui-même.
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que sont les subagents dans une architecture IA ?
2. Quel est le rôle d'un orchestrateur dans un système de subagents ?
Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Tri vertical
Ordonne la hiérarchie d'agents typique de haut en bas :
- Éditeur de code
Implémente une classe Subagent avec ABC et @abstractmethod.
- Tri vertical
Ordonne les étapes d'exécution d'une tâche par l'orchestrateur :
- Éditeur de code
Implémente un AgentOrchestrator avec les méthodes register_subagent et execute_task.
- Éditeur de code
Construis un graphe Safari IA avec des nœuds agent, outil et approbation.
- Éditeur de code
Crée un HierarchicalOrchestrator avec des sub_orchestrators et des subagents.