Sub-agents
Les sub-agents sont des exécutions d’agent en arrière-plan lancées à partir d’une exécution d’agent existante. Ils s’exécutent dans leur propre session (agent:<agentId>:subagent:<uuid>) et, une fois terminés, annoncent leur résultat dans le canal de chat demandeur. Chaque exécution de sub-agent est suivie comme une tâche d’arrière-plan.
Commande slash
Utilisez/subagents pour inspecter ou contrôler les exécutions de sub-agent de la session en cours :
/subagents list/subagents kill <id|#|all>/subagents log <id|#> [limit] [tools]/subagents info <id|#>/subagents send <id|#> <message>/subagents steer <id|#> <message>/subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]
/focus <subagent-label|session-key|session-id|session-label>/unfocus/agents/session idle <duration|off>/session max-age <duration|off>
/subagents info affiche les métadonnées d’exécution (statut, horodatages, id de session, chemin de transcription, nettoyage).
Utilisez sessions_history pour une vue de rappel bornée et filtrée pour la sécurité ; inspectez le chemin de transcription sur disque lorsque vous avez besoin de la transcription brute complète.
Comportement du lancement
/subagents spawn démarre un sub-agent d’arrière-plan en tant que commande utilisateur, et non comme relais interne, et envoie une mise à jour finale d’achèvement dans le chat demandeur lorsque l’exécution se termine.
- La commande de lancement est non bloquante ; elle renvoie immédiatement un id d’exécution.
- À l’achèvement, le sub-agent annonce un message de résumé/résultat dans le canal de chat demandeur.
- La distribution de l’achèvement est basée sur le push. Une fois lancé, ne sondez pas
/subagents list,sessions_listousessions_historyen boucle juste pour attendre la fin ; inspectez le statut uniquement à la demande pour le débogage ou l’intervention. - À l’achèvement, OpenClaw ferme au mieux les onglets/processus de navigateur suivis ouverts par cette session de sub-agent avant que le flux de nettoyage de l’annonce continue.
- Pour les lancements manuels, la distribution est résiliente :
- OpenClaw essaie d’abord une distribution
agentdirecte avec une clé d’idempotence stable. - Si la distribution directe échoue, il bascule vers le routage par file d’attente.
- Si le routage par file d’attente n’est toujours pas disponible, l’annonce est réessayée avec un court backoff exponentiel avant l’abandon final.
- OpenClaw essaie d’abord une distribution
- La distribution de l’achèvement conserve la route du demandeur résolue :
- les routes d’achèvement liées à un fil ou à une conversation sont prioritaires lorsqu’elles sont disponibles
- si l’origine de l’achèvement ne fournit qu’un canal, OpenClaw complète la cible/le compte manquants à partir de la route résolue de la session demandeuse (
lastChannel/lastTo/lastAccountId) afin que la distribution directe fonctionne quand même
- Le transfert d’achèvement vers la session demandeuse est un contexte interne généré à l’exécution (et non un texte rédigé par l’utilisateur) et inclut :
Result(dernier texte visible de réponseassistant, sinon dernier texte assainitool/toolResult)Status(completed successfully/failed/timed out/unknown)- des statistiques compactes d’exécution/tokens
- une instruction de distribution demandant à l’agent demandeur de reformuler avec une voix d’assistant normale (sans transmettre les métadonnées internes brutes)
--modelet--thinkingremplacent les valeurs par défaut pour cette exécution spécifique.- Utilisez
info/logpour inspecter les détails et la sortie après l’achèvement. /subagents spawnest un mode ponctuel (mode: "run"). Pour des sessions persistantes liées à un fil, utilisezsessions_spawnavecthread: trueetmode: "session".- Pour les sessions de harnais ACP (Codex, Claude Code, Gemini CLI), utilisez
sessions_spawnavecruntime: "acp"et voir ACP Agents.
- Paralléliser le travail de type « recherche / tâche longue / outil lent » sans bloquer l’exécution principale.
- Garder les sub-agents isolés par défaut (séparation de session + sandboxing optionnel).
- Rendre la surface d’outils difficile à mal utiliser : les sub-agents n’obtiennent pas les outils de session par défaut.
- Prendre en charge une profondeur d’imbrication configurable pour les modèles d’orchestrateur.
agents.defaults.subagents.model ou via des remplacements par agent.
Outil
Utilisezsessions_spawn :
- Démarre une exécution de sub-agent (
deliver: false, lane globale :subagent) - Exécute ensuite une étape d’annonce et publie la réponse d’annonce dans le canal de chat demandeur
- Modèle par défaut : hérite de l’appelant sauf si vous définissez
agents.defaults.subagents.model(ouagents.list[].subagents.modelpar agent) ; une valeur explicitesessions_spawn.modelreste prioritaire. - Niveau de réflexion par défaut : hérite de l’appelant sauf si vous définissez
agents.defaults.subagents.thinking(ouagents.list[].subagents.thinkingpar agent) ; une valeur explicitesessions_spawn.thinkingreste prioritaire. - Délai d’exécution par défaut : si
sessions_spawn.runTimeoutSecondsest omis, OpenClaw utiliseagents.defaults.subagents.runTimeoutSecondslorsqu’il est défini ; sinon, il retombe à0(pas de délai d’expiration).
task(obligatoire)label?(facultatif)agentId?(facultatif ; lance sous un autre id d’agent si autorisé)model?(facultatif ; remplace le modèle du sub-agent ; les valeurs invalides sont ignorées et le sub-agent s’exécute sur le modèle par défaut avec un avertissement dans le résultat de l’outil)thinking?(facultatif ; remplace le niveau de réflexion pour l’exécution du sub-agent)runTimeoutSeconds?(par défaut :agents.defaults.subagents.runTimeoutSecondslorsqu’il est défini, sinon0; lorsqu’il est défini, l’exécution du sub-agent est interrompue après N secondes)thread?(par défautfalse; lorsqu’il vauttrue, demande une liaison au fil du canal pour cette session de sub-agent)mode?(run|session)- la valeur par défaut est
run - si
thread: trueetmodeest omis, la valeur par défaut devientsession mode: "session"nécessitethread: true
- la valeur par défaut est
cleanup?(delete|keep, par défautkeep)sandbox?(inherit|require, par défautinherit;requirerejette le lancement à moins que le runtime enfant cible soit sandboxé)sessions_spawnn’accepte pas les paramètres de distribution de canal (target,channel,to,threadId,replyTo,transport). Pour la distribution, utilisezmessage/sessions_senddepuis l’exécution lancée.
Sessions liées à un fil
Lorsque les liaisons de fil sont activées pour un canal, un sub-agent peut rester lié à un fil afin que les messages utilisateur de suivi dans ce fil continuent d’être routés vers la même session de sub-agent.Canaux prenant en charge les fils
- Discord (actuellement le seul canal pris en charge) : prend en charge les sessions persistantes de sub-agent liées à un fil (
sessions_spawnavecthread: true), les contrôles manuels de fil (/focus,/unfocus,/agents,/session idle,/session max-age) et les clés d’adaptateurchannels.discord.threadBindings.enabled,channels.discord.threadBindings.idleHours,channels.discord.threadBindings.maxAgeHoursetchannels.discord.threadBindings.spawnSubagentSessions.
- Lancez avec
sessions_spawnen utilisantthread: true(et éventuellementmode: "session"). - OpenClaw crée ou lie un fil à cette cible de session dans le canal actif.
- Les réponses et messages de suivi dans ce fil sont routés vers la session liée.
- Utilisez
/session idlepour inspecter/mettre à jour le retrait automatique du focus lié à l’inactivité et/session max-agepour contrôler la limite stricte. - Utilisez
/unfocuspour détacher manuellement.
/focus <target>lie le fil en cours (ou en crée un) à une cible de sub-agent/session./unfocussupprime la liaison pour le fil actuellement lié./agentsliste les exécutions actives et l’état de liaison (thread:<id>ouunbound)./session idleet/session max-agene fonctionnent que pour les fils liés focalisés.
- Valeur par défaut globale :
session.threadBindings.enabled,session.threadBindings.idleHours,session.threadBindings.maxAgeHours - Le remplacement de canal et les clés de liaison automatique au lancement sont spécifiques à l’adaptateur. Voir Canaux prenant en charge les fils ci-dessus.
agents.list[].subagents.allowAgents: liste des ids d’agents qui peuvent être ciblés viaagentId(["*"]pour autoriser n’importe lequel). Par défaut : seulement l’agent demandeur.agents.defaults.subagents.allowAgents: allow-list d’agents cibles par défaut utilisée lorsque l’agent demandeur ne définit pas sa propre valeursubagents.allowAgents.- Garde d’héritage du sandbox : si la session demandeuse est sandboxée,
sessions_spawnrejette les cibles qui s’exécuteraient sans sandbox. agents.defaults.subagents.requireAgentId/agents.list[].subagents.requireAgentId: lorsque vrai, bloque les appelssessions_spawnqui omettentagentId(force une sélection explicite du profil). Par défaut : false.
- Utilisez
agents_listpour voir quels ids d’agents sont actuellement autorisés poursessions_spawn.
- Les sessions de sub-agent sont automatiquement archivées après
agents.defaults.subagents.archiveAfterMinutes(par défaut : 60). - L’archivage utilise
sessions.deleteet renomme la transcription en*.deleted.<timestamp>(même dossier). cleanup: "delete"archive immédiatement après l’annonce (tout en conservant la transcription via renommage).- L’archivage automatique est au mieux ; les temporisateurs en attente sont perdus si la gateway redémarre.
runTimeoutSecondsne déclenche pas d’archivage automatique ; il arrête seulement l’exécution. La session reste jusqu’à l’archivage automatique.- L’archivage automatique s’applique de la même manière aux sessions de profondeur 1 et 2.
- Le nettoyage du navigateur est distinct du nettoyage d’archivage : les onglets/processus de navigateur suivis sont fermés au mieux lorsque l’exécution se termine, même si l’enregistrement de transcription/session est conservé.
Sub-agents imbriqués
Par défaut, les sub-agents ne peuvent pas lancer leurs propres sub-agents (maxSpawnDepth: 1). Vous pouvez activer un niveau d’imbrication en définissant maxSpawnDepth: 2, ce qui autorise le modèle d’orchestrateur : principal → sub-agent orchestrateur → sub-sub-agents workers.
Comment l’activer
Niveaux de profondeur
| Depth | Forme de clé de session | Rôle | Peut lancer ? |
|---|---|---|---|
| 0 | agent:<id>:main | Agent principal | Toujours |
| 1 | agent:<id>:subagent:<uuid> | Sub-agent (orchestrateur si profondeur 2 autorisée) | Seulement si maxSpawnDepth >= 2 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | Sub-sub-agent (worker feuille) | Jamais |
Chaîne d’annonce
Les résultats remontent la chaîne :- Le worker de profondeur 2 se termine → annonce à son parent (orchestrateur de profondeur 1)
- L’orchestrateur de profondeur 1 reçoit l’annonce, synthétise les résultats, se termine → annonce au principal
- L’agent principal reçoit l’annonce et la distribue à l’utilisateur
- Démarrez le travail enfant une seule fois et attendez les événements d’achèvement au lieu de construire des boucles de sondage autour de
sessions_list,sessions_history,/subagents listou des commandesexecavec sommeil. - Si un événement d’achèvement enfant arrive après que vous avez déjà envoyé la réponse finale, le bon suivi est le jeton silencieux exact
NO_REPLY/no_reply.
Politique d’outils par profondeur
- Le rôle et la portée de contrôle sont écrits dans les métadonnées de session au moment du lancement. Cela évite que des clés de session plates ou restaurées ne récupèrent accidentellement des privilèges d’orchestrateur.
- Profondeur 1 (orchestrateur, lorsque
maxSpawnDepth >= 2) : obtientsessions_spawn,subagents,sessions_list,sessions_historyafin de pouvoir gérer ses enfants. Les autres outils de session/système restent refusés. - Profondeur 1 (feuille, lorsque
maxSpawnDepth == 1) : aucun outil de session (comportement par défaut actuel). - Profondeur 2 (worker feuille) : aucun outil de session —
sessions_spawnest toujours refusé en profondeur 2. Ne peut pas lancer d’autres enfants.
Limite de lancement par agent
Chaque session d’agent (à n’importe quelle profondeur) peut avoir au plusmaxChildrenPerAgent (par défaut : 5) enfants actifs à la fois. Cela empêche une prolifération incontrôlée depuis un seul orchestrateur.
Arrêt en cascade
L’arrêt d’un orchestrateur de profondeur 1 arrête automatiquement tous ses enfants de profondeur 2 :/stopdans le chat principal arrête tous les agents de profondeur 1 et cascade vers leurs enfants de profondeur 2./subagents kill <id>arrête un sub-agent spécifique et cascade vers ses enfants./subagents kill allarrête tous les sub-agents du demandeur et cascade.
Authentification
L’authentification du sub-agent est résolue par id d’agent, et non par type de session :- La clé de session du sub-agent est
agent:<agentId>:subagent:<uuid>. - Le stockage d’authentification est chargé depuis le
agentDirde cet agent. - Les profils d’authentification de l’agent principal sont fusionnés comme secours ; les profils de l’agent remplacent les profils principaux en cas de conflit.
Annonce
Les sub-agents remontent leurs résultats via une étape d’annonce :- L’étape d’annonce s’exécute dans la session du sub-agent (pas dans la session demandeuse).
- Si le sub-agent répond exactement
ANNOUNCE_SKIP, rien n’est publié. - Si le dernier texte assistant est exactement le jeton silencieux
NO_REPLY/no_reply, la sortie d’annonce est supprimée même si une progression visible antérieure existait. - Sinon, la distribution dépend de la profondeur du demandeur :
- les sessions demandeuses de niveau supérieur utilisent un appel
agentde suivi avec distribution externe (deliver=true) - les sessions demandeuses de sub-agent imbriquées reçoivent une injection de suivi interne (
deliver=false) afin que l’orchestrateur puisse synthétiser les résultats enfants en session - si une session demandeuse de sub-agent imbriquée a disparu, OpenClaw bascule vers le demandeur de cette session lorsque disponible
- les sessions demandeuses de niveau supérieur utilisent un appel
- Pour les sessions demandeuses de niveau supérieur, la distribution directe en mode achèvement résout d’abord toute route liée à une conversation/un fil et tout remplacement de hook, puis complète les champs cibles de canal manquants à partir de la route stockée de la session demandeuse. Cela maintient les achèvements dans le bon chat/sujet même lorsque l’origine de l’achèvement n’identifie que le canal.
- L’agrégation des achèvements enfants est limitée à l’exécution demandeuse actuelle lors de la construction des constats d’achèvement imbriqués, empêchant que d’anciennes sorties d’enfants d’exécutions précédentes ne fuient dans l’annonce actuelle.
- Les réponses d’annonce préservent le routage de fil/sujet lorsque disponible sur les adaptateurs de canal.
- Le contexte d’annonce est normalisé en un bloc d’événement interne stable :
- source (
subagentoucron) - clé/id de session enfant
- type d’annonce + étiquette de tâche
- ligne d’état dérivée du résultat d’exécution (
success,error,timeoutouunknown) - contenu du résultat sélectionné à partir du dernier texte assistant visible, sinon dernier texte assaini
tool/toolResult - une instruction de suivi décrivant quand répondre ou rester silencieux
- source (
Statusn’est pas déduit de la sortie du modèle ; il provient des signaux de résultat d’exécution.- En cas de délai d’expiration, si l’enfant n’est allé que jusqu’aux appels d’outil, l’annonce peut condenser cet historique en un court résumé de progression partielle au lieu de rejouer la sortie d’outil brute.
- Runtime (par ex.
runtime 5m12s) - Utilisation de tokens (entrée/sortie/total)
- Coût estimé lorsque la tarification du modèle est configurée (
models.providers.*.models[].cost) sessionKey,sessionIdet chemin de transcription (afin que l’agent principal puisse récupérer l’historique viasessions_historyou inspecter le fichier sur disque)- Les métadonnées internes sont destinées uniquement à l’orchestration ; les réponses visibles par l’utilisateur doivent être réécrites avec une voix d’assistant normale.
sessions_history est la voie d’orchestration la plus sûre :
- le rappel assistant est d’abord normalisé :
- les balises de réflexion sont supprimées
- les blocs d’échafaudage
<relevant-memories>/<relevant_memories>sont supprimés - les blocs de charge utile XML d’appel d’outil en texte brut tels que
<tool_call>...</tool_call>,<function_call>...</function_call>,<tool_calls>...</tool_calls>et<function_calls>...</function_calls>sont supprimés, y compris les charges utiles tronquées qui ne se ferment jamais proprement - l’échafaudage dégradé d’appel d’outil/résultat et les marqueurs de contexte historique sont supprimés
- les jetons de contrôle de modèle divulgués comme
<|assistant|>, d’autres jetons ASCII<|...|>et les variantes pleine largeur<|...|>sont supprimés - le XML d’appel d’outil MiniMax mal formé est supprimé
- le texte de type identifiant/token est caviardé
- les blocs longs peuvent être tronqués
- les historiques très volumineux peuvent supprimer des lignes plus anciennes ou remplacer une ligne trop volumineuse par
[sessions_history omitted: message too large] - l’inspection brute de la transcription sur disque reste le recours lorsque vous avez besoin de la transcription complète octet par octet
Politique d’outils (outils des sub-agents)
Par défaut, les sub-agents obtiennent tous les outils sauf les outils de session et les outils système :sessions_listsessions_historysessions_sendsessions_spawn
sessions_history reste ici aussi une vue de rappel bornée et assainie ; ce n’est pas un dump brut de transcription.
Lorsque maxSpawnDepth >= 2, les sub-agents orchestrateurs de profondeur 1 reçoivent en plus sessions_spawn, subagents, sessions_list et sessions_history afin de pouvoir gérer leurs enfants.
Remplacez via la configuration :
Concurrence
Les sub-agents utilisent une lane de file dédiée dans le processus :- Nom de la lane :
subagent - Concurrence :
agents.defaults.subagents.maxConcurrent(par défaut8)
Arrêt
- L’envoi de
/stopdans le chat demandeur interrompt la session demandeuse et arrête toutes les exécutions actives de sub-agent lancées depuis celle-ci, avec cascade vers les enfants imbriqués. /subagents kill <id>arrête un sub-agent spécifique et cascade vers ses enfants.
Limites
- L’annonce des sub-agents est au mieux. Si la gateway redémarre, le travail en attente de « retour d’annonce » est perdu.
- Les sub-agents partagent toujours les mêmes ressources de processus gateway ; traitez
maxConcurrentcomme une soupape de sécurité. sessions_spawnest toujours non bloquant : il renvoie immédiatement{ status: "accepted", runId, childSessionKey }.- Le contexte des sub-agents injecte uniquement
AGENTS.md+TOOLS.md(pas deSOUL.md,IDENTITY.md,USER.md,HEARTBEAT.mdniBOOTSTRAP.md). - La profondeur maximale d’imbrication est 5 (plage
maxSpawnDepth: 1–5). La profondeur 2 est recommandée pour la plupart des cas d’usage. maxChildrenPerAgentlimite le nombre d’enfants actifs par session (par défaut : 5, plage : 1–20).