Endlosschleifen erkennen und unterbrechen
Schutz vor zu vielen Iterationen, Erkennung wiederholter Aktionen und Circuit Breaker für Schleifen.
Endlosschleifen erkennen und unterbrechen ist eine kostenlose AI Agents-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Agents-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Die Gefahr von Endlosschleifen
Ein Agent in einer Endlosschleife verbraucht Tokens, blockiert Ressourcen und erzeugt keine brauchbare Ausgabe. Im Produktivbetrieb führt das direkt zu verschwendetem Geld und frustrierten Benutzern.
Drei Mechanismen wirken zusammen, um Endlosschleifen zu verhindern: maximale Iterationslimits, Erkennung wiederholter Aktionen und Zeitüberschreitungen.
Schutzmechanismus 1: Limit für maximale Iterationszahl
Der einfachste und wichtigste Schutzmechanismus ist ein festes Schrittlimit. Jede Agentenschleife muss über eines verfügen. Wenn das Limit erreicht ist, gibt der Agent entweder seine derzeit beste Antwort oder eine ausdrückliche Fehlermeldung zurück.
MAX_ITERATIONS = 20
def run_agent(query: str) -> dict:
history = []
for step in range(1, MAX_ITERATIONS + 1):
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer'], 'steps': step}
result = execute_tool(action['tool'], action['args'])
history.append({'step': step, 'tool': action['tool'], 'result': result})
# Hard stop — max iterations reached
return {
'status': 'max_iterations_reached',
'answer': None,
'steps': MAX_ITERATIONS
}Schutzmechanismus 2: Wiederholte Aktionen erkennen
Wiederholte Aktionen sind das typische Kennzeichen einer Endlosschleife. Verfolgen Sie den Verlauf von Paaren aus (Werkzeugname, Argumente). Wenn dasselbe Paar mehr als N-mal vorkommt, steckt der Agent fest — brechen Sie die Schleife ab und fügen Sie eine Fehlermeldung ein.
import hashlib
import json
def action_hash(tool_name: str, args: dict) -> str:
payload = json.dumps({'tool': tool_name, 'args': args}, sort_keys=True)
return hashlib.md5(payload.encode()).hexdigest()
def run_agent_with_repeat_detection(query: str) -> dict:
history = []
action_counts = {}
for step in range(1, 21):
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
key = action_hash(action['tool'], action['args'])
action_counts[key] = action_counts.get(key, 0) + 1
if action_counts[key] > 2: # seen this exact action more than twice
history.append({
'role': 'system',
'content': f'You have called {action["tool"]} with the same arguments {action_counts[key]} times. '
f'This approach is not working. Try a completely different strategy or state what you know so far.'
})
continue
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
return {'status': 'loop_detected', 'answer': None}Wiederholte Aktionen in einem Fenster verfolgen
Statt Zählungen über die gesamte Laufzeit zu verfolgen, erkennen Sie Wiederholungen in einem gleitenden Fenster der letzten N Schritte. So werden Schleifen erkannt, die leicht variieren, aber sich über einen kurzen Zeitraum wiederholen.
from collections import deque
def is_cycling(recent_actions: deque, window: int = 6) -> bool:
if len(recent_actions) < window:
return False
# Check if the last window/2 actions repeat the first window/2
half = window // 2
first_half = list(recent_actions)[:half]
second_half = list(recent_actions)[half:window]
return first_half == second_half
# In the agent loop:
# recent_actions = deque(maxlen=6)
# recent_actions.append(action_hash(tool, args))
# if is_cycling(recent_actions):
# print('Cycling detected — breaking loop')
# break
recent = deque(['a', 'b', 'a', 'b'], maxlen=6)
print(is_cycling(recent, window=4)) # True — cycling detectedSchutzmechanismus 3: Echtzeit-Timeout mit signal.alarm
Auf Unix-Systemen löst signal.alarm() nach einer festgelegten Anzahl von Sekunden ein SIGALRM aus. Das ermöglicht ein festes Timeout, selbst wenn die Agentenschleife in einem langsamen Werkzeugaufruf blockiert ist.
import signal
class AgentTimeout(Exception):
pass
def timeout_handler(signum, frame):
raise AgentTimeout('Agent exceeded time limit')
def run_agent_with_signal_timeout(query: str, timeout_seconds: int = 60) -> dict:
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(timeout_seconds) # set the alarm
try:
result = run_core_agent_loop(query)
signal.alarm(0) # cancel the alarm on success
return result
except AgentTimeout:
signal.alarm(0)
return {'status': 'timeout', 'answer': None}
except Exception as e:
signal.alarm(0)
raise
# Note: signal.alarm is Unix-only (Linux/Mac)Timeout mit threading.Timer (plattformübergreifend)
threading.Timer funktioniert auf allen Plattformen einschließlich Windows. Setzen Sie nach Ablauf des Timeouts ein Flag — die Agentenschleife prüft das Flag und beendet sich, wenn es gesetzt ist.
import threading
def run_agent_with_timer_timeout(query: str, timeout_seconds: int = 60) -> dict:
timed_out = threading.Event()
def set_timeout():
timed_out.set()
timer = threading.Timer(timeout_seconds, set_timeout)
timer.start()
history = []
try:
for step in range(1, 21):
if timed_out.is_set():
return {'status': 'timeout', 'answer': None, 'steps': step}
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
finally:
timer.cancel() # always cancel if done before timeout
return {'status': 'max_steps', 'answer': None}Asynchrones Timeout mit asyncio.wait_for
Verwenden Sie in asynchronen Agentenarchitekturen asyncio.wait_for(coroutine, timeout=N). Dadurch wird asyncio.TimeoutError ausgelöst, wenn die Coroutine nicht innerhalb der angegebenen Sekunden abgeschlossen wird.
import asyncio
async def run_async_agent(query: str) -> dict:
history = []
for step in range(1, 21):
action = await async_decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
result = await async_execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
return {'status': 'max_steps', 'answer': None}
async def run_with_timeout(query: str, timeout: float = 60.0) -> dict:
try:
return await asyncio.wait_for(run_async_agent(query), timeout=timeout)
except asyncio.TimeoutError:
return {'status': 'timeout', 'answer': None}
# asyncio.run(run_with_timeout('What is Python?', timeout=30.0))Anweisungen zum Beenden in den Verlauf einfügen
Wenn eine Schleife erkannt wird, brechen Sie sie nicht einfach stillschweigend ab. Fügen Sie eine Systemnachricht in den Gesprächsverlauf ein, die erklärt, was passiert ist, und den Agenten auffordert, zu einem Abschluss zu kommen. So erhält das LLM die Möglichkeit, vor dem Abbruch eine abschließende Antwort zu erzeugen.
def inject_loop_escape(history: list, step: int, reason: str):
message = (
f'[SYSTEM] You have been running for {step} steps. Reason: {reason}. '
f'You MUST now provide a FINAL_ANSWER based on what you have found so far, '
f'even if the information is incomplete. Do not call any more tools.'
)
history.append({'role': 'system', 'content': message})
# In the agent loop, when approaching the limit:
# if step >= MAX_ITERATIONS - 2:
# inject_loop_escape(history, step, 'approaching max iteration limit')
# Or when a repeat is detected:
# if action_counts[key] > 2:
# inject_loop_escape(history, step, 'repeated action detected')
if __name__ == '__main__':
demo_history = []
inject_loop_escape(demo_history, step=18, reason='approaching max iteration limit')
print(demo_history[-1]['content'])
Protokollieren, wenn eine Schleife abgebrochen wird
Protokollieren Sie immer, wenn ein Schleifenschutz ausgelöst wird. So entsteht eine Aufzeichnung darüber, wie oft und warum Agenten feststecken — äußerst wertvolle Daten zur Verbesserung Ihrer Prompts und Werkzeugimplementierungen.
import logging
logger = logging.getLogger('agent_guard')
def check_and_break_loop(step: int, action_counts: dict, current_key: str) -> bool:
count = action_counts.get(current_key, 0)
if count > 2:
logger.warning(
f'Infinite loop detected at step {step}. '
f'Action hash {current_key[:8]} seen {count} times. '
f'Breaking loop.'
)
return True # signal to break
if step >= 18: # approaching limit
logger.warning(
f'Approaching max iterations at step {step}. '
f'Injecting escape prompt.'
)
return False
if __name__ == '__main__':
import sys
logging.basicConfig(level=logging.WARNING, format='%(message)s', stream=sys.stdout)
demo_counts = {'search:{"q": "weather"}': 3}
check_and_break_loop(step=10, action_counts=demo_counts, current_key='search:{"q": "weather"}')
Alle drei Schutzmechanismen kombinieren
Agenten im Produktivbetrieb sollten alle drei Schutzmechanismen kombinieren: maximale Iterationszahl (obligatorisch), Erkennung von Wiederholungen (erkennt Zyklen) und Timeout (erkennt blockierende Werkzeugaufrufe). Zusammen machen sie die Schleife äußerst robust.
import threading
import hashlib
import json
def run_production_agent(query: str) -> dict:
MAX_STEPS = 20
TIMEOUT_SEC = 120
timed_out = threading.Event()
timer = threading.Timer(TIMEOUT_SEC, timed_out.set)
timer.start()
history = []
action_counts = {}
try:
for step in range(1, MAX_STEPS + 1):
if timed_out.is_set():
return {'status': 'timeout'}
action = decide_action(query, history)
if action['type'] == 'final_answer':
return {'status': 'ok', 'answer': action['answer']}
key = hashlib.md5(json.dumps(action, sort_keys=True).encode()).hexdigest()
action_counts[key] = action_counts.get(key, 0) + 1
if action_counts[key] > 2:
inject_loop_escape(history, step, 'repeat detected')
continue
result = execute_tool(action['tool'], action['args'])
history.append({'tool': action['tool'], 'result': result})
finally:
timer.cancel()
return {'status': 'max_steps'}Schleifenschutz mit Unit-Tests testen
Schreiben Sie eigene Unit-Tests für Ihre Schleifenschutzmechanismen. Erstellen Sie einen Mock-Agenten, der immer dasselbe Werkzeug aufruft, und überprüfen Sie, dass der Schutzmechanismus ihn innerhalb der erwarteten Anzahl von Schritten erkennt.
from unittest.mock import MagicMock
def test_repeat_detection_breaks_loop():
# Create a mock that always returns the same action
always_same_action = MagicMock(return_value={
'type': 'tool',
'tool': 'search_web',
'args': {'query': 'same query'}
})
always_success = MagicMock(return_value='some result')
result = run_agent_with_repeat_detection(
query='test',
decide_action=always_same_action,
execute_tool=always_success
)
# Should stop due to loop detection, not run all 20 steps
assert result['status'] in ('loop_detected', 'max_iterations_reached')
# Should not have run all 20 steps (loop should be detected by step 6-7)
print('Loop guard test passed')Wissenscheck: Endlosschleifen erkennen
Testen Sie Ihr Verständnis der Techniken zum Erkennen und Unterbrechen von Endlosschleifen.
Zusammenfassung: Endlosschleifen erkennen und unterbrechen
Sie können Ihre Agenten jetzt mit drei ergänzenden Schutzmechanismen gegen Endlosschleifen absichern:
- Maximale Iterationszahl: Festes Schrittlimit, in jeder Agentenschleife obligatorisch
- Erkennung von Wiederholungen: Paare aus (Werkzeug, Argumente) hashen und die Schleife abbrechen, wenn sie mehr als N-mal vorkommen
- Timeout:
signal.alarm()auf Unix,threading.Timerplattformübergreifend,asyncio.wait_for()für asynchrone Agenten - Anweisungen zum Beenden: Dem Agenten die Möglichkeit geben, vor dem endgültigen Abbruch zu einem Abschluss zu kommen
- Immer protokollieren, wenn ein Schutzmechanismus ausgelöst wird — diese Daten sind für die Verbesserung von Prompts wertvoll
Häufig gestellte Fragen
Ist die Lektion „Endlosschleifen erkennen und unterbrechen“ kostenlos?
Ja — der vollständige Text von „Endlosschleifen erkennen und unterbrechen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Agents-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Agents-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Endlosschleifen erkennen und unterbrechen“?
Schutz vor zu vielen Iterationen, Erkennung wiederholter Aktionen und Circuit Breaker für Schleifen. Du übst AI Agents mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um AI Agents zu starten?
Keine Vorkenntnisse erforderlich. AI Agents auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Endlosschleifen erkennen und unterbrechen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser AI Agents-Lektion Code schreiben und ausführen?
Ja. Jede AI Agents-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Häufige Fehler in Agentenschleifen
- Trace-Logging für Agentenschritte
- Endlosschleifen erkennen und unterbrechen
- Techniken zum schrittweisen Debuggen