Startseite / Artikel

LangGraph kann kompiliert und erfolgreich ausgeführt werden, wenn ein erforderlicher Knoten übersprungen wird.

LangGraph compile() überprüft die Verkabelung, nicht die Vollständigkeit der Geschäftsabläufe. Ein Graph von Kauf bis Rechnung kann erfolgreich sein, wenn ein Knoten übersprungen wird, daher muss geprüft werden, ob die erforderlichen Schritte ausgeführt wurden.

Verlag: REACTAPP.TOP5 Min. Lesezeit1149 Wörter

Quellen: The Node That Never Ran: What LangGraph Does Not Check at Compile Time

Ein LangGraph-Ablauf von Kauf bis Rechnung kann erfolgreich kompiliert werden, auch wenn ein Knoten übersprungen wird. Dieser Fehlerfall ist schlimmer als ein Absturz: Die Finanzabteilung geht davon aus, dass eine Rechnung existiert, obwohl der Graph den entsprechenden Schritt nie ausgeführt hat. Der Grund liegt in einer Lücke bei dem, was compile() überprüft – sowie in zwei Kontrollmechanismen, die diesen Fehler erkennen sollten.

Die Nachvollziehung

Jeder Knoten gibt seinen Namen aus. Ein einwandfreier Ablauf zeigt alle Stationen an und endet erfolgreich. Entfernt man eine Kante:

graph.add_edge("create_purchase_order_from_request", "create_an_invoice")

Wird der Ablauf erneut ausgeführt:

Executing: load_purchase_request
Executing: validate_purchase_request_is_approved
Executing: create_purchase_order_from_request

Die Ausführung stoppt nach der Erstellung der Bestellbestätigung. Die Rechnungszeile erscheint nie. Der Endzustand bleibt bei einem Zwischenwert. Es tritt keine Ausnahme auf. Die Aufrufer erhalten einen normalen Rückgabewert, der nicht auf das fehlende Finanzdokument hinweist.

Was compile() tatsächlich überprüft

StateGraph.compile() überprüft, ob die Kanten auf echte Knoten verweisen, ob START vorhanden ist und ob die Zielkanten Knoten oder END sind. Es beweist jedoch nicht, dass jeder Knoten erreichbar ist, dass jeder Knoten END erreichen kann oder dass jeder Knoten ausgeführt wird. Anleitungen, die behaupten, Erreichbarkeitsprüfungen durchzuführen, überschätzen die Funktionalitäten der API.

Ein Mangel, zwei Fehlermöglichkeiten

  1. Waisenknoten – registriert, aber ohne ein ankommendes Kante; wird niemals ausgeführt; die Kompilierung ist dennoch erfolgreich.
  2. Unterbrochener Pfad zu END – das Löschen einer Kante mitten im Graphen führt zu einem stillschweigenden, teilweisen Erfolg mit einem nicht-endgültigen Status.

Sowohl Fälle als auch Situationen erscheinen als „grüne“ Kompilierungen.

Warum der Motor Erfolg meldet

LangGraph betrachtet einen Ablauf als abgeschlossen, wenn er ein Knoten erreicht, von dem keine Ausgangskanten ausgehen – oder ohne Fehler zurückkehrt. Erfolg bedeutet „der Laufzeitumgebung ist kein Absturz aufgetreten“, nicht „jedes geschäftliche Meilenstein wurde erreicht“. Statusfelder sind Anwendungskonventionen, es sei denn, sie werden vorgeschrieben.

Warum END nicht speziell genug ist

END ist ein Endmarker für Kanten, bei denen dies aktiviert wurde. Knoten, die einfach aufhören, führen nicht automatisch zu einem Fehler beim Aufruf. Ohne Überprüfungen der erforderlichen Meilensteine erscheinen teilweise erstellte Graphen gesund.

Warum das Framework diese Entscheidung trifft

Erreichbarkeits- und Pflichtknotenanalyse sind Probleme der Programmlogik. Die Bibliothek überprüft die strukturelle Verkabelung und lässt anschließend den Produktcode bestimmen, welche Knoten erforderlich sind. Dadurch bleibt die Kompilierung schnell und es werden keine vorgefertigten Geschäftsregeln eingeführt – die Verantwortung wird jedoch auf Tests verlagert.

