WISSEN · AGENTEN

Agenten scheitern leise

Klassische Software scheitert laut: mit Stacktrace, Alarm und rotem Dashboard. Ein KI-Agent scheitert anders: Er läuft weiter und produziert etwas, das aussieht wie Arbeit. Fünf Geschichten aus unserer eigenen Entwicklungspraxis.

Klassische Software scheitert ehrlich. Eine Exception hat einen Stacktrace, ein abgestürzter Prozess löst einen Alarm aus, ein 500er färbt das Dashboard rot. Die gesamte Betriebspraxis der IT (Monitoring, Alerting, Bereitschaft) beruht auf einer stillen Annahme: Wenn etwas kaputt ist, merkt man es.

KI-Agenten brechen diese Annahme. Ein Sprachmodell in einer Schleife produziert immer irgendetwas, auch wenn seine Werkzeuge leer laufen, sein Kontext beschnitten wurde oder sein Stop-Signal verloren ging. Der Fehler äußert sich nicht als Ausfall, sondern als plausibel aussehendes Ergebnis. In Masse.

Was folgt, sind fünf Fehlerbilder aus unserer eigenen Entwicklungspraxis: aus agentischen Systemen, die wir auf eigener Hardware mit lokalen Modellen bauen und betreiben. Jede dieser Geschichten ist uns selbst passiert. Keine davon hat eine Exception geworfen.

Der gefährlichste Fehler eines Agenten ist nicht der Absturz. Es ist das Ergebnis, das aussieht wie Arbeit.

Das Update, das den Stopp entfernte

Eine unserer Pipelines lässt lokale Sprachmodelle über Nacht Skripte generieren, automatisch bewerten und in Runden weiter verbessern. Vier parallele Inferenz-Slots, jeder mit großem Kontextfenster. Eines Abends schien die zweite Runde festzuhängen. Kein Fehler, kein Absturz: Das System lief einfach weiter.

Die Ursache lag drei Tage zurück. Ein Update des Chat-Templates hatte ein Werkzeug-Token versehentlich als Ende-Signal deklariert. Der Inferenz-Server, bei uns llama.cpp, verlor darüber das echte Stop-Token aus seiner Liste. Das Ergebnis: Generationen von über 90.000 Tokens, die niemand angefordert hatte. Alle vier Slots belegt. Das Gateway hatte die Anfragen da längst mit einem Timeout beantwortet. Die verwaisten Generationen dekodierten im Hintergrund weiter, unsichtbar für jeden, der nur auf die API schaute.

Drei Konsequenzen haben sich seitdem bewährt. Modell-Updates sind eine Lieferkette: Gewichte, Chat-Template und Tokenizer-Metadaten ändern das Verhalten, auch wenn „nur eine Kleinigkeit“ gepatcht wurde. Nach jedem Update prüfen wir die Stop-Token-Konfiguration im Log des Inferenz-Servers [1]. Und eine abgeschnittene Generation (finish_reason: length) ist seither ein Alarmsignal erster Klasse im Monitoring, keine Fußnote.

# after every model update: is the stop-token list still intact?
podman logs llama-server 2>&1 | grep special_eog_ids

# in the harness: a truncated generation is an alarm, not a footnote
if response.finish_reason == "length":
    alert("runaway_generation", model=model, tokens=usage.completion_tokens)

Der Stapel namens „Sonstiges“

Ein Workflow bei uns sortiert einen Posteingang: Ein lokales Modell klassifiziert jede E-Mail in definierte Kategorien. Zweimal ist dieser Workflow leise gescheitert: auf zwei verschiedene Arten, mit demselben Symptom.

Der erste Fall: eine gut gemeinte Ausgabe-Begrenzung. Ein Reasoning-Modell verbrauchte sein Token-Budget mitten im Denken; die eigentliche Antwort blieb leer, und die Pipeline sortierte jede einzelne Mail in „Sonstiges“ ein. Es sah aus wie ein Qualitätsproblem des Modells. Es war ein Budget-Problem. Das gesetzte max_tokens zu entfernen, behob den Fehler vollständig.

