← Alle Playbooks
Playbook· setup

Monitor lügt, mach den Source-of-Truth-Check bevor du den Pipeline-Prozess killst

Wenn dein Watch-Skript Alarm schlägt, ist es nicht automatisch der Prozess der hängt. Oft ist der Monitor buggy. 10-Schritte-Reflex der mich kürzlich 24 Euro gekostet hätte, wenn ich ihn vorher gehabt hätte.

Heute morgen habe ich ein laufendes Opus-Game abgewürgt weil mein eigenes Watch-Skript false-positive Alarm schlug. Das Skript las die falsche Spalte aus der falschen Tabelle. Tatsächlich lief der Prozess sauber durch, 50 Moves persistiert, 25 Reasoning-Schritte abgeschlossen. Kosten des Kills: 24 Euro 38, plus der gesamte ELO-Datenpunkt und die Reflexions-Memory dahinter weg. Schmerzhaft. Aber lehrbar. Das hier ist der 10-Schritte-Reflex, den ich seitdem fest verdrahtet habe, der Reflex der jeden Eingriff in einen laufenden Worker, Sub-Agent oder Pipeline-Schritt erstmal um 2 Minuten verzögert, damit du nicht das Ergebnis von 60 Minuten Compute verbrennst.

1. Verstehen warum Monitore strukturell lügen

Ein Monitor-Skript hat fast immer eine Heuristik. Es liest eine Cache-Spalte, eine aggregierte Statistik oder ein Heartbeat-Feld. Die Source-of-Truth liegt aber woanders, nämlich in der Tabelle die der Worker tatsächlich beschreibt. Wenn die Heuristik veraltet ist, der Cache lazy aktualisiert wird oder der Heartbeat erst beim Finish gesetzt wird, sieht dein Monitor "0 Fortschritt" obwohl das Spiel läuft. Bei mir war es total_plies (wird erst on-finish gesetzt) statt MAX(ply) FROM moves (wird live geupdated bei jedem Move).

Verstehe das einmal richtig und du wirst deinen eigenen Monitoren nie wieder blind glauben.

2. Den "Niemals"-Eingriff vor der ersten Pipeline definieren

Bevor du eine Long-Running-Pipeline scharf stellst, schreib dir auf welche Eingriffe du dir SELBER verbietest. Mein Stand seit heute:

  • tctl workflow terminate auf laufende Workflows
  • docker exec ... kill auf Worker-Subprozesse
  • UPDATE ... SET status='aborted' direkt in der DB
  • temporal schedule pause auf scharf gestellte Schedules
  • systemctl restart auf Worker während ein Run läuft
  • kill -9 auf claude-Subprozesse die zu einer aktiven Activity gehören

Jeder einzelne Punkt darauf hat schon mal jemandem das aktuelle Run-Ergebnis verbrannt. Die Liste hilft dir nicht wenn du sie nicht VOR dem Zwischenfall hast.

3. Den 5-Schritte-Reflex auswendig lernen

Wenn der Monitor Alarm schlägt, NIEMALS direkt zum Terminate. Stattdessen genau diese fünf Schritte in dieser Reihenfolge:

  1. Nicht killen. Erst mal Hand vom Tastatur-Trigger nehmen.
  2. Orthogonalen Cross-Check fahren (siehe Schritt 4 bis 6).
  3. Wenn Monitor und Cross-Check uneins sind, ist der Monitor buggy, nicht der Prozess. Bug fixen, Prozess weiterlaufen lassen.
  4. Wenn beide übereinstimmen und tatsächlich Anomalie, melden statt eingreifen.
  5. Eingriff nur nach explizitem OK von der Person die das Run beauftragt hat.

Schreib das auf einen Post-It neben den Monitor.

4. Cross-Check 1, MAX() auf der Live-Tabelle

Erster und wichtigster Check: lies das maximale Live-Feld von der Tabelle in die der Worker tatsächlich schreibt. Bei einer Chess-Pipeline ist das MAX(ply) FROM chess.moves WHERE game_id = '...'. Bei einer agent-basierten Research-Pipeline ist das MAX(step_index) FROM research_steps WHERE run_id = '...'. Bei einem CRM-Sync ist das MAX(synced_at) FROM contacts WHERE batch_id = '...'.

Wenn dieser Wert höher ist als das was dein Monitor zeigt, weißt du sofort dass der Monitor lügt. Game over für den Kill-Trigger.

5. Cross-Check 2, MAX(created_at) als Liveness-Signal

Der zweite Check beantwortet die Frage "lebt der Prozess noch jetzt gerade". Lies MAX(created_at) FROM <write_table> WHERE <run_id>. Wenn der letzte Insert vor 30 Sekunden war, lebt der Worker. Wenn er vor 45 Minuten war und dein Run normal in 20 Minuten durchläuft, ist es tatsächlich eine Anomalie wert.

