LangGraph Integration (Python)
First-class Thoth governance for LangGraph StateGraph, CompiledStateGraph, and ToolNode patterns.
Why LangGraph Needs Special Handling
LangGraph executes tools through ToolNode and tool objects (.invoke() / .ainvoke()), not only plain Python callables.
Compared to LangChain AgentExecutor, production graphs add:
- Stateful multi-step execution (
StateGraph/ compiled graphs) - Sync + async tool invocation paths
- Parallel branches that require session-safe call history
Thoth's instrument_langgraph() instruments the graph or tools in one call and preserves one session across the full workflow.
Installation
langgraph is optional. If missing, Thoth raises:
API
Accepted inputs:
StateGraph(pre-compile)CompiledStateGraphlistof@tooltools
Return type matches input type.
Pattern A: Instrument a Tool List
Pattern B: Instrument ToolNode Directly
Pattern C: @thoth_graph Decorator
Session Continuity
A single instrument_langgraph() call creates one SessionContext.
All tool calls in that graph execution share:
- one
session_id - one accumulating
session_tool_callshistory
This enables accumulation-style policy logic (for example MOSES risk progression) across multi-step flows.
Sync + Async Handling
Thoth wraps both:
tool.invoke(...)tool.ainvoke(...)
Async calls use async enforcement (acheck) and async step-up polling.
STEP_UP in Graph Execution
When the enforcer returns STEP_UP with a hold_token, Thoth polls /v1/enforce/hold/{hold_token} until resolution.
- Approved: tool executes and graph continues
- Denied/timeout:
ThothPolicyViolationis raised and graph execution stops unless your graph/app handles it
MODIFY Behavior
For MODIFY decisions, Thoth rewrites tool arguments from decision.modified_tool_args, executes with modified args, and emits telemetry with:
original_tool_argsmodified_tool_argsmodification_reason
DEFER Behavior
For DEFER, Thoth does not execute the tool. It raises ThothDeferredError and includes defer metadata (defer_reason, defer_timeout_seconds).
Regulatory Context (HIPAA / Clinical)
Set regulatory context fields directly at instrumentation time:
session_intentpurposedata_classificationtask_context
These are propagated to enforcement payloads and tool telemetry.
Fail-Open vs Fail-Closed
fail_open=False(default): unreachable enforcer returns fail-closed behavior in enforcing modes.fail_open=True: retryable transport/status failures can allow execution.observemode always executes tools and logs warnings when enforcer is unavailable.
Mock Mode
Set THOTH_MOCK_MODE=true to simulate decisions locally without a live enforcer.
Mock behavior:
- tool in scope ->
ALLOW - out-of-scope +
observe->ALLOW - out-of-scope +
step_up/progressive->STEP_UPthen approval - out-of-scope +
block->BLOCK - tool name contains
write|delete|modify|exportwithdata_classification="PHI"->STEP_UP
Compatibility Matrix
Validated in this SDK against:
langgraphprebuiltToolNodeStateGraphandCompiledStateGraph- sync and async tool invocation paths
Migration: Tracer.wrap_tool() -> instrument_langgraph()
Before (manual wiring):
After (one call):