Wie man das feststellt

Fügen Sie eine explizite Nach-Ausführungs-Prüfung (oder auf Graphenebene) hinzu, die überprüft, ob die erforderlichen Knoten ausgeführt wurden – mithilfe von Zählern im Zustand, Callback-Hooks oder einem Abschlussprädikat:

def find_detached_nodes(compiled):
    g = compiled.get_graph()
    sources = {e.source for e in g.edges}
    targets = {e.target for e in g.edges}
    dead_ends = [n for n in g.nodes if n not in sources and n != "__end__"]
    orphans  = [n for n in g.nodes if n not in targets and n != "__start__"]
    return dead_ends, orphans

Fügen Sie außerdem Unit-Tests hinzu, die bewusst Kanten löschen und erwarten, dass der Schutzmechanismus fehlschlägt. Optional können statische Prüfungen die Adjazenzliste durchlaufen, um die Erreichbarkeit von START bis zu jedem erforderlichen Knoten und weiter bis zu END zu überprüfen.

Zusammenfassung

  • compile() bedeutet nicht notwendigerweise vollständige Geschäftsabwicklung.
  • Für Finanzworkflows sollten lieber Abstürze oder eindeutige Fehlermeldungen statt stummer Übersprünge verwendet werden.
  • Codieren Sie die erforderlichen Meilensteine im Zustand und überprüfen Sie diese, bevor Sie Erfolg an die übergeordneten Systeme melden.
  • Dokumentieren Sie die Lücken für jeden Ingenieur, der ein lineares Tutorial in die Produktionsumgebung für Geldtransfers übernimmt.

Zuordnung des Fehlers zum Geldtransfer

Von der Bestellung bis zur Rechnung gibt es keinen Spielraum für Fehler. Wenn create_invoice niemals ausgeführt wird, weichen die Zahlungsabwicklungsysteme, Steuerexporte sowie die Lieferantenportale voneinander ab. Die Rückgabe von success zusammen mit status=purchase_order_created ist ein typisches Manko solcher Anwendungen: Die übergeordneten Dienste interpretieren fehlerfreie Rückgabewerte als Abschluss der Aufgabe. Man sollte den HTTP-/Job-Status mit einer Checkliste der erforderlichen Knotenfingerabdrücke abgleichen, die im Zustandsobjekt gespeichert sind.

Ein minimales Vertragsmodell für erforderliche Knoten

Bewahren Sie state["executed"] als Set-Reducer auf. Jeder Knoten fügt seinen Namen hinzu. Vor dem Ende (oder vom Aufrufer nach dem Aufruf) muss geprüft werden, ob {"load","validate","create_po","create_invoice"} <= executed gilt. Fehlende Namen lösen einen speziellen IncompleteGraphError aus, auf den das Überwachungssystem reagieren kann. Dadurch wird der bisher tolerante Erfolgsfall des Frameworks in einen klaren Fehler im Anwendungsbereich umgewandelt.

Statische Nachbarschaftsprüfungen in CI

Serialisieren Sie die Kantenliste des Graphen in den Tests. Berechnen Sie die Erreichbarkeit von START aus. Der CI-Fehler tritt auf, wenn ein erforderlicher Knoten nicht erreichbar ist oder END nicht erreichen kann. Diese Tests erkennen kommentierte Kanten bereits am selben Nachmittag, an dem sie eingeführt werden – ohne auf ein stillschweigendes Überspringen in der Produktion warten zu müssen.

Was „kompiliert“ in Runbooks bedeuten sollte

Dokumentieren Sie für das Team: „Kompiliert“ bedeutet, dass die Verbindungen syntaktisch korrekt sind. „Vollständig“ bedeutet, dass die erforderlichen Geschäftsprozessknoten ausgeführt wurden. Eine Einarbeitung, die diese beiden Begriffe verwechselt, führt erneut zum Vorfall mit den übersprungenen Rechnungen. Verknüpfen Sie die Dokumentation mit einem Reproduktionsbeispiel, damit neue Mitarbeiter absichtlich einen einfachen Graphen stören und sehen können, wie die Schutzmechanismen aktiviert werden.