Der zweite Fall: Der Modell-Server war nicht erreichbar. Jeder Aufruf schlug in Millisekunden fehl, und der Workflow verbuchte gehorsam jede Mail als „Sonstiges (Fehler)“, während die Fortschrittsanzeige wie eingefroren wirkte, weil alles so schnell „fertig“ wurde. Heute bricht der Workflow hart ab, wenn die erste Welle von Aufrufen geschlossen fehlschlägt, mit einem roten Banner statt eines vollständig „verarbeiteten“ Posteingangs.

# fail fast: if the first wave fails across the board, stop the job
first = [classify(mail) for mail in inbox[:3]]
if all(r.status >= 500 for r in first):
    raise PipelineDown("model unreachable, refusing to file everything as 'Other'")

Die Lehre ist unbequem: Niemand kontrolliert den Stapel „Sonstiges“ nach. Eine plausible falsche Antwort aus einer versteckten Begrenzung ist gefährlicher als ein lauter Kontextfehler. Und eine Pipeline, deren Modell ausfällt, muss stehen bleiben, nicht einheitlich falsch „weiterarbeiten“.

Erst das Werkzeug prüfen, dann das Modell beschuldigen

Ein autonomer Agent sollte ein Drittsystem über dessen Skript-API steuern. Das lokale 12B-Modell schlug sich schlecht; der Wechsel auf ein großes Cloud-Modell brachte etwas Besserung. Die naheliegende Diagnose: Das kleine Modell ist zu schwach.

Die echte Ursache stand in den Logs. Das Werkzeug, das die API-Referenz des Systems für den Agenten aufbereitete, lieferte still null Funktionen und null Namespaces: ein Parser, den Windows-Zeilenenden und ein typisiertes Stub-Format aus dem Tritt gebracht hatten. Beide Modelle hatten die ganze Zeit ohne echte API-Referenz gearbeitet und Funktionssignaturen aus dem Gedächtnis ihrer Trainingsdaten rekonstruiert. Das kleine Modell hatte sogar zweimal gemeldet, die Funktionsliste wirke leer. Es hatte recht – und wurde ignoriert. Der Fix waren ein paar Zeilen im Parser: von null auf 49 Funktionen.

„Das Modell ist zu dumm“ ist die teuerste Fehldiagnose im Agenten-Betrieb, denn ihre Therapie heißt größeres Modell und mehr Hardware statt eines Bugfixes. Seitdem gilt bei uns: Werkzeug-Ausgaben bekommen harte Invarianten. Eine Referenz mit null Einträgen ist kein leeres Ergebnis, sondern ein Grund, die Pipeline anzuhalten. Und wenn ein Modell meldet, seine Eingabe sehe leer aus, lohnt ein Blick.

# a tool output with zero entries is a reason to stop, not an input
reference = parse_api_stubs(raw_docs)
if not reference.functions:
    raise ToolOutputError("API reference is empty, halting pipeline")

Fortschritt, der keiner ist

Eine Extraktions-Pipeline sollte Fakten aus einem umfangreichen Dokumentenbestand in eine Wissensbasis überführen, Abschnitt für Abschnitt, in einer Schleife mit der Abbruchbedingung: Stoppe, wenn keine neuen Fakten mehr hinzukommen. Ein einzelner Abschnitt lieferte 155 „neue“ Fakten. Bei näherem Hinsehen waren es überwiegend Umformulierungen: zehn bis dreizehn Varianten desselben Sachverhalts pro Entität. Jede neue Formulierung war technisch ein neuer Eintrag und setzte den Fortschritts-Zähler zurück. Die Schleife lief produktiv aussehend im Kreis.

Ein schärferer Prompt („keine Umformulierungen!“) änderte nichts. Auch lexikalische Ähnlichkeitsmaße trennten eine Paraphrase nicht zuverlässig von einem echten neuen, verwandten Fakt. Was fehlte, war eine semantische Dublettenerkennung: per Embedding statt Zeichenkettenvergleich.

Das Muster ist größer als dieses Beispiel: Ein Modell in einer Schleife erfüllt den Buchstaben seiner Abbruchbedingung, nicht ihre Absicht. Fortschrittsmaße für Agenten müssen Bedeutung messen, nicht Zeichenketten. Sonst „macht das System Fortschritt“, solange Strom fließt.

