Tools
Виявлення циклів інструментів
OpenClaw має два узгоджені запобіжники проти повторюваних шаблонів викликів інструментів,
обидва налаштовуються в tools.loopDetection:
- Виявлення циклів (
enabled) — типово вимкнено. Відстежує ковзну історію викликів інструментів, щоб виявляти повторювані шаблони та повторні спроби виклику невідомих інструментів. - Запобіжник після Compaction (
postCompactionGuard) — увімкнений, якщоenabledявно не встановлено вfalse. Активується після кожної повторної спроби після Compaction і перериває виконання, якщо агент повторює ту саму трійку(інструмент, аргументи, результат)у межах вікна.
Установіть tools.loopDetection.enabled: false, щоб вимкнути обидва запобіжники.
Навіщо це потрібно
- Виявляти повторювані послідовності, які не дають прогресу.
- Виявляти високочастотні цикли без результату (той самий інструмент, ті самі вхідні дані, повторювані помилки).
- Виявляти певні шаблони повторюваних викликів для відомих інструментів опитування.
- Переривати цикли переповнення контексту -> Compaction -> той самий цикл, а не дозволяти їм виконуватися нескінченно.
Блок конфігурації
Глобальні типові значення з усіма задокументованими полями:
{ tools: { loopDetection: { enabled: false, // головний перемикач детекторів ковзної історії historySize: 30, warningThreshold: 10, criticalThreshold: 20, unknownToolThreshold: 10, globalCircuitBreakerThreshold: 30, detectors: { genericRepeat: true, knownPollNoProgress: true, pingPong: true, }, postCompactionGuard: { windowSize: 3, // активується після повторної спроби після Compaction; працює, якщо enabled явно не дорівнює false }, }, },}Перевизначення для окремого агента (необов’язково, у agents.list[].tools.loopDetection):
{ agents: { list: [ { id: "safe-runner", tools: { loopDetection: { enabled: true, warningThreshold: 8, criticalThreshold: 16, }, }, }, ], },}Налаштування окремого агента накладаються на глобальний блок поле за полем (включно з вкладеними
detectors і postCompactionGuard), тому агенту потрібно задавати лише
поля, які він хоче змінити.
Поведінка полів
| Поле | Типове значення | Вплив |
|---|---|---|
enabled |
false |
Головний перемикач детекторів ковзної історії. false також вимикає запобіжник після Compaction. |
historySize |
30 |
Кількість останніх викликів інструментів, що зберігаються для аналізу. |
warningThreshold |
10 |
Кількість повторів, після якої шаблон класифікується як такий, що потребує лише попередження. |
criticalThreshold |
20 |
Кількість повторів для блокування шаблону циклу без прогресу. У разі помилкового налаштування середовище виконання підвищує це значення понад warningThreshold. |
unknownToolThreshold |
10 |
Блокує повторні виклики того самого недоступного інструмента після такої кількості невдалих спроб. Не залежить від detectors. |
globalCircuitBreakerThreshold |
30 |
Глобальний переривач циклів без прогресу для всіх детекторів. У разі помилкового налаштування середовище виконання підвищує це значення понад criticalThreshold. Не залежить від detectors. |
detectors.genericRepeat |
true |
Попереджає про повторні виклики того самого інструмента з тими самими аргументами; блокує, коли ці виклики також повертають однакові результати. |
detectors.knownPollNoProgress |
true |
Виявляє відомі шаблони опитування без прогресу (process з action: "poll"/"log", command_status). |
detectors.pingPong |
true |
Виявляє почергові шаблони без прогресу між двома викликами. |
postCompactionGuard.windowSize |
3 |
Кількість спроб, протягом яких запобіжник залишається активним після Compaction, а також кількість однакових трійок, що спричиняє переривання виконання. |
Для exec хешування відсутності прогресу порівнює стабільні результати команд (стан,
код завершення, ознаку перевищення часу очікування, виведення) та ігнорує мінливі метадані середовища виконання, як-от
тривалість, PID, ідентифікатор сеансу та робочий каталог. Результати надсилання вихідних повідомлень
хешуються без мінливих ідентифікаторів окремих викликів (ідентифікатора повідомлення, ідентифікатора файлу, часової позначки),
щоб результат «надіслано» не виглядав однаковим із результатом іншого надсилання.
Коли доступний ідентифікатор виконання, історія оцінюється лише в межах цього виконання,
тому заплановані цикли Heartbeat і нові виконання не успадковують застарілі лічильники циклів
від попередніх виконань.
Рекомендоване налаштування
- Для менших моделей установіть
enabled: trueі залиште порогові значення типовими. Провідним моделям детекція за ковзною історією потрібна рідко, тому можна залишити головний перемикач у станіfalse, водночас користуючись перевагами запобіжника після Compaction. - Зберігайте такий порядок порогових значень:
warningThreshold < criticalThreshold < globalCircuitBreakerThreshold; середовище виконання збільшуєcriticalThresholdіglobalCircuitBreakerThreshold, якщо ви встановите їх на рівні або нижче порогового значення, яке вони мають перевищувати. - Якщо виникають хибні спрацювання:
- Збільште
warningThresholdта/абоcriticalThreshold. - За потреби збільште
globalCircuitBreakerThreshold. - Вимкніть лише конкретний детектор, який спричиняє проблеми (
detectors.<name>: false). - Зменште
historySize, щоб скоротити історичне вікно.
- Збільште
- Щоб вимкнути все, включно із запобіжником після Compaction, явно встановіть
tools.loopDetection.enabled: false.
Запобіжник після Compaction
Після повторної спроби з Compaction унаслідок переповнення контексту виконавець активує
запобіжник із коротким вікном для кількох наступних викликів інструментів. Якщо агент видає ту саму
трійку (toolName, argsHash, resultHash) postCompactionGuard.windowSize
разів у межах цього вікна, запобіжник робить висновок, що Compaction не перервала
цикл, і перериває виконання з помилкою compaction_loop_persisted.
Запобіжник керується головним прапорцем tools.loopDetection.enabled з однією
особливістю: він залишається увімкненим, коли прапорець не задано або має значення true,
і вимикається лише тоді, коли прапорець явно встановлено в false. Це зроблено навмисно — запобіжник
дає змогу вийти з циклів Compaction, які інакше витрачали б необмежену кількість токенів,
тому навіть користувач без конфігурації отримує цей захист.
{ tools: { loopDetection: { // головний перемикач; установіть false, щоб вимкнути запобіжник разом із ковзними детекторами enabled: true, postCompactionGuard: { windowSize: 3, // типове значення }, }, },}- Менше значення
windowSizeє суворішим (менше спроб до переривання). - Більше значення
windowSizeдає агенту більше спроб відновлення. - Запобіжник ніколи не перериває виконання, доки результати змінюються; його активують лише побайтово однакові результати в межах вікна.
- Він активується лише одразу після повторної спроби з Compaction, а не в інших точках виконання.
Журнали та очікувана поведінка
Коли виявлено цикл, OpenClaw записує подію циклу до журналу та або попереджає, або блокує наступний цикл роботи інструмента залежно від серйозності, захищаючи від неконтрольованого витрачання токенів і зависань, водночас зберігаючи звичайний доступ до інструментів.
- Спочатку з’являються попередження.
- Блокування відбувається, коли шаблон зберігається після перевищення порога попередження.
- Критичні порогові значення блокують наступний цикл роботи інструмента та додають чітку причину виявлення циклу до запису про виконання.
- Запобіжник після Compaction генерує помилки
compaction_loop_persisted, указуючи проблемний інструмент і кількість однакових викликів.
Пов’язані матеріали
Політика дозволу та заборони виконання команд оболонки.
Рівні глибини міркування та взаємодія з політикою постачальника.
Створення ізольованих агентів для обмеження неконтрольованої поведінки.
Повна схема tools.loopDetection і семантика об’єднання.