Rightshold™ Sign up

Answers · agent safety

How do I stop an AI agent from looping forever and burning tokens?

Last updated

TL;DR: 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.

What should I check, step by step?

1. 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.

  1. 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.
  2. 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.
  3. Add a wall-clock timeout per run and a retry cap with backoff per tool, so one flaky tool can't trigger endless retries.
  4. Give each agent its own provider project or workspace with a hard monthly spend limit. Spend alerts alone don't stop traffic.
  5. 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.
  6. 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.

What each framework does by default

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.

Why you still need a limit at the provider

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.

How to spot a loop in the logs

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.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then 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.”

One-click setup

{
  "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"
    ]
  }
}

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.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'