Loop detection

Stop AI agents stuck in a loop before they spend

When an agent keeps sending the same call, GuardrailX notices and blocks it before the provider: by default, the sixth identical call in 60 seconds pauses that job for 5 minutes. Blocked repeats cost nothing.

Free plan forever: 5,000 requests a month, no credit card.

Request log: total cost, blocked requests and “blocked · loop · paused” rows at 03:20.

A loop makes no noise. You see it on the invoice.

Agents retry on their own, and one logic error is enough to send the same request hundreds of times. Provider console limits apply to the whole account and kick in when the money is already spent.

The tool that always gives the same answer

A search that always returns «no results», and an agent that asks the same question again, forever.

The error retried without changing anything

The model rejects a format and the agent sends the same body again. SDKs add their own automatic retries.

At night, with nobody watching

Scheduled jobs run while the team sleeps. A loop at 3 a.m. keeps going until morning.

How it detects a loop

Every call goes through GuardrailX before it reaches the provider. The check runs in memory and doesn’t slow down normal calls.

  1. 1

    It fingerprints the call

    A signature built from the model, the last two messages and the attachments. First it strips what changes at every round without changing the question: dates, times, uuids, ids and long numbers.

  2. 2

    It looks at the circuit

    The circuit is the gr_ key plus, if present, the session (X-GuardrailX-Session). Each run with its own session is counted on its own: a looping agent doesn’t stop other jobs using the same key.

  3. 3

    It counts the repeats

    If 5 calls with the same fingerprint already went through in the window (60 seconds by default), the sixth is blocked with loop_detected.

  4. 4

    It pauses the circuit

    For 5 minutes every call on that circuit gets loop_paused, even a different one. Other sessions and other keys keep working normally.

  5. 5

    It alerts you

    You get an alert by email, webhook (Slack, Discord) or Telegram with the agent, the session and how many identical calls. From the Limits tab you can reopen the circuit before the pause ends.

What your code receives

A 429 error in the provider’s format (OpenAI, Anthropic or Gemini): official SDKs read it like any other error.

  • The code loop_detected, then loop_paused while the pause lasts.
  • A Retry-After header with the seconds of pause left.
  • x-should-retry: false: the OpenAI and Anthropic SDKs don’t retry on their own, so the loop doesn’t carry on through automatic retries.
# GuardrailX’s answer to the sixth identical call
HTTP/1.1 429 Too Many Requests
retry-after: 300
x-should-retry: false
x-guardrailx-blocco: loop_detected

{
  "error": {
    "type": "guardrail_error",
    "code": "loop_detected",
    "message": "GuardrailX: likely agent loop (agente-fatture keeps repeating the same request). Calls paused for 300 seconds."
  }
}
// Node: stop the run instead of retrying
const client = new OpenAI({
  baseURL: 'https://agent.guardrailx.ai/openai/v1',
  apiKey: process.env.GUARDRAILX_KEY,
  defaultHeaders: { 'X-GuardrailX-Session': run.id }
});

try {
  await client.chat.completions.create(richiesta);
} catch (e) {
  if (e.code === 'loop_detected' || e.code === 'loop_paused') {
    return run.stop('loop');
  }
  throw e;
}

When two calls are «the same»

What counts is the question, not the details that change at every round. Small numbers stay: «page 2» and «page 3» are different calls.

Two callsFor loop detection
«Check order 12345 at 10:00» and «Check order 67890 at 10:05»The same: only the order number and the time change
«Extract the data of page 2» and «Extract the data of page 3»Different
The same text sent to two different modelsDifferent
The same last two messages, with a longer conversationThe same
A round that only changes a small counter («attempt 3», «attempt 4»)Different, unless you send the step in X-GuardrailX-Step: same session and same step are the same call

You decide when two calls are «the same»

Besides loop blocking you can write uniqueness rules on the fields your code sends to GuardrailX in its headers (X‑GuardrailX‑Session, ‑Step, ‑Agent, ‑Customer, ‑User, ‑Feature), on the model and on the prompt. You turn them on in the Limits tab; they are off by default and loop blocking stays as it is.

  • The same when they have the same fields: for example session and step, even if the prompt changes a little.
  • At most a given number of times in a window, from 1 second to 24 hours.
  • Only on calls with a given value of a field, prefixes included (inv*).
  • Beyond the limit: reject the call (duplicate_call) or pause the whole group, even with a different prompt.
  • While you write it, the preview tells how many calls of the last 7 days it would have stopped.
// The fields you write rules on
const client = new OpenAI({
  baseURL: 'https://agent.guardrailx.ai/openai/v1',
  apiKey: process.env.GUARDRAILX_KEY,
  defaultHeaders: {
    'X-GuardrailX-Session': lavoro.id,
    'X-GuardrailX-Step': `pagina-${n}`,
    'X-GuardrailX-Feature': 'fatture',
    'X-GuardrailX-Customer': cliente.id
  }
});
# The answer when a rule stops the call
HTTP/1.1 429 Too Many Requests
x-should-retry: false
x-guardrailx-regola: Once per session

{ "error": { "code": "duplicate_call", … } }
RuleWhat you get
Once per step · session + step, once in 24 hoursEach page of a file is processed only once, even if the client sends it again with a slightly different prompt.
Once per session · session + feature, only the «invoices» featureThe invoice is generated once per session, whatever the prompt.
Same prompt per customer · customer + prompt, for example 3 times in 10 minutes, then a pauseA customer repeating the same question is stopped; other customers keep going.
FAQ

Questions about loop detection

How does it detect a loop?

If the same request keeps arriving on the same circuit (the gr_ key and, if present, the session), 5 times in 60 seconds by default, the next one is blocked with loop_detected and the circuit is paused for 5 minutes. Repeats, window and pause can be set per project.

Can I decide when two calls are the same?

Yes, with the uniqueness rules in the Limits tab. Pick the fields your code sends in the X-GuardrailX headers (session, step, agent, customer, user, feature), the model or the prompt, how many times they may pass and in how long. Beyond the limit the call gets a 429 duplicate_call, or the group is paused.

What if a repeated call is intentional?

Send a different session for each job (X-GuardrailX-Session): circuits are counted separately. Or raise the allowed repeats or shorten the window in the Limits tab, or turn loop blocking off for that project.

Does a provider error count as a repeat?

No. A call that fails because of the provider (429, 5xx errors, dropped connection, no answer in time) isn’t counted: your code can retry it without looking like a loop. 4xx responses do count: sending again the same body the provider rejects is a loop.

Does blocking stop all my agents?

No, only the looping circuit. With X-GuardrailX-Session each run is counted on its own, and with X-GuardrailX-Customer each of your customers too: the others keep working. Without a session the circuit is the whole gr_ key.

Can I change the thresholds?

Yes, per project in the Limits tab: how many identical calls, in how many seconds and how long the pause lasts. Loop blocking is in every plan, Free included.

Do blocked calls cost anything?

No. They stop before the provider, so they use no tokens. In the request log they show up as blocked, with an estimate of what they would have cost.

Put a cap on spending before the next loop.

Start on the Free plan: 5,000 requests a month, no card and no end date.