Step Limits für AI Agents (Stop Loops) + Code

Step Limits sind die billigste Loop-Versicherung. So caps’t du Agent-Steps, surfacest Stop-Reasons und verhinderst 700 Tool Calls.
Auf dieser Seite
  1. Problem (aus der Praxis)
  2. Warum das in Production bricht
  3. 1) „It’ll stop when it’s done“ ist keine Strategie
  4. 2) Ohne Stop-Reason ist es unsichtbar
  5. 3) Steps müssen in der Run Loop enforced werden
  6. Implementierungsbeispiel (echter Code)
  7. Echter Incident (mit Zahlen)
  8. Abwägungen
  9. Wann du es NICHT nutzen solltest
  10. Checkliste (Copy/Paste)
  11. Sicheres Default-Config-Snippet (JSON/YAML)
  12. FAQ (3–5)
  13. Verwandte Seiten (3–6 Links)
Interaktiver Ablauf
Szenario:
Schritt 1/3: Execution

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

Problem (aus der Praxis)

Agenten sind Loops. Loops wollen weiterlaufen.

Wenn du keinen Step Cap hast, dann ist „fertig“ einfach: wenn der Agent zufällig aufgibt. In Prod heißt das: er gibt nicht auf.

Warum das in Production bricht

1) „It’ll stop when it’s done“ ist keine Strategie

In echten Systemen gibt es:

  • flaky tools
  • rate limits
  • partial outages
  • ambiguous tasks

Und die Kombination aus „ambiguous“ + „tools“ + „no cap“ ist, wie du 700 Calls in ein Logfile bekommst.

2) Ohne Stop-Reason ist es unsichtbar

Wenn du nur „timeout“ siehst, weiß niemand, dass Steps eskaliert sind. Stop-Reasons sind Debugging.

3) Steps müssen in der Run Loop enforced werden

Nicht nur im UI. Nicht nur im Agent Code „meistens“. In der Loop, jedes Mal.

Implementierungsbeispiel (echter Code)

Ein Step Guard, der:

  • step counter incremented
  • stop reason wirft
  • im Ergebnis surfaced
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;
}
}

Echter Incident (mit Zahlen)

Wir hatten einen Agenten, der „einfach nur“ eine Liste von Ergebnissen sammeln sollte.

Er hatte:

  • keine Step Caps
  • keine Loop Detection
  • ein Tool, das gelegentlich leicht andere Ergebnisse liefert

Ergebnis:

  • ~700 Tool Calls in einem Run
  • ~18 Minuten Laufzeit
  • bill war nicht gigantisch (glücklicherweise), aber Rate Limits + Queue Delay waren real

Fix:

  1. Step cap + stop reason
  2. loop detection (same args hash)
  3. dedupe/caching bei gleichen queries

Abwägungen

  • Step Limits stoppen manchmal früh. Besser als unbounded.
  • Wenn du zu niedrig setzt, bekommst du mehr „stopped“ Responses → du brauchst UX.
  • Step Limits ohne Time/Cost Budgets sind unvollständig (aber trotzdem wertvoll).

Wann du es NICHT nutzen solltest

  • Eigentlich immer nutzen. Wenn du wirklich keine Steps limitieren willst, brauchst du andere harte Budgets.

Checkliste (Copy/Paste)

  • [ ] max_steps pro run
  • [ ] Stop reason max_steps geloggt + surfaced
  • [ ] Step count in traces (debug)
  • [ ] loop detection / no-progress stop
  • [ ] kombiniert mit time + cost budgets

Sicheres Default-Config-Snippet (JSON/YAML)

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

FAQ (3–5)

Wie setze ich max_steps?
Starte mit 25. Miss stops. Wenn’s oft stoppt, sind Tooling/Prompt/Task-Scoping das Problem – nicht die Zahl.
Reicht max_steps alleine?
Nein. Du willst auch max_seconds, max_tool_calls und oft max_usd.
Was ist der beste Stop-Reason Name?
Kurz und maschinenlesbar: max_steps. Du willst Alerts und Dashboards.

Q: Wie setze ich max_steps?
A: Starte mit 25. Miss stops. Wenn’s oft stoppt, sind Tooling/Prompt/Task-Scoping das Problem – nicht die Zahl.

Q: Reicht max_steps alleine?
A: Nein. Du willst auch max_seconds, max_tool_calls und oft max_usd.

Q: Was ist der beste Stop-Reason Name?
A: Kurz und maschinenlesbar: max_steps. Du willst Alerts und Dashboards.

Nicht sicher, ob das dein Fall ist?

Agent gestalten ->
⏱️ 4 Min. LesezeitAktualisiert Mär, 2026Schwierigkeit: ★★★
In OnceOnly umsetzen
Budgets + permissions you can enforce at the boundary.
In OnceOnly nutzen
# 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 }
Integriert: Production ControlOnceOnly
Guardrails für Tool-Calling-Agents
Shippe dieses Pattern mit Governance:
  • Budgets (Steps / Spend Caps)
  • Tool-Permissions (Allowlist / Blocklist)
  • Kill switch & Incident Stop
  • Idempotenz & Dedupe
  • Audit logs & Nachvollziehbarkeit
Integrierter Hinweis: OnceOnly ist eine Control-Layer für Production-Agent-Systeme.
Autor

Diese Dokumentation wird von Engineers kuratiert und gepflegt, die AI-Agenten in der Produktion betreiben.

Die Inhalte sind KI-gestützt, mit menschlicher redaktioneller Verantwortung für Genauigkeit, Klarheit und Produktionsrelevanz.

Patterns und Empfehlungen basieren auf Post-Mortems, Failure-Modes und operativen Incidents in produktiven Systemen, auch bei der Entwicklung und dem Betrieb von Governance-Infrastruktur für Agenten bei OnceOnly.