Tools

Обнаружение циклов инструментов

OpenClaw использует два взаимодополняющих защитных механизма от повторяющихся шаблонов вызова инструментов, оба настраиваются в разделе tools.loopDetection:

  1. Обнаружение циклов (enabled) — по умолчанию отключено. Отслеживает скользящую историю вызовов инструментов для выявления повторяющихся шаблонов и повторных попыток вызова неизвестных инструментов.
  2. Защита после Compaction (postCompactionGuard) — включена, если enabled явно не задано как false. Активируется после каждой повторной попытки вслед за Compaction и прерывает выполнение, если агент повторяет одну и ту же тройку (tool, args, result) в пределах окна.

Задайте tools.loopDetection.enabled: false, чтобы отключить оба защитных механизма.

Зачем это нужно

  • Обнаруживать повторяющиеся последовательности, которые не приводят к прогрессу.
  • Обнаруживать высокочастотные циклы без результата (тот же инструмент, те же входные данные, повторяющиеся ошибки).
  • Обнаруживать определённые шаблоны повторных вызовов известных инструментов опроса.
  • Прерывать циклы «переполнение контекста -> Compaction -> тот же цикл», а не позволять им выполняться бесконечно.

Блок конфигурации

Глобальные значения по умолчанию со всеми документированными полями:

json5
{  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:

json5
{  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, которые иначе расходовали бы неограниченное количество токенов, поэтому защита действует даже для пользователя без соответствующей конфигурации.

json5
{  tools: {    loopDetection: {      // главный переключатель; задайте false, чтобы отключить защиту вместе с детекторами скользящей истории      enabled: true,      postCompactionGuard: {        windowSize: 3, // значение по умолчанию      },    },  },}
  • Меньшее значение windowSize делает проверку строже (меньше попыток до прерывания).
  • Большее значение windowSize предоставляет агенту больше попыток восстановления.
  • Защита никогда не прерывает выполнение, пока результаты меняются; она срабатывает только при побайтово идентичных результатах в пределах окна.
  • Она активируется только непосредственно после повторной попытки вслед за Compaction, но не в другие моменты выполнения.

Журналы и ожидаемое поведение

При обнаружении цикла OpenClaw записывает событие цикла в журнал и либо выдаёт предупреждение, либо блокирует следующий цикл работы с инструментами в зависимости от серьёзности, предотвращая неконтролируемый расход токенов и зависания и при этом сохраняя обычный доступ к инструментам.

  • Сначала выдаются предупреждения.
  • Если шаблон сохраняется после достижения порога предупреждений, начинается блокировка.
  • Критические пороговые значения блокируют следующий цикл работы с инструментами и добавляют понятную причину обнаружения цикла в запись выполнения.
  • Защита после Compaction выдаёт ошибки compaction_loop_persisted с указанием проблемного инструмента и количества идентичных вызовов.

Связанные материалы

Was this useful?
On this page

On this page