Skip to main content
Ein Adapter für beide. LangGraph läuft auf dem Callback-Manager von langchain-core, daher instrumentiert das Einbinden des einen automatisch auch das andere.

Installation

Für LangChain ohne LangGraph: failproofai-sdk[langchain]. Unterstützt: langchain-core 1.4.7 bis 2.0, langgraph 1.2 bis 2.0. Außerhalb dieses Bereichs wird der Adapter trotzdem installiert und gibt einmalig eine Warnung aus.

Instrumentierung

instrument() registriert einen Tracer über langchain_core.tracers.context.register_configure_hook. LangChain fügt ihn in jeden Callback-Manager ein, den es erstellt – Graphs, Tools und Modelle werden also aufgezeichnet, ohne dass eine Aufrufstelle geändert werden muss, auch nicht in Bibliotheken, die man selbst nicht geschrieben hat.

Was aufgezeichnet wird

Ein Node wird zu einem Hook, nicht zu einem verschachtelten Agent. agent_id ist das primäre Merkmal auf jeder Dashboard-Oberfläche – retrieve, grade_documents und should_continue zu Agents zu befördern würde die Ansicht überladen und die Session nach dem Node benennen, der zufällig als Erstes ausgeführt wurde. Hook-Spans werden gleich dargestellt und bieten dennoch eine knotenspezifische Latenzsicht.
Nodes können beliebig benannt werden. Ein Node-Run wird anhand seiner Form identifiziert – ein Nicht-Blatt-Run mit LangGraphs eigenem Step-Tag – niemals anhand seines Namens.
Einen Node nach dem darin ausgeführten Objekt zu benennen ließ dessen Ereignisse früher verschwinden. Das ist nicht mehr der Fall.

Streaming

.stream() und .astream() erzeugen keine Token-Ereignisse. Sie werden in das abschließende model_response eingefaltet:

Token-Counts bei gestreamten Antworten

Ein separates Thema, das leicht übersehen wird: OpenAI sendet die Nutzung bei einer gestreamten Antwort nur auf Anfrage.
Der Adapter zeichnet auf, was das Framework liefert. Ohne dieses Flag gibt es nichts aufzuzeichnen, und model_response kommt ohne Token-Counts an.

Beispiel

Spans benennen

Standardmäßig übernimmt der Root-Span den eigenen Namen des Graphs. Durch ein Wrapping lässt sich ein selbst gewähltes Label vergeben:
Bei Multi-Agent-Setups werden die Scopes verschachtelt. Jeder Worker wird zu einem Child-Span mit parent_id:
agent_id sollte eine niedrige Kardinalität haben. Rolle oder Node-Name verwenden, niemals eine UUID oder einen run-spezifischen String.

Session steuern

Die Session-ID wird in folgender Reihenfolge aufgelöst, wobei der erste Treffer gewinnt:
  1. instrument("langchain", session_id=...)
  2. config={"metadata": {"failproofai_sdk_session_id": ...}}
  3. Der umschließende failproofai_sdk.session()-Scope
  4. metadata["session_id"], metadata["conversation_id"] oder metadata["thread_id"]
  5. Die Root-Run-ID
Sie wird niemals von Grund auf neu generiert, da eine synthetisierte ID einen Run auf mehrere Sessions aufteilt.

Optionen

capture_content=False für regulierte Daten verwenden. Struktur, Timings, Token-Counts, Tool-Namen und Ergebnisse werden weiterhin aufgezeichnet; Nachrichteninhalte nicht. include_chains gilt nur für verschachtelte Runs. Ein Runnable, das auf der obersten Ebene aufgerufen wird, ist die Root der Session und wird daher zum Agent-Span statt zum Hook-Paar – eine Benennung hier hat keinen Effekt.

Human in the Loop

interrupt() erzeugt vier Ereignisse, und keines der Paare ist redundant:
human_wait bis human_input enthält den Prompt und die Antwort (beides wird bei capture_content=False weggelassen, ebenso wie Retrieval-Dokumentquellen – die Dokumentanzahl bleibt erhalten). agent_pause bis agent_resume ist das einzige Paar, das die Pause-Zeit erfasst; ohne es wird eine zehnminütige menschliche Wartezeit als aktive Agent-Zeit gewertet. Der Root-Span bleibt über die Pause hinweg offen und hält beide Aufrufe in einer Session.

Häufige Probleme

create_react_agent propagiert die Ausnahme. Um dem Modell zu ermöglichen, den Fehler zu sehen und fortzufahren, den Tool-Node explizit aufbauen:
Der Fehler wird in jedem Fall als tool_result mit einem Fehler aufgezeichnet. Das entscheidet nur, ob der Run ihn überlebt.
Ein direktes llm.invoke() außerhalb eines Graphs hat keinen übergeordneten Run und öffnet daher einen Root-Span, in dem das Modellpaar ausgegeben wird. Das Dashboard ordnet Blätter einem offenen Agent zu, daher ist der Span beabsichtigt. Benennen:
Es wurde ein Failproof-Handler in config={"callbacks": [...]} übergeben und zusätzlich instrument() aufgerufen. Den Handler entfernen. Der Configure-Hook deckt bereits jeden Callback-Manager im Prozess ab.
Das ist nicht der Fall. LangGraph löst GraphInterrupt über denselben Pfad wie eine echte Ausnahme aus, weshalb jede Pause den Tracer als Fehler-Callback erreicht. Jede GraphBubbleUp-Unterklasse wird stattdessen als Kontrollfluss behandelt, sodass eine Genehmigung keinen roten Fehler erzeugt.
In dieser Reihenfolge prüfen: instrument() wurde vor der Graph-Ausführung aufgerufen; ein with failproofai_sdk.session(): umschließt den Aufruf; FAILPROOFAI_SDK_STRICT=1 ist gesetzt, sodass ein fehlerhafter Hook eine Ausnahme auslöst statt unterdrückt zu werden.

Weiter

Funktionsweise

Paare, IDs, Session-Lebenszyklus und Zustellung.

Einen Trace lesen

Kausalität durch die gerade aufgezeichnete Session verfolgen.

Andere Frameworks

CrewAI, LlamaIndex, Pydantic AI und benutzerdefinierte Agents.