Stopping runaway agents: turn, token and spend caps per tool

Shared by Pavel · Updated 2026-11-09

Stopping runaway agent loops and cost stampedes across many agents

Read date for all sources: 2026-11-09. Written for a founder running a small human team and a large agent fleet.

Labels: [vendor] = the vendor's own docs or source code. [opinion] = a reading, untested. Nothing here was run against a live agent: every behaviour below comes from docs and source.

Questions people are asking

QuestionWhere / dateState
"How are you guys stopping agents from silent loops/stampedes? Standard step_counters feel like garbage."github.com/microsoft/autogen/discussions/8135, 2026-08-31No accepted answer
Same question, cross-postedforum.langchain.com/t/4479, 2026-09-02No accepted answer
"How are you capping spend on LangChain / LangGraph agents in production?"forum.langchain.com/t/4917, 2026-10-27Partly answered
Inherited recursion-depth budget for Agent.as_tool delegationgithub.com/openai/openai-agents-python/issues/5453, 2026-10-29Open
A run stopping at max_turns with conversation_id leaves tool calls without outputs; later turns return 400github.com/openai/openai-agents-python/issues/5642, 2026-11-09Open
RetryPolicy(max_attempts) never gives up on a node that calls interrupt()github.com/langchain-ai/langgraph/issues/9493, 2026-10-30Open
Antigravity side question re-ran the same turn about 259 times, about 30M tokens, weekly quota fell from about 50% to about 30%discuss.ai.google.dev/t/198137, 2026-11-04No accepted answer
Gemini API billing cap increase; unexpected bills from infinite-loop codediscuss.ai.google.dev/t/199268 (2026-11-09), /171429Not answered
Claude Code Ultra weekly allowance reported at 20% after reset and exhausted in about 10 hours; cause unconfirmedgithub.com/anthropics/claude-code/issues/108111, 2026-11-07Open

Per-tool caps [vendor]

ToolSettingDefaultWhere setAt the cap
OpenAI Agents SDK (Python)max_turns10 (DEFAULT_MAX_TURNS in src/agents/run.py); None disablesRunner.run, run_sync, run_streamedRaises MaxTurnsExceeded, or returns a fallback via error_handlers={"max_turns": fn}
OpenAI Agents SDKModelSettings.timeout; tool timeout_behavior="raise_exception"; max_function_tool_concurrencyconcurrency None (all calls start)Model settings, tool definition, run configModelTimeoutError, ToolTimeoutError
LangGraphrecursion_limitSource on main: 10007, overridable by env LANGGRAPH_DEFAULT_RECURSION_LIMIT; the docs page states no numberconfig={"recursion_limit": N}Raises GraphRecursionError
AutoGen AgentChatMaxMessageTermination(max_messages)requiredtermination_conditionRun ends, TaskResult.stop_reason set
AutoGenTokenUsageTermination(max_total_token, max_prompt_token, max_completion_token)all None; ValueError if all three are NonesameRun ends: "Token usage limit reached"
AutoGenTimeoutTermination(timeout_seconds)requiredsameRun ends: "Timeout of N seconds reached"
CrewAImax_iter25 in source and the customizing docs; the agents concept page says 20Agent(...)Docs: the agent "will try its best to give a good answer"
CrewAImax_rpmNoneAgent(...)Throttles request rate, does not stop
CrewAImax_execution_time (seconds)NoneAgent(...)Task times out
CrewAImax_retry_limit2Agent(...)Retries on error stop after N
Claude Code CLI--max-turnsno limit; print mode (-p) onlyCLI flagResult subtype error_max_turns
Claude Code CLI / Agent SDK--max-budget-usd; SDK max_budget_usd / maxBudgetUsdno limit; print mode onlyCLI flag; SDK optionsResult subtype error_max_budget_usd
Claude Agent SDKmax_turns / maxTurnsno limitClaudeAgentOptions / OptionsResult subtype error_max_turns
Claude Code hooksPreToolUse deny; exit code 2; JSON continue: false with stopReasonn/ahook configBlocks the action, or stops processing
Codex CLINo turn, token or budget key found. Source: DEFAULT_EXEC_COMMAND_TIMEOUT_MS = 10_000; config types include MCP tool_timeout_sec, startup_timeout_sec, agent max_threads, max_depth, job_max_runtime_secondsas listedconfig.tomlNot read in detail
Gemini CLImodel.maxSessionTurns-1 (unlimited)settings.jsonInteractive: message and stop; non-interactive: exits with an error

Counting differs by tool: OpenAI counts model-call turns, LangGraph counts graph supersteps, AutoGen counts messages, Claude counts a model response plus its tool calls. The same number is not the same cap.

LangGraph issue 9416: with_config ignored an explicit recursion_limit equal to the default, so set a value that differs from it.

What happens at the cap [vendor]

Provider-side spend caps [vendor]

Patterns [opinion, untested]

Gaps

Sources

openai.github.io/openai-agents-python/running_agents; openai-agents-python src/agents/run.py and exceptions.py; docs.langchain.com/oss/python/langgraph/GRAPH_RECURSION_LIMIT; langgraph _internal/_config.py and errors.py; microsoft.github.io/autogen/stable agentchat termination tutorial; autogen conditions/_terminations.py; docs.crewai.com/en/concepts/agents and /en/learn/customizing-agents; crewAI base_agent.py; code.claude.com/docs/en/cli-reference, agent-sdk agent-loop, hooks; codex docs/config.md, codex-rs/core/src/exec.rs; gemini-cli docs/cli/session-management.md, docs/reference/configuration.md, packages/core/src/core/client.ts; platform.claude.com/docs/en/api/rate-limits; developers.openai.com/api/docs/guides/rate-limits; aistudio.google.com/docs/billing. All read 2026-11-09.