Der Spurenleser – Fehlersuche in einer verteilten Landschaft
Wenn ein fachliches Testszenario in der Pipeline rot wird und ein Dutzend Dienste gleichzeitig deployen, ist die Suche nach dem Verursacher anstrengender als die Behebung. Warum die Diagnose eines Assistenten mit Logs und Traces steht und fällt — und er trotzdem drei Hypothesen liefern muss statt einer Antwort.
13.09.2026
•11 Min. LesezeitHinweis zum Inhalt
Dieser Beitrag beschreibt meine Erkenntnisse beim Aufbau von KI-Assistenten für den Produktprozess. Das sind persönliche Erfahrungen, aus denen ich Maßnahmen abgeleitet habe, die für meine Projekte funktioniert haben. Konkrete Systemnamen, Kennzahlen und Projektinhalte bleiben außen vor.
Die bisherigen Beiträge dieser Reihe drehten sich um Anforderungen. Dieser handelt von einer ganz anderen Aufgabe, die auf derselben Architektur läuft — und die für mich der überzeugendste Beleg dafür ist, dass ein Baukasten mehr kann als das, wofür er gebaut wurde.
Die Ausgangslage
Ein Fehler wird gemeldet. Nicht von einem Nutzer, sondern von einer Pipeline — und nicht in Prosa, sondern als fehlgeschlagenes Szenario:
Szenario: Bestätigte Buchung stornieren
Angenommen es existiert eine bestätigte Buchung
Wenn der Kunde die Stornierung auslöst
Dann hat die Buchung den Status "storniert"
✗ Schritt 3 fehlgeschlagen — erwartet "storniert", war "bestätigt"
Das liest sich präzise, und genau darin liegt die Falle. Der Text sagt exakt, was nicht stimmt — und kein Wort darüber, wo. Ein fachliches Szenario beschreibt einen Vertrag über die gesamte Kette hinweg. Wird es rot, hat irgendwer in dieser Kette seinen Teil des Vertrags gebrochen. Welcher Dienst das war, steht nicht dabei — das ist ja gerade der Sinn eines fachlich formulierten Tests.
Solange nur ein Dienst im Spiel ist, bleibt das beherrschbar. Teuer wird der Zustand, der in einer Microservice-Landschaft der Normalfall ist: ein Dutzend Dienste, ein Dutzend eigener Pipelines — und alle liefern gegen dieselbe Integrationsstufe. Zum Zeitpunkt des roten Laufs war dort nicht eine Änderung aktiv, sondern sieben. Von sieben Teams, die nichts voneinander wussten.
Damit verschiebt sich die Frage. Sie lautet nicht mehr „was ist kaputt", sondern:
Wessen Änderung, aus welcher Pipeline, hat diesen Lauf rot gemacht?
Und die kann ausgerechnet das Team, dem der Test gehört, aus eigener Kraft nicht beantworten. Es sieht seinen Commit, seinen Build, sein Log. Es sieht nicht, dass vier Minuten vorher ein anderer Dienst ein Feld in einer Antwort umbenannt hat.
Der Reflex ist überall derselbe — und überall berechtigt: „Bei uns hat sich nichts geändert." Sieben Teams haben recht, der Lauf ist trotzdem rot.
Was dann passiert, kennt jeder: Der Lauf wird wiederholt. Beim zweiten Mal ist er grün, weil das fremde Deployment inzwischen durch ist — und das Szenario bekommt still das Etikett „flaky". Kein Befund, kein Ticket, keine Ursache. Beim übernächsten Mal glaubt niemand mehr, dass Rot etwas bedeutet. Das ist der eigentliche Schaden: nicht der einzelne Fehlschlag, sondern eine Suite, der keiner mehr traut.
Die Erfahrung, die jeder kennt, der so etwas betreibt: Die Suche dauert länger als die Behebung. Nicht immer, aber oft genug, dass sie die eigentliche Belastung ist — die Korrektur danach ist häufig ein Einzeiler.
Und der Weg dorthin ist selten analytisch. Er verläuft über die Frage „wer könnte wissen, wo das herkommt", über Nachrichten in mehreren Kanälen, über Kollegen, die gerade etwas anderes tun — und über die Zeitachsen mehrerer Pipelines, die am Ende jemand von Hand nebeneinanderlegt.
Was der Assistent leistet — und was nicht
Er stellt eine Diagnose. Wie belastbar sie ist, entscheidet nicht das Modell, sondern das Material.
Das ist der Punkt, den ich anfangs falsch eingeschätzt hatte. Ich hatte den Assistenten als reinen Wegweiser gedacht: ein grober erster Verdacht, die Feinarbeit beim Menschen. Sobald er mehr sehen konnte als den beschriebenen Sollzustand, war das eine deutliche Untertreibung. Die Qualität der Analyse ist keine Eigenschaft des Assistenten — sie ist eine Funktion dessen, was die Systeme drumherum an Belegen hergeben:
| Was angebunden ist | Was der Assistent daraus machen kann |
|---|---|
| Der Fehlerbericht — das fehlgeschlagene Szenario im Wortlaut | Einstieg — welcher fachliche Vertrag ist an welchem Schritt gebrochen |
| + Quellcode der Integrationstests | Der tatsächliche Ablauf — welche Endpunkte das Szenario in welcher Reihenfolge aufruft und was genau zugesichert war |
| + Quellcode aller beteiligten Microservices | Kandidaten mit Codebezug — welcher Dienst bedient diesen Endpunkt, welche Aufrufe löst er selbst aus, an welcher Stelle wird der Status gesetzt |
| + Dokumentation, Servicekatalog, abgeschlossene Vorgänge | Zuständigkeit und Vorgeschichte — welches Team, welche vergleichbaren Fälle gab es schon |
| + Logs der beteiligten Dienste | Fundstellen — welcher Aufruf ist wo und mit welcher Meldung gescheitert |
| + Traces und Aufrufbeziehungen über die ganze Kette | Root Cause — der Sprung, an dem der Vertrag gebrochen wurde, mit Beleg |
| + Deployment- und Pipeline-Historie (bei mir offen) | Auslöser — welche Änderung war zum Zeitpunkt des roten Laufs frisch |
Die Leiter hat eine Bruchkante in der Mitte. Alles oberhalb der Logs ist statisch: Fehlerbericht, Tests, Quellcode und Dokumentation sagen, wie es gemeint war. Damit kommt man erstaunlich weit — der Quellcode der Tests und der Dienste beantwortet die Frage „welche Komponenten sind an diesem Szenario überhaupt beteiligt" präziser als jedes Architekturbild, weil er nicht veralten kann.
Was der statische Teil nicht beantwortet, ist die Frage nach diesem Lauf. Dafür braucht es den dynamischen: Ein Log sagt, dass ein Aufruf fehlgeschlagen ist. Ein Trace sagt, in welcher Reihenfolge, zwischen welchen Diensten und in welcher Version — und damit lässt sich das „Bei uns hat sich nichts geändert" aus dem vorigen Abschnitt gegen Daten prüfen statt gegen Erinnerung. Das ist der Punkt, an dem aus Eingrenzen tatsächlich Ursachenfindung wird.
Die letzte Stufe der Leiter fehlt in meinem Aufbau allerdings: Die Deployment- und Pipeline-Historie ist nicht angebunden. Der Assistent kann also aus Logs und Traces rekonstruieren, wo der Vertrag gebrochen wurde — aber nicht, wessen Deployment vier Minuten vorher durchgelaufen ist. Die Frage aus dem vorigen Abschnitt beantwortet er damit nur zur Hälfte: Er benennt den Bruch, den Auslöser muss jemand daneben legen.
Ich führe die Stufe trotzdem in der Tabelle auf, weil sie aus meiner Sicht das beste Verhältnis von Aufwand zu Wirkung hat, das in diesem Aufbau noch offen ist. Es geht um eine überschaubare Datenquelle, die ohnehin existiert — wer wann was auf welche Stufe gebracht hat — und sie beantwortet genau die Frage, an der die Suche am längsten hängt. Angebunden ist sie noch nicht; von allen Ausbauschritten wäre es der erste, den ich angehen würde.
Und was er auch dann nicht leistet:
Er entscheidet nicht. Auch eine gut belegte Diagnose ist ein Befund, den ein Mensch bestätigt, bevor daraus ein Ticket in einem fremden Team wird.
Er diagnostiziert nichts, was er nicht sieht. Was nicht angebunden ist, fehlt — und muss als fehlend im Ergebnis stehen, nicht stillschweigend weggelassen werden.
Er legt sich nicht auf eine Ursache fest, auch wenn die Belege es hergeben würden. Warum ausgerechnet das die wichtigste Regel ist, steht weiter unten.
| Teil | Inhalt |
|---|---|
| Aufgabe | Aus einer Fehlerbeschreibung Hypothesen über beteiligte Komponenten ableiten — und sie so weit zur Ursache verdichten, wie die Belege tragen |
| Regeln | Nie nur eine Hypothese; jede Hypothese braucht einen benannten Beleg und ein Falsifikationskriterium |
| Quellen | Der Fehlerbericht, der Quellcode der Integrationstests und der beteiligten Microservices, Servicekatalog mit Zuständigkeiten, Schnittstellenbeschreibungen, Architekturdokumentation, abgeschlossene Vorgänge — und, wo angebunden, Logs, Traces und Aufrufbeziehungen |
| Ausgabeschema | Mehrere gewichtete Hypothesen mit Begründung, Beleg und Prüfschritt |
Zum Mitnehmen: die Vorlage für eine Fehleranalyse
# Fehleranalyse: <Kurzbeschreibung>
## Symptom
<Wie der Fehler gemeldet wurde — im Wortlaut, nicht interpretiert.>
## Beobachtbare Rahmenbedingungen
<Seit wann bzw. seit welchem Lauf? Immer oder nur sporadisch?
Reproduzierbar? „Unbekannt" ist eine gültige Antwort.>
## Hypothesen
### H-1 · Confidence: <hoch | mittel | niedrig>
- **Komponente:** <Vermuteter Ursprung>
- **Zuständigkeit:** <Team oder Rolle, falls bekannt>
- **Begründung:** <Warum kommt diese Komponente in Frage?>
- **Stützt sich auf:** <Codestelle, Testfall, Dokument, Schnittstelle,
Log- oder Trace-Fundstelle, früherer Vorgang — so konkret, dass es
nachschlagbar ist>
- **Nächster Prüfschritt:** <Was konkret zu prüfen ist>
- **Widerlegt, wenn:** <Woran erkennt man, dass diese Spur falsch ist?>
### H-2 · Confidence: …
- …
### H-3 · Confidence: …
- …
## Nicht berücksichtigt
| Quelle | Grund |
|--------|-------|
| <z. B. Deployment-Historie> | <nicht angebunden> |
Und das Regelwerk:
## Regeln für diesen Assistenten
**Pflicht**
- Mindestens drei Hypothesen. Auch wenn eine offensichtlich wirkt.
- Jede Hypothese braucht ein Widerlegungskriterium.
- Jede Hypothese braucht einen konkreten nächsten Prüfschritt.
- Die Confidence richtet sich nach der Beleglage, nicht nach der
Plausibilität der Erzählung.
- Jede Quelle, die nicht angebunden oder nicht erreichbar war, steht
unter „Nicht berücksichtigt".
**Verboten**
- Sich auf eine Ursache festlegen.
- Eine Hypothese ohne Beleg aus einer benannten Quelle.
- Laufzeitverhalten behaupten, das nicht aus einem Log oder Trace
hervorgeht — Code und Dokumentation beschreiben den Sollzustand,
nicht diesen Lauf.
Das Feld Widerlegt, wenn ist der Grund, warum diese Vorlage funktioniert. Dazu jetzt.
Was beim ersten Entwurf nicht funktioniert hat
Der Assistent war zu überzeugend.
Die erste Fassung lieferte genau eine Antwort, sauber begründet, mit selbstbewusstem Ton. Und genau das war das Problem.
Ein plausibel klingender erster Verdacht wirkt wie ein Ergebnis. Wer ihn liest, prüft ihn — und hört auf, andere Möglichkeiten in Betracht zu ziehen. Wenn der Verdacht stimmt, ist das großartig. Wenn er falsch ist, hat der Assistent die Suche nicht verkürzt, sondern in eine Sackgasse gelenkt und dabei die Zeit gekostet, die man ohne ihn für die richtige Spur gehabt hätte.
Das ist ein bekanntes menschliches Muster, kein technisches. Ein früher Ankerpunkt verzerrt alles, was danach kommt — und ein maschinell erzeugter Ankerpunkt wirkt objektiver, als er ist.
Ein falscher erster Verdacht ist gefährlicher als gar keiner.
Die Konsequenz war, dem Assistenten zu verbieten, sich festzulegen. Mindestens drei Hypothesen, jede mit Gewichtung, jede mit einem konkreten nächsten Schritt und jede mit dem Kriterium, an dem man erkennt, dass sie falsch ist.
Dazu die Regel, die den Ton vom Inhalt trennt: Die Gewichtung hängt an den Belegen, nicht an der Formulierung. Eine Hypothese, die auf einem Trace steht, darf „hoch" sein. Eine, die nur aus der Architekturdokumentation folgt, nicht — auch wenn sie sich genauso flüssig liest. Genau diese beiden Fälle waren in der ersten Fassung nicht auseinanderzuhalten, und deshalb wirkte sie über ihre Datenlage hinaus überzeugend.
Der Nebeneffekt war der eigentliche Gewinn: Aus einer Antwort, die man glaubt oder nicht, wird eine Arbeitsliste, die man abarbeitet.
Grenzen
Die Diagnose ist nur so gut wie das, was angebunden ist. Wo nur der statische Teil der Leiter zur Verfügung steht — Fehlerbericht, Tests, Quellcode, Dokumentation —, argumentiert der Assistent über den Sollzustand: über ein System, wie es gemeint ist, nicht wie es in diesem Lauf gelaufen ist. Der Quellcode ist dabei die einzige Quelle, die nicht veralten kann. Bei der Dokumentation ist das anders: Wo die Landschaft sich verändert hat und die Beschreibung nicht, argumentiert er über ein System, das es so nicht mehr gibt.
Das ist keine Kleinigkeit. Wer dieses Muster nutzen will, sollte wissen, worauf eine Diagnose jeweils steht, bevor er ihr vertraut — und den Abschnitt Nicht berücksichtigt ernst nehmen. Er ist der Unterschied zwischen „keine Spur gefunden" und „an dieser Stelle nicht gesucht". Bei mir steht dort regelmäßig die Deployment-Historie: ein bekannter, benannter blinder Fleck — dokumentiert, nicht versteckt.
Und der Umkehrschluss, den ich unterschätzt hatte: Er ersetzt keine Beobachtbarkeit — er lebt von ihr. Ich hatte erwartet, dass so ein Assistent dort am meisten hilft, wo es kein durchgehendes Tracing gibt. Es ist andersherum. Ohne Telemetrie bleibt er ein Wegweiser, der den Suchraum eingrenzt; mit ihr wird er ein Diagnosewerkzeug, das die Ursache benennt und belegt. Wer den größeren Nutzen will, investiert deshalb nicht in den Assistenten, sondern in die Datenlage, aus der er liest.
Fazit
Von allen Assistenten im Baukasten ist das der, der am wenigsten mit dem ursprünglichen Zweck zu tun hat — und der, bei dem die Rückmeldungen am deutlichsten waren.
Der Grund liegt aus meiner Sicht in der Art des Problems: Fehlersuche ist Suche, und Suche skaliert schlecht mit der Anzahl der Beteiligten. Ein Werkzeug, das den Suchraum eingrenzt, spart nicht die Behebung — es spart die Koordination davor. Und je besser die Beleglage, desto weniger bleibt vom Suchen überhaupt übrig: Aus „fragt mal in euren Kanälen" wird „schaut euch diesen Aufruf in diesem Trace an".
Und die wichtigste Gestaltungsentscheidung war trotzdem eine, die den Assistenten schwächer wirken lässt: Er darf sich nicht sicher sein — auch dann nicht, wenn die Belege es hergeben würden.
Damit schließt sich der rote Faden über alle vier Assistenten: der Ersteller weist Annahmen aus, der Transformer weist die Herkunft aus, der Kritiker weist ungeprüfte Stellen aus, der Spurenleser weist Unsicherheit aus. Viermal dasselbe Prinzip — ein Assistent, der seine eigenen Grenzen sichtbar macht.