Agent Loop · Deep Dive
An agent that loops is not broken — it is telling you something about its instructions, its tools, or its environment. Unlike a regular program that crashes with a stack trace, a looping agent produces page after page of plausible-looking actions that go nowhere. The signal is in the pattern.
This guide teaches you to read agent traces, identify common failure patterns, and apply the fix systematically.
A healthy agent trace shows variety in tool selection and a clear trajectory toward a final answer. A bad trace has the opposite signature: the same tool called with the same arguments, turn after turn.
Key metrics to check first: total steps, unique tools called, repeated (tool, args) pairs, tool error count. These four numbers tell you more than reading every line.
Loop without Final Answer: the agent never emits the stop signal. Fix by reinforcing the format in the prompt. Hallucinated tool names: the agent calls a non-existent tool. Add validation that catches unknown names. Format errors: action text doesn't match the expected regex. Tighten the parser. Ignored tool errors: the agent treats error messages as valid data. Surface errors prominently.
1. Capture every turn as structured records. 2. Run through an analyzer for repeated actions, missing final answers, hallucinated tools. 3. Find the first anomaly — the turn where the loop started. 4. Fix one thing and re-run. 5. Turn the failing trace into a regression test.
Concrete Example
from collections import Counter
VALID_TOOLS = {"search", "calculate", "lookup", "fetch"}
def analyze_trace(steps):
issues = []
has_final = any(s["action"].strip().startswith("Final Answer:") for s in steps)
if not has_final:
issues.append("Agent never emitted a Final Answer.")
action_counter = Counter()
hallucinated = set()
for s in steps:
if s["tool"] and s["tool"] not in VALID_TOOLS:
hallucinated.add(s["tool"])
key = f"{s['tool']}:{s.get('args', '')}"
action_counter[key] += 1
if action_counter[key] > 2:
issues.append(f"Repeated action: ({s['tool']}) x{action_counter[key]}")
if hallucinated:
issues.append(f"Hallocinated tools: {', '.join(hallucinated)}")
return {"issues": issues, "total_steps": len(steps)}The analyzer flags repeated actions, hallucinated tool names, and missing final answers. Key metrics are checked first to identify the failure pattern quickly.
Healthy traces show tool variety. Loops show the same action repeating.
No final answer, hallucinated tools, format errors, ignored errors.
Catch hallucinated tools by checking against your valid tool list.
Every loop you fix becomes a test case to prevent regressions.