Your agent loops forever. It is probably tool_choice.
By Nihar Ranjan Das · Wed Aug 19 2026 · 6 min read · 0 views
View as a Web StoryAISoftware#ai agents#llm#tool calling#LangChain#OpenAI Agents SDK#debugging

Your agent loops forever. It is probably tool_choice.
Your agent calls the same tool repeatedly and never returns an answer. The advice you will find first is to set max_iterations, which caps your bill without addressing the underlying defect.
In most production cases the cause is a request setting that persists when you did not expect persistence. If you forced the model to use a tool, that force is probably still switched on.
What an infinite tool-calling loop actually is
An infinite tool-calling loop is a run where the model keeps asking for tool calls and never returns a final answer. It is not a crash. The process is healthy, the API is answering, and your token spend climbs the whole time.
That is precisely why it hurts financially. A crash terminates; a loop continues indefinitely. The cheapest AI API is not the cheapest to run, and an unterminated loop is the clearest illustration of that difference.
tool_choice is the request field that tells a model whether it may call a tool. Set it to auto and the model decides. Set it to required, or to a named function, and the model must call one.
Why raising max_iterations is not a fix
An iteration cap stops the bleeding without explaining why the agent continued.
Worse, it hides the shape of the problem. A run that hits your cap looks the same whether it repeated one tool twenty times or made twenty useful calls. You need to know which, and a counter cannot tell you.
So configure a cap, but understand it as a seatbelt rather than a diagnosis. The checks below are the actual investigation.
Cause one: tool_choice sticks across turns
This is the first thing to check, and it is often the whole answer.
When you set tool_choice to force tool usage, that setting persists across model calls. The model returns a tool call. Your framework runs the tool. Then it sends the result back with the same forced setting still attached. The model is told, again, that it must call a tool.
Advertisement
It obeys, and that repetition is the loop.
The openai-agents-python patch fixes exactly this. It resets tool_choice to auto after tool execution, so the model can decide whether more calls are needed. The change was merged on March 25, 2025.
Two consequences follow. First, upgrade your dependencies before writing guardrail code, because your framework may already handle the reset internally. Second, if you configure tool_choice yourself in a raw API call, the reset is your responsibility.
Cause two: the over-correction that breaks real workflows
The obvious remedy is to set tool_choice to none after any tool result. That reliably stops the loop, and it simultaneously breaks anything requiring more than a single step.
Oracle's langchain-oracle change documents the damage well. Its earlier fix set tool_choice to none unconditionally. A four-step diagnostic agent, for example one that checks status, reads events, checks recent changes, then restarts a pod, stopped dead after the first call.
That is the trade-off nobody warns you about. An unconditional stop after one tool converts every agent into a single-tool script. You will observe no error, only incorrect answers.
The better detector: same tool, same arguments
Here is the underlying principle worth remembering, whichever framework you use.
A loop is not "many calls". A loop is the same call. Oracle's newer approach detects repeats by spotting the same tool invoked with identical arguments in succession, and adds a max_sequential_tool_calls limit as a backstop.
max_sequential_tool_calls is a cap on how many tool calls may run in a row before the model is forced to answer. In that patch the default is 8.
Combine the two and you get behavior a plain counter cannot give you:
| Signal | What it catches | What it misses |
|---|---|---|
| Iteration cap | Runaway spend. | Long workflows, which it also kills. |
| Wall-clock timeout | Hung tools and slow APIs. | Fast loops that repeat cheaply. |
| Repeat detection | The real loop, on the second identical call. | A loop that varies one argument. |
| All three together | Cost, hangs, and repeats. | Very little. |
Repeat detection is inexpensive to implement, and almost nobody implements it. Consider what an identical-arguments comparison would have saved you on the last runaway execution you paid for.
Caps that stop the bleeding, and one that throws
LangChain's AgentExecutor accepts both max_iterations and max_execution_time, documented in LangChain's Python reference. Configure both parameters. One bounds the number of steps; the other bounds elapsed time, and slow tools genuinely need the second.
Then there is early_stopping_method. The advice you will read everywhere is to set it to generate, so the model writes a best-effort answer instead of failing. Check your version before you copy that line. Developers hitting the limit have reported the exact error Got unsupported early_stopping_method 'generate', filed as LangChain issue 16263 in January 2024.
So the recommended remedy can itself become the subsequent defect. Test the stopping path deliberately: force a run past your cap in staging and observe exactly what your users would receive.
What newer frameworks do by default
The defaults are moving, which changes what you need to write yourself.
Microsoft's Agent Framework migration guide notes that its agents keep executing tools until the task completes, rather than stopping at an iteration count you set, with built-in safety mechanisms to prevent infinite loops. AutoGen's AssistantAgent, by contrast, was single-turn unless you raised max_tool_iterations.
Read that difference carefully before migrating. A framework that previously stopped early now continues until completion. Your existing iteration cap may no longer perform the function you assume, and your token invoice is where that will surface first.
Agents left running unattended become expensive quickly. Can AI Agents Run a Business? It Lost $447 demonstrates the identical lesson at product scale: unbounded autonomy is a cost problem before it becomes a quality problem.
The fix order
Work it in this order, and stop when the loop stops.
- Upgrade your SDK. The sticky
tool_choiceclass of bug is patched upstream in several libraries. - Log the tool name and arguments on every call. If the last two are identical, you have your answer in one glance.
- Reset
tool_choicetoautoafter each tool result if you build requests yourself. - Add repeat detection on name plus arguments, and force a final answer on the second match.
- Set an iteration cap and a wall-clock timeout as backstops, and test what your app returns when they fire.
Advertisement
FAQ
Why does my AI agent keep calling the same tool in a loop?
Most often because `tool_choice` is set to `required` or to a named function and persists across model calls. Every time the tool result goes back, the model is told again that it must call a tool. Resetting `tool_choice` to `auto` after tool execution breaks the cycle.
Does setting max_iterations fix an infinite tool-calling loop?
No. It caps the cost and ends the run, but it does not remove the cause, and it cannot tell a genuine multi-step workflow from a repeat. Use it as a backstop alongside repeat detection on the tool name and arguments.
What is the error "Got unsupported early_stopping_method generate"?
It is the error raised when an `AgentExecutor` hits its iteration limit with `early_stopping_method` set to `generate` on a version that does not support it. It was reported in LangChain issue 16263. Check your version before copying that setting from a tutorial.
How do I stop a loop without breaking multi-step agents?
Do not force `tool_choice` to `none` after the first tool result. That stops loops and also stops legitimate chains. Detect the same tool called with identical arguments in succession instead, and keep a sequential-call limit, such as eight, as the backstop.
Should I fix the loop in the prompt or in the code?
In the code first. Prompts help the model know when it is done, but a forced setting or a missing stop rule will beat any wording. Fix the request lifecycle and the stop conditions, then tighten the prompt.
Comments
Loading…
Sign in to join the conversation.
Related posts

89% watch agents fail. Only half test before shipping.
Most teams can see their agent failing in production. Fewer than half can catch it beforehand.
Wed Aug 19 2026 · 6 min read · 0 views

Agent memory that does not wreck your prompt cache
Most advice on agent memory treats it as a storage question. Pick a vector store, summarize when the window fills, move on. That misses the bill.
Wed Aug 19 2026 · 6 min read · 0 views

AutoGen is in maintenance mode. Where to migrate now.
AutoGen is not getting new features. The project README states it plainly: "AutoGen is now in maintenance mode. It will not receive new features or enhancements and is community managed going
Wed Aug 19 2026 · 5 min read · 0 views