Step limits pour agents IA (stopper les loops) + Code

Les step limits sont l’assurance la moins chère contre les loops. Cappe les steps, expose un stop reason, et évite les 700 tool calls.
Sur cette page
  1. Le problème (côté prod)
  2. Pourquoi ça casse en prod
  3. 1) “It’ll stop when it’s done” n’est pas un plan
  4. 2) Sans stop reason, c’est invisible
  5. 3) Enforce dans la run loop
  6. Exemple d’implémentation (code réel)
  7. Incident réel (avec chiffres)
  8. Compromis
  9. Quand NE PAS l’utiliser
  10. Checklist (copier-coller)
  11. Config par défaut sûre (JSON/YAML)
  12. FAQ (3–5)
  13. Pages liées (3–6 liens)
Flux interactif
Scénario:
Étape 1/3: Execution

Action is proposed as structured data (tool + args).

Le problème (côté prod)

Les agents sont des loops. Les loops veulent continuer.

Sans step cap, “fini” veut dire : l’agent abandonne par hasard. En prod, il n’abandonne pas.

Pourquoi ça casse en prod

1) “It’ll stop when it’s done” n’est pas un plan

En prod tu as :

  • tools flaky
  • rate limits
  • pannes partielles
  • tâches ambiguës

Ambigu + tools + pas de cap = un log avec 700 calls.

2) Sans stop reason, c’est invisible

Si tu vois seulement “timeout”, tu ne sais pas que les steps ont explosé. Les stop reasons aident à debugger.

3) Enforce dans la run loop

Pas dans l’UI. Pas “la plupart du temps”. Dans la loop, à chaque step.

Exemple d’implémentation (code réel)

Un step guard minimal :

PYTHON
from dataclasses import dataclass


@dataclass(frozen=True)
class StepPolicy:
  max_steps: int = 25


class StepExceeded(RuntimeError):
  def __init__(self, stop_reason: str):
      super().__init__(stop_reason)
      self.stop_reason = stop_reason


def run(task: str, *, policy: StepPolicy) -> dict:
  steps = 0
  try:
      while True:
          steps += 1
          if steps > policy.max_steps:
              raise StepExceeded("max_steps")

          action = llm_decide(task)  # (pseudo)
          if action.kind != "tool":
              return {"status": "ok", "answer": action.final_answer, "steps": steps}

          obs = call_tool(action.name, action.args)  # (pseudo)
          task = update(task, action, obs)  # (pseudo)

  except StepExceeded as e:
      return {"status": "stopped", "stop_reason": e.stop_reason, "steps": steps}
JAVASCRIPT
export class StepExceeded extends Error {
constructor(stopReason) {
  super(stopReason);
  this.stopReason = stopReason;
}
}

export function run(task, { maxSteps = 25 } = {}) {
let steps = 0;
try {
  while (true) {
    steps += 1;
    if (steps > maxSteps) throw new StepExceeded("max_steps");

    const action = llmDecide(task); // (pseudo)
    if (action.kind !== "tool") return { status: "ok", answer: action.finalAnswer, steps };

    const obs = callTool(action.name, action.args); // (pseudo)
    task = update(task, action, obs); // (pseudo)
  }
} catch (e) {
  if (e instanceof StepExceeded) return { status: "stopped", stopReason: e.stopReason, steps };
  throw e;
}
}

Incident réel (avec chiffres)

Un agent devait “juste” collecter une liste de résultats.

Il n’avait :

  • ni step cap
  • ni loop detection
  • et un tool retournait des résultats légèrement différents

Résultat :

  • ~700 tool calls en un run
  • ~18 minutes de runtime
  • pas un gros coût (chance), mais rate limits + queue delay, oui

Fix :

  1. step cap + stop reason
  2. loop detection (args hash)
  3. dedupe/caching sur les mêmes queries

Compromis

  • Les step limits stoppent parfois tôt. Mieux que non borné.
  • Si tu mets trop bas, tu vas avoir plus de “stopped” → il faut une UX.
  • Step limits sans time/cost budgets, c’est incomplet (mais déjà utile).

Quand NE PAS l’utiliser

  • Honnêtement : utilise toujours un cap. Si tu ne veux pas de max_steps, il te faut d’autres budgets durs.

Checklist (copier-coller)

  • [ ] max_steps par run
  • [ ] stop reason max_steps loggé + surfacé
  • [ ] step count dans les traces
  • [ ] loop detection / no-progress stop
  • [ ] combiné avec time + cost budgets

Config par défaut sûre (JSON/YAML)

YAML
step_limits:
  max_steps: 25
stop_reasons:
  surface_to_user: true
  log: true

FAQ (3–5)

Je mets quoi comme max_steps ?
Commence à 25. Mesure les stops. Si ça stoppe souvent, c’est un problème de scope/outils/prompt, pas juste le chiffre.
Max_steps suffit ?
Non. Ajoute aussi max_seconds, max_tool_calls, souvent max_usd.
Quel stop reason name ?
Court et machine-friendly : max_steps. Tu vas vouloir des alertes et dashboards.

Q: Je mets quoi comme max_steps ?
A: Commence à 25. Mesure les stops. Si ça stoppe souvent, c’est un problème de scope/outils/prompt, pas juste le chiffre.

Q: Max_steps suffit ?
A: Non. Ajoute aussi max_seconds, max_tool_calls, souvent max_usd.

Q: Quel stop reason name ?
A: Court et machine-friendly : max_steps. Tu vas vouloir des alertes et dashboards.

Pages liées (3–6 liens)

Pas sur que ce soit votre cas ?

Concevez votre agent ->
⏱️ 4 min de lectureMis à jour Mars, 2026Difficulté: ★★★
Implémenter dans OnceOnly
Budgets + permissions you can enforce at the boundary.
Utiliser dans OnceOnly
# onceonly guardrails (concept)
version: 1
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
  max_usd: 1.00
policy:
  tool_allowlist:
    - search.read
    - http.get
writes:
  require_approval: true
  idempotency: true
controls:
  kill_switch: { enabled: true }
Intégré : contrôle en productionOnceOnly
Ajoutez des garde-fous aux agents tool-calling
Livrez ce pattern avec de la gouvernance :
  • Budgets (steps / plafonds de coût)
  • Permissions outils (allowlist / blocklist)
  • Kill switch & arrêt incident
  • Idempotence & déduplication
  • Audit logs & traçabilité
Mention intégrée : OnceOnly est une couche de contrôle pour des systèmes d’agents en prod.
Auteur

Cette documentation est organisée et maintenue par des ingénieurs qui déploient des agents IA en production.

Le contenu est assisté par l’IA, avec une responsabilité éditoriale humaine quant à l’exactitude, la clarté et la pertinence en production.

Les patterns et recommandations s’appuient sur des post-mortems, des modes de défaillance et des incidents opérationnels dans des systèmes déployés, notamment lors du développement et de l’exploitation d’une infrastructure de gouvernance pour les agents chez OnceOnly.