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.

Quick Start

1

It's already on

from praisonaiagents import Agent

agent = Agent(
    instructions="You are a helpful assistant."
)

# Loop Guard is initialised automatically.
# No flag needed — every Agent gets one.
agent.start("Summarise the README")
2

Tune the thresholds

For power users, you can customize thresholds after agent creation:
from praisonaiagents import Agent
from praisonaiagents.escalation.loop_guard import LoopGuard, LoopGuardConfig

agent = Agent(instructions="Polls a slow status endpoint")

agent._loop_guard = LoopGuard(LoopGuardConfig(
    idempotent_warn_threshold=10,
    idempotent_block_threshold=20,
    idempotent_halt_threshold=30,
    max_time_per_turn=300.0,
))
3

Turn it off

Disabling Loop Guard removes the safety net for misbehaving tools.
from praisonaiagents import Agent
from praisonaiagents.escalation.loop_guard import LoopGuard, LoopGuardConfig

agent = Agent(instructions="Agent without safety guard")

agent._loop_guard = LoopGuard(LoopGuardConfig(enabled=False))

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

from praisonaiagents import Agent
from praisonaiagents.escalation.loop_guard import LoopGuard, LoopGuardConfig

agent = Agent(instructions="Monitor deployment status")

# Increase idempotent thresholds for polling scenarios
agent._loop_guard = LoopGuard(LoopGuardConfig(
    idempotent_warn_threshold=15,
    idempotent_block_threshold=25,
    idempotent_halt_threshold=40,
    max_time_per_turn=300.0,  # 5 minute timeout
))

Strict mode for production database agents

from praisonaiagents import Agent
from praisonaiagents.escalation.loop_guard import LoopGuard, LoopGuardConfig

agent = Agent(instructions="Manage user database")

# Lower mutating thresholds for safety
agent._loop_guard = LoopGuard(LoopGuardConfig(
    mutating_warn_threshold=2,
    mutating_block_threshold=3,
    mutating_halt_threshold=4,
))

Observability with stats

agent = Agent(instructions="Data processing agent")

# Get statistics for dashboards
stats = agent._loop_guard.get_stats()
print(f"Turn elapsed: {stats['turn_elapsed']}s")
print(f"Tool counts: {stats['tool_counts']}")

Relationship to Loop Detection

Loop Guard and Loop Detection are complementary features with different purposes:
FeatureOpt-in?WhereWhat it catches
Loop DetectionYesloop_detection=TrueIdentical-call, no-progress poll, ping-pong patterns
Loop GuardNo — always-on for every AgentPer-turn tool-call counts with idempotent-vs-mutating classification and graduated warnblockhalt responses
Loop Detection (opt-in) catches identical-argument / no-progress patterns at any frequency, while Loop Guard (always-on) catches high-frequency tool calls within a single turn regardless of argument variation. Use both for comprehensive protection.

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