zeroclaw-labs/zeroclaw · error

Agent exceeded maximum tool iterations ({max_iterations})

Error message

Agent exceeded maximum tool iterations ({max_iterations})

What it means

When the tool loop exhausts max_iterations and LoopKnobs.max_iteration_behavior is ErrorAtCap, finish_after_max_iterations bails immediately with this error instead of spending one more LLM call on a graceful summary — embedders driving Agent::turn use it as a control signal ('cap reached'). The graceful path (a tools-free final summary) only runs under the non-ErrorAtCap behavior. A WARN 'tool_loop_exhausted' event with the model and cap is logged first.

Source

Thrown at crates/zeroclaw-runtime/src/agent/turn/max_iter.rs:48

    mut new_messages_out: Option<&mut Vec<ChatMessage>>,
) -> Result<String> {
    ::zeroclaw_log::record!(
        WARN,
        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
            .with_category(::zeroclaw_log::EventCategory::Agent)
            .with_outcome(::zeroclaw_log::EventOutcome::Failure)
            .with_attrs(::serde_json::json!({
                "model": model,
                "max_iterations": max_iterations,
                "trace_id": turn_id,
            })),
        "tool_loop_exhausted"
    );

    // ErrorAtCap callers (embedders driving Agent::turn) treat the cap as a
    // control signal: bail instead of spending another LLM call on a summary.
    if knobs.max_iteration_behavior == MaxIterationBehavior::ErrorAtCap {
        anyhow::bail!("Agent exceeded maximum tool iterations ({max_iterations})")
    }

    // Graceful shutdown: ask the LLM for a final summary without tools
    ::zeroclaw_log::record!(
        WARN,
        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
            .with_category(::zeroclaw_log::EventCategory::Agent)
            .with_outcome(::zeroclaw_log::EventOutcome::Unknown)
            .with_attrs(::serde_json::json!({"max_iterations": max_iterations})),
        "Max iterations reached, requesting final summary"
    );
    let tool_calls_stripped =
        crate::agent::history_pruner::strip_orphaned_tool_calls_from_assistants(history);
    let tool_messages_removed =
        crate::agent::history_pruner::remove_orphaned_tool_messages(history).removed;
    if tool_calls_stripped > 0 || tool_messages_removed > 0 {
        ::zeroclaw_log::record!(
            WARN,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Raise max_iterations for tasks that legitimately need more tool rounds.
  2. If you want a final answer instead of an error at the cap, set the max-iteration behavior to the graceful summary path.
  3. Inspect the loop logs for non-convergence: repeated identical tool calls or failing tools burning iterations, and fix the underlying tool/prompt issue.
  4. For embedded use, catch this error and treat it as 'budget exhausted' — resume the turn with a fresh budget if the work should continue.

Example fix

// before — embedder default treats the cap as a hard error
let result = agent.turn(request).await; // bails: exceeded maximum tool iterations

// after — opt into graceful summary at the cap, or raise the cap
// knobs: max_iteration_behavior = MaxIterationBehavior::Graceful (summary instead of error)
// or: max_iterations = 80
Defensive patterns

Strategy: fallback

Try / catch

Catch 'Agent exceeded maximum tool iterations', then choose a fallback: resume the turn with a raised cap if the work should continue, or accept the accumulated transcript/streamed output as partial results. Under ErrorAtCap this error is a control signal — treat it as 'budget exhausted', not a crash.

Prevention

When it happens

Trigger: A task legitimately needs more tool rounds than the configured cap; the model loops without converging (repeated failing tool calls); an embedded Agent::turn integration running with the default ErrorAtCap behavior on long multi-step jobs.

Common situations: Large refactors or repo-wide scans under a default iteration cap; a tool returning errors so the model keeps retrying; embedders unaware that ErrorAtCap turns the cap into a hard error.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/72747f065c9a2722. Report an issue: GitHub.