tools.loopDetection :
- Détection des boucles (
enabled) — désactivée par défaut. Surveille l’historique glissant des appels d’outils afin de repérer les schémas répétitifs et les nouvelles tentatives d’utilisation d’outils inconnus. - Garde post-Compaction (
postCompactionGuard) — activée tant queenabledn’est pas explicitement défini surfalse. Elle s’arme après chaque nouvelle tentative suivant une Compaction et interrompt l’exécution si l’agent répète le même triplet(outil, arguments, résultat)dans la fenêtre.
tools.loopDetection.enabled: false pour désactiver les deux garde-fous.
Pourquoi ce mécanisme existe
- Détecter les séquences répétitives qui ne produisent aucune progression.
- Détecter les boucles à haute fréquence sans résultat (même outil, mêmes entrées, erreurs répétées).
- Détecter des schémas spécifiques d’appels répétés pour les outils d’interrogation connus.
- Interrompre les cycles dépassement de contexte -> Compaction -> même boucle au lieu de les laisser s’exécuter indéfiniment.
Bloc de configuration
Valeurs globales par défaut, avec tous les champs documentés :agents.list[].tools.loopDetection) :
detectors et postCompactionGuard). Un agent ne doit donc définir que les
champs qu’il souhaite modifier.
Comportement des champs
Pour
exec, le hachage de l’absence de progression compare les résultats stables des commandes (état,
code de sortie, indicateur d’expiration du délai, sortie) et ignore les métadonnées d’exécution volatiles telles
que la durée, le PID, l’identifiant de session et le répertoire de travail. Les résultats d’envoi de messages
sortants sont hachés après suppression des identifiants volatils propres à chaque appel (identifiant du message, identifiant du fichier, horodatage),
afin qu’un résultat « envoyé » ne paraisse pas identique à un autre résultat « envoyé ».
Lorsqu’un identifiant d’exécution est disponible, l’historique n’est évalué qu’au sein de cette exécution ;
les cycles Heartbeat planifiés et les nouvelles exécutions n’héritent donc pas des anciens nombres de boucles
issus d’exécutions antérieures.
Configuration recommandée
- Pour les modèles plus petits, définissez
enabled: trueet conservez les seuils par défaut. Les modèles de pointe ont rarement besoin de la détection basée sur l’historique glissant et peuvent conserver le commutateur principal surfalsetout en bénéficiant de la garde post-Compaction. - Conservez les seuils dans l’ordre
warningThreshold < criticalThreshold < globalCircuitBreakerThreshold; à l’exécution,criticalThresholdetglobalCircuitBreakerThresholdsont augmentés si vous les définissez à une valeur inférieure ou égale au seuil qu’ils doivent dépasser. - En cas de faux positifs :
- Augmentez
warningThresholdet/oucriticalThreshold. - Augmentez éventuellement
globalCircuitBreakerThreshold. - Désactivez uniquement le détecteur précis à l’origine des problèmes (
detectors.<name>: false). - Réduisez
historySizepour raccourcir la fenêtre historique.
- Augmentez
- Pour tout désactiver, y compris la garde post-Compaction, définissez explicitement
tools.loopDetection.enabled: false.
Garde post-Compaction
Après une nouvelle tentative suivant une Compaction provoquée par un dépassement de contexte, l’exécuteur arme une garde à fenêtre courte pour les quelques appels d’outils suivants. Si l’agent émet le même triplet(toolName, argsHash, resultHash) postCompactionGuard.windowSize
fois dans cette fenêtre, la garde conclut que la Compaction n’a pas interrompu la
boucle et interrompt l’exécution avec une erreur compaction_loop_persisted.
La garde dépend du drapeau principal tools.loopDetection.enabled, avec une
particularité : elle reste activée lorsque le drapeau n’est pas défini ou vaut true, et ne se
désactive que lorsque le drapeau vaut explicitement false. Ce comportement est intentionnel : la garde
sert à échapper aux boucles de Compaction qui consommeraient autrement un nombre illimité de jetons.
Ainsi, même un utilisateur sans configuration bénéficie de cette protection.
- Une valeur
windowSizeplus faible est plus stricte (moins de tentatives avant l’interruption). - Une valeur
windowSizeplus élevée accorde davantage de tentatives de récupération à l’agent. - La garde n’interrompt jamais l’exécution tant que les résultats changent ; seuls des résultats identiques octet par octet dans toute la fenêtre la déclenchent.
- Elle ne s’arme que juste après une nouvelle tentative suivant une Compaction, et non à d’autres moments de l’exécution.
La garde post-Compaction s’exécute dès lors que le drapeau principal n’est pas explicitement défini sur
false, même si vous n’avez jamais écrit de bloc tools.loopDetection. Pour le vérifier, recherchez post-compaction guard armed for N attempts dans le journal du Gateway immédiatement après un événement de Compaction.Journaux et comportement attendu
Lorsqu’une boucle est détectée, OpenClaw consigne un événement de boucle et émet un avertissement ou bloque le cycle d’outil suivant selon sa gravité, afin d’éviter une consommation incontrôlée de jetons et les blocages tout en préservant l’accès normal aux outils.- Les avertissements surviennent en premier.
- Le blocage intervient lorsqu’un schéma persiste au-delà du seuil d’avertissement.
- Les seuils critiques bloquent le cycle d’outil suivant et indiquent clairement la raison de la détection de boucle dans l’enregistrement de l’exécution.
- La garde post-Compaction émet des erreurs
compaction_loop_persistedqui indiquent l’outil en cause et le nombre d’appels identiques.
Voir aussi
Approbations Exec
Politique d’autorisation et de refus pour l’exécution de commandes shell.
Niveaux de réflexion
Niveaux d’effort de raisonnement et interaction avec la politique du fournisseur.
Sous-agents
Création d’agents isolés pour limiter les comportements incontrôlés.
Référence de configuration
Schéma complet de
tools.loopDetection et sémantique de fusion.