{
  "question": "How do I stop an AI agent from looping forever and burning tokens?",
  "slug": "how-to-stop-an-ai-agent-from-looping-forever-and-burning-tokens",
  "url": "https://www.rightshold.com/answers/how-to-stop-an-ai-agent-from-looping-forever-and-burning-tokens",
  "short_answer": "Set a hard limit at every layer: an explicit turn or step cap in the agent framework, a repeat detector that stops the run when the same tool call keeps coming back, a wall-clock timeout, and a hard spend limit at the model provider on a project or workspace that only this agent uses. Don't trust defaults: the OpenAI Agents SDK stops at 10 turns, but the Claude Agent SDK has no turn or budget limit unless you set one, and LangGraph's built-in recursion limit is now 10,007 steps. Framework caps stop one run; the provider limit is the ceiling when your own code is the bug.",
  "checklist": [
    "Pass an explicit cap on every run: Runner.run(agent, input, max_turns=N) in the OpenAI Agents SDK, ClaudeAgentOptions(max_turns=N, max_budget_usd=X) in the Claude Agent SDK, graph.invoke(input, {\"recursion_limit\": N}) in LangGraph.",
    "Treat hitting the cap as a normal result: catch MaxTurnsExceeded or pass error_handlers={\"max_turns\": ...}; check for ResultMessage subtypes error_max_turns and error_max_budget_usd; catch GraphRecursionError. Log it and alert someone.",
    "Detect repeats: hash the tool name plus its arguments for every call, and stop or ask a human when the same hash shows up three times in a row or the same error comes back twice.",
    "Add a wall-clock timeout per run and a retry cap with backoff per tool, so one flaky tool can't trigger endless retries.",
    "Give each agent its own provider project or workspace with a hard monthly spend limit. Spend alerts alone don't stop traffic.",
    "Leave headroom: spend is checked after responses arrive, so a run can pass its cap by about one response (plus running subagents), and provider enforcement isn't instant.",
    "If the loop can pay for things (paid APIs, x402), check every payment against a per-purchase and daily cap first, so a looping agent gets a deny instead of paying again."
  ],
  "sections": [
    {
      "heading": "What each framework does by default",
      "points": [
        "OpenAI Agents SDK (Python): Runner.run, run_sync and run_streamed default max_turns to 10 and raise MaxTurnsExceeded when a run goes past it. max_turns=None removes the limit. An error handler under the \"max_turns\" key can return a controlled final output instead of raising.",
        "Claude Agent SDK: max_turns / maxTurns and max_budget_usd / maxBudgetUsd default to no limit. Hitting either ends the run with a ResultMessage of subtype error_max_turns or error_max_budget_usd. Count one extra turn for the final text answer, or the run ends at the cap with no answer. Subagent spend counts toward the budget, and once it's reached new subagents fail with 'Budget limit reached' (Claude Code v2.1.217 or later).",
        "LangGraph: in langgraph 1.2.19, DEFAULT_RECURSION_LIMIT is 10007 (overridable with the LANGGRAPH_DEFAULT_RECURSION_LIMIT environment variable). Older docs, and langchain_core's own default, say 25, so a graph you expected to stop at 25 steps can now run thousands. Going over raises GraphRecursionError, and LangChain's docs say that if you don't expect many iterations, you probably have a cycle."
      ]
    },
    {
      "heading": "Why you still need a limit at the provider",
      "points": [
        "Framework caps live in your code. A process supervisor that restarts failed runs, a cron job that retries, or many parallel runs that each stay under their own cap can still add up to a large bill.",
        "OpenAI: spend alerts notify without stopping traffic. Hard spend limits on the organization or a project stop affected requests with the error codes organization_spend_limit_exceeded or project_spend_limit_exceeded, and retrying won't help until the limit is raised or the month resets. OpenAI says enforcement isn't instant, so recorded spend can slightly exceed the limit.",
        "Anthropic: each workspace can have a monthly spend limit, set from the Workspaces page in the Claude Console. Workspace limits can be lower than the organization's but not higher, organization limits always apply, and the Default Workspace can't have a spend limit, so put agents in their own workspace."
      ]
    },
    {
      "heading": "How to spot a loop in the logs",
      "points": [
        "The same tool with the same arguments over and over, the same error message coming back each time, tokens per turn climbing as the context grows, and no new files or state changing between turns.",
        "Log a run id, turn number, tool name, argument hash and token count for every call. A loop then shows up as one query instead of a surprise on the invoice."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Cap this agent's credential at $1 per purchase and $5 a day, only on api.example.com, so a looping agent gets denied instead of paying again.",
    "mcp_call": {
      "tool": "set_spend_policy",
      "arguments": {
        "credential_id": "<credential id from issue_agent_credential>",
        "currency": "USD",
        "per_tx_max_minor": 100,
        "daily_max_minor": 500,
        "allowed_domains": [
          "api.example.com"
        ]
      }
    },
    "also": [
      "Needs an owner account key (MCP toolset=trust). Every version of the policy stays on Rightshold's ledger.",
      "Before each payment the agent calls authorize_spend. Once a purchase is over the per-purchase cap or the running daily total would pass the daily cap, it returns a signed deny receipt with reasons. It records decisions only and never moves money, so your code has to stop when it gets a deny.",
      "account_controls freeze is an emergency stop for spending, listings and new work on a Rightshold account. revoke_agent (owner key) revokes a credential permanently, and every Rightshold check refuses it from then on."
    ],
    "scope": "Rightshold doesn't see or meter your model tokens and can't stop a running process. Its spending policy only covers payments your agent checks with authorize_spend; turn caps, timeouts and provider spend limits have to be set in your framework and your provider's console."
  },
  "sources": [
    {
      "title": "OpenAI Agents SDK: Running agents (max_turns, MaxTurnsExceeded, error handlers)",
      "url": "https://openai.github.io/openai-agents-python/running_agents/"
    },
    {
      "title": "openai-agents-python source: run_config.py (DEFAULT_MAX_TURNS = 10)",
      "url": "https://github.com/openai/openai-agents-python/blob/main/src/agents/run_config.py"
    },
    {
      "title": "Claude Agent SDK: How the agent loop works (turns and budget, budget headroom)",
      "url": "https://code.claude.com/docs/en/agent-sdk/agent-loop"
    },
    {
      "title": "LangGraph source: _config.py (DEFAULT_RECURSION_LIMIT)",
      "url": "https://github.com/langchain-ai/langgraph/blob/main/libs/langgraph/langgraph/_internal/_config.py"
    },
    {
      "title": "LangChain docs: GRAPH_RECURSION_LIMIT",
      "url": "https://docs.langchain.com/oss/python/langgraph/errors/GRAPH_RECURSION_LIMIT"
    },
    {
      "title": "OpenAI Help Center: Troubleshooting API usage and spend limits",
      "url": "https://help.openai.com/en/articles/6614457-troubleshooting-api-usage-and-spend-limits"
    },
    {
      "title": "Claude docs: Workspaces (spend limits)",
      "url": "https://platform.claude.com/docs/en/manage-claude/workspaces"
    }
  ],
  "related": [
    {
      "title": "How to build a kill switch for an autonomous AI agent",
      "url": "https://www.rightshold.com/answers/how-to-build-a-kill-switch-for-an-autonomous-ai-agent"
    },
    {
      "title": "How to rate limit an AI agent's API calls per key",
      "url": "https://www.rightshold.com/answers/how-to-rate-limit-an-ai-agents-api-calls-per-key"
    },
    {
      "title": "How to set a spending cap for an AI agent paying with x402",
      "url": "https://www.rightshold.com/answers/how-to-set-a-spending-cap-for-an-ai-agent-paying-with-x402"
    },
    {
      "title": "How to cap MCP tool output size to prevent context flooding",
      "url": "https://www.rightshold.com/answers/how-to-cap-mcp-tool-output-size-to-prevent-context-flooding"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-10-31"
}