---
read_when:
    - Пользователь сообщает, что агенты зацикливаются, повторяя вызовы инструментов
    - Необходимо настроить защиту от повторяющихся вызовов
    - Вы редактируете политики инструментов и среды выполнения агента
    - После повторной попытки из-за переполнения контекста происходит прерывание `compaction_loop_persisted`
summary: Как включить и настроить защитные механизмы для обнаружения повторяющихся циклов вызова инструментов
title: Обнаружение циклов инструментов
x-i18n:
    generated_at: "2026-07-13T18:43:09Z"
    model: gpt-5.6
    postprocess_version: locale-links-v1
    prompt_version: 24
    provider: openai
    source_hash: fccbb81281b6c6921e6dad50d15295c1be3f59c664f2caed900bf3dce14bc40a
    source_path: tools/loop-detection.md
    workflow: 16
---

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, но не в другие
  моменты выполнения.

<Note>
  Защита после Compaction работает всегда, когда главный флаг явно не задан как `false`, даже если вы никогда не добавляли блок `tools.loopDetection`. Чтобы проверить это, найдите `post-compaction guard armed for N attempts` в журнале Gateway непосредственно после события Compaction.
</Note>

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

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

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

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

<CardGroup cols={2}>
  <Card title="Подтверждения выполнения" href="/ru/tools/exec-approvals" icon="shield">
    Политика разрешения и запрета выполнения команд оболочки.
  </Card>
  <Card title="Уровни рассуждения" href="/ru/tools/thinking" icon="brain">
    Уровни глубины рассуждений и взаимодействие с политикой провайдера.
  </Card>
  <Card title="Субагенты" href="/ru/tools/subagents" icon="users">
    Запуск изолированных агентов для ограничения неконтролируемого поведения.
  </Card>
  <Card title="Справочник по конфигурации" href="/ru/gateway/config-tools#toolsloopdetection" icon="gear">
    Полная схема `tools.loopDetection` и семантика объединения.
  </Card>
</CardGroup>
