Agent Execution Loops
An agent doesn't run once — it loops: observe, think, act, repeat. Understanding the loop lifecycle helps you configure limits, attach hooks, stream progress, and debug agents that get stuck.
Loop Lifecycle
- Init — Load system prompt, tools, memory, and config
- Observe — Receive user input or previous tool result
- Think — LLM generates a Thought and decides next action
- Act — Execute the selected tool (or produce a final answer)
- Check — Test termination conditions (done? max_steps? budget?)
- Repeat — Return to Observe with the tool result as new input
Step and Budget Limits
agent:
max_steps: 20 # Hard stop after 20 steps
max_tokens_total: 100000 # Stop if total tokens exceed 100k
max_wall_time_seconds: 120 # Stop after 2 minutes
max_cost_usd: 0.50 # Stop if estimated cost exceeds $0.50
on_limit_reached: "return_partial" # return_partial | raise | retryLoop Detection
An agent can get stuck in a loop — calling the same tool with the same args repeatedly. OpenClaw uses a hash-based similarity check to detect and break loops automatically.
agent:
loop_detection:
enabled: true
window: 4 # Check last 4 steps for repetition
similarity: 0.95 # Trigger if similarity > 95%
action: "inject_hint" # inject_hint | abort | ask_userPause and Resume
For long-running agents or human-in-the-loop workflows, you can pause execution and resume later:
from openclaw import Agent
agent = Agent(model="gpt-4o", tools=["web_search", "code_exec"])
session = agent.start("Analyse the top 10 open-source LLM frameworks")
# Pause mid-run and serialise state
checkpoint = session.pause()
checkpoint.save(".openclaw/checkpoint.json")
# Later: restore from checkpoint
from openclaw import AgentSession
restored = AgentSession.load(".openclaw/checkpoint.json")
result = restored.resume()Streaming Intermediate Steps
agent = Agent(model="gpt-4o", tools=["web_search"])
for step in agent.stream("Compare React and Vue in 2025"):
if step.type == "thought":
print(f"[Thinking] {step.content}")
elif step.type == "tool_call":
print(f"[Tool] {step.tool_name}({step.args})")
elif step.type == "observation":
print(f"[Result] {step.content[:200]}...")
elif step.type == "final":
print(f"\n[Done]\n{step.content}")Lifecycle Hooks
from openclaw import Agent
def on_step_start(step_num, thought):
print(f"Step {step_num} starting: {thought[:80]}")
def on_step_end(step_num, tool_name, result):
print(f"Step {step_num} done: {tool_name} returned {len(result)} chars")
def on_complete(result):
print(f"Agent finished in {result.steps_taken} steps, "
f"cost ${result.usage.estimated_cost_usd:.4f}")
agent = Agent(
model="gpt-4o",
tools=["web_search"],
hooks={
"on_step_start": on_step_start,
"on_step_end": on_step_end,
"on_complete": on_complete,
},
)Debugging a Stuck Loop
If an agent keeps repeating the same step, check:
- The tool is returning an error the agent doesn't understand
- The system prompt doesn't tell the agent when to stop
- The model is not recognising the final answer state
Enable verbose mode and inspect the trace: Agent(verbose=True, return_trace=True). The trace shows every thought and tool call in sequence.
- Every agent run is a loop: observe → think → act → check → repeat.
- Always set
max_stepsandmax_cost_usdto cap runaway agents. - Use
agent.stream()to show real-time progress in production UIs. - Lifecycle hooks let you log, audit, or modify behaviour at each step boundary.
- Enable
loop_detectionto automatically catch agents stuck in repetition.
Advanced Loop Patterns
Beyond the basic Thought → Action → Observation cycle, OpenClaw supports several extended loop patterns for complex workflows:
- Nested loops. An outer orchestrator agent spawns sub-agents for specific tasks. Each sub-agent runs its own loop and returns a result to the parent. Use
agent.spawn_subagent()to create a nested execution context. - Parallel step execution. When a planning step identifies independent tasks (e.g., "fetch from API A" and "fetch from API B"), OpenClaw can execute them concurrently using
asyncio.gatherunder the hood, reducing total latency. - Reflective loops. After task completion, a reflection step reviews the output for errors or missed requirements before returning to the caller. Enable with
enable_reflection=Truein the agent config.
from openclaw import Agent
agent = Agent(
model="gpt-4o",
max_steps=20,
loop_detection=True,
loop_detection_window=5, # flag if same action repeats 5x
enable_reflection=True,
reflection_prompt="Review your answer. Is it complete and correct?",
)