OpenClaw has two cooperating guardrails for repetitive tool-call patterns:Documentation Index
Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
- Loop detection (
tools.loopDetection.enabled) — disabled by default. Watches the rolling tool-call history for repeated patterns and unknown-tool retries. - Post-compaction guard (
tools.loopDetection.postCompactionGuard) — enabled by default unlesstools.loopDetection.enabledis explicitlyfalse. Arms after every compaction-retry and aborts the run when the agent emits the same(tool, args, result)triple within the window.
tools.loopDetection block, but the post-compaction guard runs whenever the master switch is not explicitly off. Set tools.loopDetection.enabled: false to silence both surfaces.
Why this exists
- Detect repetitive sequences that do not make progress.
- Detect high-frequency no-result loops (same tool, same inputs, repeated errors).
- Detect specific repeated-call patterns for known polling tools.
- Prevent context-overflow then compaction then same-loop cycles from running indefinitely.
Configuration block
Global defaults, with every documented field shown:Field behavior
| Field | Default | Effect |
|---|---|---|
enabled | false | Master switch for the rolling-history detectors. Setting false also disables the post-compaction guard. |
historySize | 30 | Number of recent tool calls kept for analysis. |
warningThreshold | 10 | Threshold before a pattern is classified as warning-only. |
criticalThreshold | 20 | Threshold for blocking repetitive no-progress loop patterns. |
unknownToolThreshold | 10 | Block repeated calls to the same unavailable tool after this many misses. |
globalCircuitBreakerThreshold | 30 | Global no-progress breaker threshold across all detectors. |
detectors.genericRepeat | true | Warns on repeated same-tool + same-params patterns and blocks when the same calls also return identical outcomes. |
detectors.knownPollNoProgress | true | Detects known polling-like patterns with no state change. |
detectors.pingPong | true | Detects alternating ping-pong patterns. |
postCompactionGuard.windowSize | 3 | Number of post-compaction tool calls during which the guard stays armed and the count of identical triples that aborts the run. |
exec, no-progress checks compare stable command outcomes and ignore volatile runtime metadata such as duration, PID, session ID, and working directory. When a run id is available, recent tool-call history is evaluated only within that run so scheduled heartbeat cycles and fresh runs do not inherit stale loop counts from earlier runs.
Recommended setup
- For smaller models, set
enabled: trueand leave the thresholds at their defaults. Flagship models rarely need rolling-history detection and can leave the master switch atfalsewhile still benefiting from the post-compaction guard. - Keep thresholds ordered as
warningThreshold < criticalThreshold < globalCircuitBreakerThreshold. - If false positives occur:
- Raise
warningThresholdand/orcriticalThreshold. - Optionally raise
globalCircuitBreakerThreshold. - Disable only the specific detector causing issues (
detectors.<name>: false). - Reduce
historySizefor less strict historical context.
- Raise
- To disable everything (including the post-compaction guard), set
tools.loopDetection.enabled: falseexplicitly.
Post-compaction guard
When the runner completes a compaction-retry after a context-overflow, it arms a short-window guard that watches the next few tool calls. If the agent emits the same(toolName, argsHash, resultHash) triple multiple times within the window, the guard concludes that compaction did not break the loop and aborts the run with a compaction_loop_persisted error.
The guard is gated by the master tools.loopDetection.enabled flag with one twist: it stays enabled when the flag is unset or true and only deactivates when the flag is explicitly false. This is intentional. The guard exists to escape compaction loops that would otherwise burn unbounded tokens, so a no-config user still gets the protection.
- Lower
windowSizeis stricter (fewer attempts before abort). - Higher
windowSizegives the agent more recovery attempts. - The guard never aborts when results are changing, only when results are byte-identical across the window.
- It is intentionally narrow: it fires only in the immediate aftermath of a compaction-retry.
The post-compaction guard runs whenever the master flag is not explicitly
false, even if you never wrote a tools.loopDetection block. To verify, look for post-compaction guard armed for N attempts in the gateway log immediately after a compaction event.Logs and expected behavior
When a loop is detected, OpenClaw reports a loop event and either dampens or blocks the next tool-cycle depending on severity. This protects users from runaway token spend and lockups while preserving normal tool access.- Warnings come first.
- Suppression follows when patterns persist past the warning threshold.
- Critical thresholds block the next tool-cycle and surface a clear loop-detection reason in the run record.
- The post-compaction guard emits
compaction_loop_persistederrors with the offending tool name and identical-call count.
Related
Exec approvals
Allow/deny policy for shell execution.
Thinking levels
Reasoning effort levels and provider-policy interaction.
Sub-agents
Spawning isolated agents to bound runaway behavior.
Configuration reference
Full
tools.loopDetection schema and merging semantics.