Stop a repeating agent with enforced execution budgets and a rule for failures that cannot improve through repetition. Put the stop decision in orchestration code; asking the model to be economical is not an execution limit.
Recognize an unchanged operation
A tool name alone is insufficient: two lookups with different authorized records may be legitimate. Use a bounded signature of the operation and relevant arguments, plus a failure category. Avoid copying raw secrets into the signature or logs. A permanent-invalid-input result should trigger a different response from a transient upstream failure.
Enforce budgets before the next call
- Check elapsed duration, total steps, retry count, and applicable spend budget before dispatch.
- Record whether a retry changes an input or condition relevant to the failure.
- Stop or request clarification when repeated permanent failures have no changed input.
- Propagate cancellation to supported in-flight operations and report the incomplete task accurately.
Read the repeated-failure fixture
The synthetic plan proposes the same invalid lookup four times. The loop stops after observing a second permanent failure with the same fingerprint, despite a larger total step budget. It emits a termination reason rather than pretending the lookup succeeded.
Test more than the happy stop path
Exercise a tool that ignores cancellation, delayed callbacks, and a failure that occurs after a side effect. A local iteration cap limits one process; distributed workers also need shared task state or coordination appropriate to their architecture. The example does not simulate billing, remote cancellation, or concurrent agents.
Run the worked example
Save the synthetic Node.js example and run node stop-repeating-agent-tool-calls.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.
// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';
const plan = Array(4).fill({ fingerprint: 'lookup:missing-id', failure: 'permanent' });
let steps = 0;
let previous = null;
let stopped = null;
for (const operation of plan) {
if (steps >= 5) { stopped = 'step-budget'; break; }
steps++;
if (operation.failure === 'permanent' && operation.fingerprint === previous) {
stopped = 'repeated-permanent-failure'; break;
}
previous = operation.fingerprint;
}
assert.equal(steps, 2);
assert.equal(stopped, 'repeated-permanent-failure');
console.log(JSON.stringify({ steps, stopped }));
References and further reading
Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.