Skip to main content
Loop Guard stops broken or misconfigured tools from burning tokens by counting per-turn calls and reacting differently to safe-to-repeat vs state-changing tools.
Looking for bot-to-bot reply-loop protection? See Bot-to-Bot Loop Protection — a separate gateway-layer primitive that caps how many exchanges a pair of bots can trade.
The user sends a task; Loop Guard tracks tool calls per turn and blocks runaway loops automatically.

Quick Start

1

It's already on

2

Tune the thresholds

For power users, you can customize thresholds after agent creation:
3

Turn it off

Disabling Loop Guard removes the safety net for misbehaving tools.

How It Works

DecisionEffectUser sees
ALLOWTool runs normallyNormal result
WARNTool runs; warning loggedResult + _loop_guard warning metadata
BLOCKTool execution replaced{"error": "[loop-guard] ...", "loop_blocked": True}
HALTNon-retryable exception raisedToolExecutionError propagates out

User Interaction Flow

Here’s what happens when an agent repeatedly calls the same tool: The agent experiences escalating resistance: warnings first, then blocked execution, then complete halt.

Tool Classification

Loop Guard categorizes tools into two buckets with different thresholds: Idempotent tools (safe to repeat): read_file, list_files, search_files, web_search, get_memory, git_status, git_log, db_query, etc. Mutating tools (state-changing): write_file, edit_file, delete_file, execute_code, shell, git_commit, git_push, sql_insert, install_package, etc.
If you can’t move your tool into the explicit set, name it well — Loop Guard’s heuristic looks for substrings like read, get, list, search, find, show, view, check (case-insensitive) to classify tools as idempotent.

Configuration Options

OptionTypeDefaultDescription
enabledboolTrueEnable/disable Loop Guard entirely
idempotent_warn_thresholdint5Warning threshold for idempotent tools
idempotent_block_thresholdint8Block threshold for idempotent tools
idempotent_halt_thresholdint12Halt threshold for idempotent tools
mutating_warn_thresholdint3Warning threshold for mutating tools
mutating_block_thresholdint5Block threshold for mutating tools
mutating_halt_thresholdint7Halt threshold for mutating tools
max_time_per_turnfloat120.0Maximum seconds per turn before timeout
no_progress_warnint4Warning threshold for no-progress detection
no_progress_haltint8Halt threshold for no-progress detection
GuardAction values: ALLOW, WARN, BLOCK, HALT LoopGuardDecision fields: action, code, message, metadata

What happens at each threshold

DecisionPre-execution effectPost-execution effectUser sees
ALLOWTool runs normallyCounter incrementedNormal result
WARNTool runs; warning loggedWarning appended/attached to result_loop_guard key in dict result, or [loop-guard] ... suffix on string result
BLOCKTool not executedCounter still incrementedTool result replaced with {"error": "[loop-guard] ...", "loop_blocked": True}
HALTToolExecutionError raised, is_retryable=FalseN/AException propagates out of agent.chat() / agent.start()

Common Patterns

Polling a slow status endpoint

Strict mode for production database agents

Observability with stats


Relationship to Loop Detection

Loop Detection is also always-on as of PR #3005 — every Agent runs result-aware name + args + result-hash detection in the same tool-execution path. The two are complementary: Loop Guard counts per-turn tool calls with idempotent-vs-mutating thresholds, while Loop Detection catches repeated identical fingerprints at any frequency and back-fills result hashes so polling with progress is not flagged. Both fire through the same blocked_result path, so trace spans, stream events, and AFTER_TOOL hooks stay consistent regardless of which one triggers.

Best Practices

The default thresholds (5/8/12 for idempotent, 3/5/7 for mutating) work well for most agents. Only customize when you have specific use cases like status polling or strict production environments.
Resist the urge to disable Loop Guard entirely. Instead, adjust thresholds to match your agent’s workflow. A monitoring agent might need higher idempotent thresholds, but even monitoring agents can benefit from mutating tool limits.
If your custom tool isn’t in the explicit IDEMPOTENT_TOOLS or MUTATING_TOOLS sets, name it descriptively. Tools named check_status, read_config, or search_logs will be classified as idempotent automatically.
Monitor your agents’ tool usage patterns with agent._loop_guard.get_stats(). High tool counts might indicate the agent is struggling with a task and needs different instructions or tools.

Loop Detection

Agent Autonomy