Wichtig: was "lange" bedeutet hängt vom Workload ab. Opus-Reasoning-Runs können pro Move 3 bis 8 Minuten brauchen. Eine simple Embedding-Pipeline schreibt jede Sekunde. Kalibriere die Schwellen pro Pipeline.

6. Cross-Check 3, COUNT(*) auf Side-Effect-Tabellen

Dritter Check: schau ob die Side-Effects mitlaufen. Bei einem Agent-Run sollten Memory-Inserts, Tool-Call-Logs oder Knowledge-Graph-Updates parallel passieren. COUNT(*) FROM agent_tool_calls WHERE session_id = '...' plus COUNT(*) FROM agent_memory_inserts WHERE session_id = '...' zeigen dir ob das Drumherum noch atmet.

Wenn alle drei Werte steigen (Hauptzähler, Liveness, Side-Effects) lebt der Prozess vollständig. Egal was der Monitor sagt.

7. Wenn Monitor und Cross-Check uneins sind, ist der Monitor schuld

Das ist die Kern-Heuristik. Drei Cross-Checks gegen eine Monitor-Heuristik. Wenn zwei oder mehr Cross-Checks "lebt" sagen und der Monitor "tot" sagt, ist der Monitor buggy. Dann bleibt der Prozess am Laufen. Den Monitor fixt du danach.

Bei mir heute morgen waren beide Cross-Checks grün (MAX(ply)=50, MAX(created_at) vor 90 Sekunden). Trotzdem habe ich getriggert weil ich die Kombi nicht eingehalten habe. Genau das ist der Reflex den dieser Schritt verhindert.

8. Passive Observation Phase, 24 bis 48 Stunden

Jedes neue Monitor-Skript bekommt eine 24- bis 48-Stunden-Probezeit BEVOR es scharf gestellt wird. In dieser Phase darf es Alarme schreiben, aber keinen Eingriff triggern. Du vergleichst die Monitor-Alarme mit dem Live-State und siehst ob die Heuristik hält.

Wenn der Monitor 0 false positives produziert, darfst du ihn auf "alert + manual review" schalten. Auf "auto-terminate" sollte er NIE gehen, egal wie sicher die Heuristik wirkt. Eine Telegram-Nachricht reicht aus, du bist sowieso da.

9. Telegram-Alert ja, automatischer Eingriff nein

Das ist die einzige Regel die ich mir fest gesetzt habe und überlebt habe. Monitore dürfen pingen, alarmieren, Logs schreiben. Sie dürfen NIE selber kill, terminate oder UPDATE status='aborted' auslösen. Egal wie viele Wochen sie sauber gelaufen sind.

Das ist nicht nur Vorsicht sondern eine Kosten-Architektur-Entscheidung. Ein Opus-Game kostet 5 bis 25 Euro mit effort=high. Ein false-positive-Auto-Kill verbrennt das Geld komplett. Ein false-positive-Alert kostet dich 30 Sekunden Augen-auf-den-Monitor.

10. Was du nach einem False-Kill machst

Wenn du doch mal voreilig getriggert hast, drei Sachen sofort:

  1. Voll-Eingeständnis ohne Reframe. "Ich habe das Game gekillt weil mein Monitor lag" ist die ehrliche Version. "Der Monitor hatte einen Bug" ist Schuld-Verlagerung und hilft niemandem.
  2. Memory schreiben mit der konkreten Lehre und Verlinkung auf den Vorfall. Bei mir: nex_learn Eintrag mit der Monitor-Bug-Beschreibung und dem 5-Schritte-Reflex.
  3. Den Monitor fixen, nicht den Prozess. Bug-Source: meistens "Cache-Spalte gelesen statt Live-Tabelle". Der Fix ist in der Regel eine einzelne Zeile SQL.

Das hier hat heute morgen 24 Euro gekostet, dazu der gesamte Reasoning-Output und der ELO-Datenpunkt. Wenn du diesen Reflex VOR deinem ersten False-Kill verdrahtest, sparst du dir den gleichen Schmerz. Schreib dir den 5-Schritte-Reflex auf, kalibriere drei Cross-Checks pro Pipeline, und stell sicher dass kein Monitor jemals selbst killt.

Was als nächstes

Wenn du gerade dabei bist eine Long-Running-Pipeline mit Sub-Agents zu bauen, lies /levels/5/02-ceo-worker-pattern für die Architektur und danach /playbooks/subagent-team-strukturieren für die operative Aufteilung. Wenn du noch keinen Defensive-Hook gegen destruktive Befehle eingerichtet hast, das /playbooks/pretooluse-hook-fuer-destruktive-bash-befehle Playbook ist die natuerliche Ergänzung.

Source

Konkret kalibriert auf Temporal-Worker-Pattern, vergleichbar für LangGraph und Inngest-Pipelines. Doku zu Temporal Workflow Lifecycle: docs.temporal.io/workflows. Anti-Pattern dahinter beschrieben in temporal.io/blog/why-you-shouldnt-terminate-workflows (allgemeines Pattern, kein Replacement für Source-of-Truth-Check).