Verwandte Fallstricke

  • Bedingte Kanten, die an kein Ziel weiterleiten können, wenn ein Zustandsflag nicht gesetzt ist.
  • Wiederholte Aufrufe von invoke ohne Beseitigung teilweiser Nebeneffekte, wodurch doppelte POs erstellt werden, während die Rechnungen weiterhin übersprungen werden.
  • Ausnahmeloser Verlass auf LangSmith-Screenshots anstelle von maschinell überprüfbaren Aussagen in CI.
  • Betrachten Sie die Graphentopologie als Produktionsdaten. Überprüfen Sie sie wie Schemata – nicht wie optionale Kommentare.

    Durchsicht eines funktionierenden versus eines fehlerhaften Aufrufs

    In einem funktionierenden Graphen zeigen Callbacks oder Ausgabeanweisungen die Abfolge Load → Validierung → Erstellung der PO → Erstellung der Rechnung → Abschlussmarke. Operator, die die Logs mit einem Runbook vergleichen, können jede Station abhaken. Nach dem Löschen einer Kante erscheint die Rechnungsmarke nie, dennoch erhält der Python-Aufrufer weiterhin ein Dict. Nachgeschaltete Systeme, die nur den Transporterfolg überprüfen, geben „done“ in ein Fallverwaltungstool ein. So werden stille Übersprünge zu finanziellen Problemen.

    Entwurf von Status-Enums, die nicht lügen können

    Es werden Terminalzustände bevorzugt, die nur durch einen speziellen Abschlussknoten nach Bestehen der erforderlichen Prüfung gesetzt werden: completed, failed_incomplete, failed_exception. Für eine strömende Benutzeroberfläche können Zwischenzustände existieren, doch APIs, die Arbeit an andere Dienste melden, sollten nach der Überprüfung ausschließlich completed ausgeben. Übersetzen Sie failed_incomplete in ein Ausgleichsticket um, das die fehlenden Knotennamen auflistet.

    Wechselwirkung mit Checkpointern

    Falls Checkpointer einen Lauf nach einem Absturz wieder aufnehmen, führt ein fehlender Kante weiterhin zum Überspringen. Die Persistenz erzeugt keine Kanten. Wiederholte Tests sollten Topologiemutationen beinhalten. Ebenso sollte die Graphendefinition zusammen mit den Checkpoint-Daten versioniert werden, damit alte Checkpoints auf einer inkompatiblen Topologie ohne Migrationslogik nicht erneut ausgeführt werden.

    Die Lücke ohne Angst vermitteln

    Ingenieure, die aus Sprachen mit dem Prinzip „Kompilieren bedeutet Korrektheit“ kommen, benötigen eine gezielte Demonstration: Sie brechen in einer Sandbox einen Grenzfall aus, beobachten den Erfolg, aktivieren anschließend die Schutzmaßnahme und sehen den Misserfolg. Eine Live-Demonstration verhindert monatelanges Vertrauen in die vermeintliche Sicherheit. Fügen Sie diesen Demo-Script neben das README des Repositories für den Prozess von Kauf bis Rechnung hinzu.

    Checkliste, bevor ein Graph als „fertig“ bezeichnet wird

    1. Jeder erforderliche Geschäftsnode erscheint in executed.
    2. Bedingte Router verfügen über ausführliche Verzweigungen, einschließlich eines expliziten Fehlerwegs.
    3. Kein Node führt irreversible Eingabe/Ausgabe-Aktionen durch, ohne dass ein Idempotenzschlüssel im Zustand gespeichert ist.
    4. Die Kompilierung ist erfolgreich und die Erreichbarkeitstests im CI sind erfolgreich.
    5. Die Aufrufergebnisse enthalten ein maschinenlesbares Abschlussflag, das von HTTP 200 getrennt ist.

    Sobald diese fünf Bedingungen erfüllt sind, werden übersprangene Rechnungen zu erkennbaren Fehlern anstelle stiller Erfolge. Das ist der betriebliche Standard, den LangGraph-Anwendungen benötigen, wenn Geld oder Konformität auf dem Spiel stehen – und nicht nur ein grünes Kompilierungsprotokoll.