Build1 publisher3 min readPublished
Your agent's infinite tool loop is a setting that outlived its turn
The common agent loop is a persisted tool_choice value, not a missing guardrail. Fixing it takes an upstream upgrade plus repeat-argument detection; max_iterations only caps the bill.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction
What happened
- The agent discussion on Reddit and in GitHub issues has shifted from "what can agents do" to "why does mine call the same tool nineteen times".
- The advice everyone gives is to set max_iterations; that caps your bill but does not fix the bug.
- When tool_choice is set to required or to a named function, that setting persists across model calls.
- The framework runs the tool, sends the result back, and the same forced tool_choice setting rides along; the model is told again that it must call a tool, and it obeys. That is the loop.
- The merged fix in openai-agents-python resets tool_choice to auto after tool execution.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
The complaint that has replaced "what can agents do" is narrower and more embarrassing: why does mine call the same tool nineteen times [1]. According to a dev.to breakdown of five recurring agent engineering problems, the usual cause is not an absent guardrail but a configuration value that persists past the moment it was meant for [3].
The mechanism is dull, which is why it survives so long in production. Set `tool_choice` to `required` or to a named function, and that setting persists across model calls [3]. Your framework executes the tool, appends the result, and sends the conversation back with the same forced setting attached; the model is told again that it must call a tool, and it does [4]. Nothing is broken. The model is complying with an instruction nobody remembered to withdraw.
Step one is therefore a dependency bump rather than defensive code. The merged fix in openai-agents-python resets `tool_choice` to `auto` after tool execution [5], which the writeup frames as upgrade first, guardrails second [6].
Step two is the part that gets skipped. A loop is not many calls; it is the same call [7]. Oracle's langchain-oracle patch detects repeats by matching the tool name and identical arguments in succession, with a `max_sequential_tool_calls` backstop defaulting to 8 [8]. Note what the shape of that fix implies about the shape of the bug: identity of arguments, not volume of calls, is the signal.
The alternative was tried and it hurt. An earlier Oracle fix set `tool_choice` to `none` after any tool result, which stopped loops and also broke a four-step diagnostic agent after its first call [9]. That is the trade you make when you suppress a capability instead of detecting a repetition.
Which brings us to the advice most teams ship instead. An iteration counter cannot tell a six-step workflow from a six-step loop; argument identity can [10]. `max_iterations` caps your bill, not your bug [2]. It is worth keeping for exactly that reason, since the failure mode is expensive, but a cap converts an unbounded incident into a bounded one and leaves the defect in place. On the nineteen-call complaint, Oracle's default backstop of 8 would have ended the run eleven calls earlier and still told you nothing about why the model kept going [11].
The pricing pressure here is moving the wrong way. In Microsoft Agent Framework, agents keep calling tools until the job is done rather than stopping at a count you set, which is friendlier for simple tasks and harder to price [12]. If the ceiling is gone by design, repeat detection stops being a nice diagnostic and becomes the only thing standing between a stuck agent and your invoice.
Worth watching: whether repeat-argument detection lands as a default in mainstream frameworks rather than a vendor patch, and whether frameworks that removed iteration ceilings ship a substitute stop condition. Until then, check your pinned version of openai-agents-python and log tool name plus argument hash on every call, because you cannot detect an identical call you never recorded [8].