zeroclaw-labs/zeroclaw · error

Agent loop aborted: repeated prompt-required tool call '{too

Error message

Agent loop aborted: repeated prompt-required tool call '{tool_name}' with identical arguments before approval.

What it means

In tool-call preparation, ZeroClaw tracks signatures (tool name + arguments) of prompt-approval-required shell calls across the whole loop. When the model emits a shell call whose signature was already recorded in a previous round and still has not been approved, prepare_tool_calls aborts the turn — an explicit infinite-approval-loop guard rather than letting the model re-request the same command forever. A status delta and a WARN log with the tool and scrubbed arguments precede the bail.

Source

Thrown at crates/zeroclaw-runtime/src/agent/turn/call_prep.rs:217

                        .with_attrs(::serde_json::json!({
                            "model": ctx.model,
                            "iteration": iteration + 1,
                            "tool": tool_name.clone(),
                            "arguments": scrub_credentials(&tool_args.to_string()),
                            "result": repeated,
                            "trace_id": ctx.turn_id,
                        })),
                    "tool_call_result"
                );
                if let Some(tx) = ctx.on_delta {
                    let _ = tx
                        .send(StreamDelta::Status(format!(
                            "\u{274c} {}: {}\n",
                            tool_name, repeated
                        )))
                        .await;
                }
                anyhow::bail!("{repeated}");
            }
        }

        // ── Approval hook ────────────────────────────────
        let approved = match gate_tool_approval(ctx, &tool_name, &tool_args, iteration).await {
            ApprovalGateOutcome::Proceed { approved } => approved,
            ApprovalGateOutcome::Deny(outcome) | ApprovalGateOutcome::Replace(outcome) => {
                // Streaming consumers see the denied/replaced call and its
                // synthesized result (e.g. a DenyWithEdit replacement) as a
                // ToolCall/ToolResult pair, as the direct path always did.
                if let Some(tx) = ctx.event_tx {
                    emit_tool_call_pair(tx, call, &outcome).await;
                }
                ordered_results[idx] =
                    Some((tool_name.clone(), call.tool_call_id.clone(), outcome));
                continue;
            }
        };

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Resolve the pending approval: run interactively and approve/deny, or adjust the approval policy so this specific command class proceeds without a prompt.
  2. Change the system prompt so the model varies arguments or asks the user instead of repeating an identical call.
  3. Inspect the WARN 'tool_call_result' log for the exact tool and scrubbed arguments, then fix whatever output keeps making the model retry identically (e.g. a failing command's error).
  4. If the environment is legitimately non-interactive, scope approval requirements down for the commands that run there.

Example fix

# before — non-interactive run, model repeats `shell: cargo test` awaiting approval that never comes
# after — pre-approve deterministic commands or instruct the model:
#   "`cargo test` is pre-approved. Run it once; if it fails, change the command before rerunning."
# and/or relax the approval policy for that command class in the agent's risk profile
Defensive patterns

Strategy: try-catch

Try / catch

Catch the abort at the turn boundary, read the WARN 'tool_call_result' log for tool name + scrubbed arguments, then either resume the turn after the approval is granted/policy adjusted, or surface the tool call to the user for an explicit decision. Do not auto-retry the identical turn — it will abort again.

Prevention

When it happens

Trigger: The model re-issues the exact same shell command after the earlier identical call was denied, replaced, or recorded as a duplicate; a non-interactive channel (cron, gateway) where the approval prompt can never be answered; the model retrying a failing command with identical arguments instead of changing them.

Common situations: Risk profile flags shell for approval in an environment with no human to approve; agent stuck in a retry loop on a command that keeps failing; approval hooks that deny without telling the model what to change.

Related errors


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