Grüne Dashboards, erfundene Antworten

Zwei kürzere Fundstücke aus derselben Familie. Erstens: Im Model Context Protocol, dem offenen Standard für die Werkzeug-Anbindung von Agenten, kommt ein fehlgeschlagener Tool-Aufruf als Fehlermarkierung innerhalb einer erfolgreichen HTTP-Antwort zurück [2]. Ein Logger, der nur den Statuscode ansieht, zeigt eine Fehlerrate von null, während jeder einzelne Aufruf scheitert. Der Transport meldet Erfolg; die Wahrheit liegt eine Protokoll-Ebene tiefer.

# MCP: the transport says 200, the truth sits in the payload
result = await session.call_tool(name, args)
if result.isError:
    metrics.increment("tool_error", tool=name)  # this call was NOT a success

Zweitens: In einem Assistenz-System hatten wir die Web-Suche abgeschaltet, sauber aus der Werkzeugliste entfernt. Die System-Instruktion aber sagte weiterhin: „Nutze die Web-Suche für aktuelle Informationen.“ Das Modell löste den Widerspruch auf seine Art: Es erfand Suchergebnisse, inklusive eines frei halluzinierten Wetterberichts, im Brustton der Überzeugung [3]. Der Fix war nicht, das Werkzeug besser zu verstecken, sondern dem Modell explizit mitzuteilen, dass es fehlt, und Erfindungen zu untersagen. Danach kam auf dieselbe Frage die ehrliche Antwort: keine aktuellen Daten verfügbar.

Halluzination entsteht in der Lücke zwischen dem, was einem Agenten erlaubt ist, und dem, was ihm gesagt wurde. Wer Werkzeuge pro Mandant, pro Rolle oder aus Compliance-Gründen abschaltet – im Unternehmenseinsatz der Normalfall –, muss genau diesen Fall explizit testen.

Laut scheitern ist eine Architektur-Entscheidung

Fünf Geschichten, ein Muster: Nirgendwo flog eine Exception. Jedes System lief weiter und produzierte etwas, das wie Arbeit aussah: endlose Generationen, ein sortierter Posteingang, API-Aufrufe aus dem Gedächtnis, eine wachsende Wissensbasis, ein grünes Dashboard. Zuverlässige Agenten entstehen deshalb nicht dadurch, dass solche Fehler nie passieren. Sie entstehen dadurch, dass Scheitern sichtbar wird, bevor es real kostet. Bevor die GPU nächtelang Ausschuss rechnet. Und bevor Menschen von Hand korrigieren, was die KI ihnen eigentlich abnehmen sollte [4]:

Eine Beobachtung zum Schluss: Keiner dieser Fehler wurde gefunden, indem jemand „das Modell“ anschaute. Jeder einzelne wurde in den Logs einer Schicht gefunden, die wir selbst betreiben: im Inferenz-Server, im Gateway, im Protokoll der Orchestrierung. On-Premise verhindert diese Fehler nicht. Aber es macht jede Schicht einsehbar, in der sie sich verstecken. Bei einer verwalteten Agenten-Plattform sind mehrere dieser Schichten die Black Box eines Dritten – und ein leiser Fehler bleibt leise. Wie eine Appliance aussieht, bei der Hardware, Modell und Agenten-Orchestrierung unter Ihrer Kontrolle laufen, lesen Sie unter Produkt, und was Agenten im Mittelstand heute konkret übernehmen, unter Anwendung.

Quellen

  1. llama.cpp – Inferenz-Server für lokale Modelle; Stop-Token-/EOG-Konfiguration und Chat-Templates.
  2. Model Context Protocol – Spezifikation (Fehlerbehandlung von Tool-Aufrufen innerhalb erfolgreicher Antworten).
  3. OWASP – Top 10 for LLM Applications 2025 (u. a. LLM09: Misinformation).
  4. Anthropic – Building effective agents (Grundmuster zuverlässiger Agenten-Architekturen).

Betreiben heißt beobachten können.

Sprechen wir dreißig Minuten darüber, wie Agenten auf Ihrer eigenen Infrastruktur laufen, mit Einblick in jede Schicht.

Erstgespräch vereinbaren →
Erstgespräch vereinbaren →