interrupt() is not a policy.
Without a separate authority layer, you hardcode pauses or trust the model.
Add a deterministic ALLOW / REQUIRE_CONFIRM / BLOCK outcome to your human-in-the-loop workflows.
Building Human-in-the-Loop workflows in LangGraph usually means hardcoding nodes to pause execution, or relying on the model to "ask for permission" before doing something dangerous.
Interrupting at fixed nodes causes fatigue. Every action requires human eyes, regardless of relative risk.
Prompting the model to ask the user creates risk. If the model bypasses the prompt, execution happens.
Resuming the graph state doesn't generate durable receipts of who approved what action at what specific time.
The node executes automatically. No graph interruption needed. Record generated.
KiLu signals the graph to interrupt(). Execution pauses for explicit human review.
Fails fast without user fatigue. Policy violation recorded as evidence.
Keep your graph focused on agent logic. Let KiLu handle authorization.
# before — hardcoding interruptions workflow.add_node("sensitive_tool", sensitive_tool_node) workflow.add_edge("agent", "sensitive_tool") workflow.compile(interrupt_before=["sensitive_tool"]) # after — KiLu decides if interrupt() is needed def safe_tool_node(state): decision = kilu.check_intent(action="tool.execute") if decision.outcome == "REQUIRE_CONFIRM": interrupt("Approval needed") elif decision.outcome == "BLOCK": raise PolicyViolation() return run_tool()
| Approach | What it does | What it misses |
|---|---|---|
| interrupt_before | Pauses at specific nodes | Rigid. Pauses even for safe args |
| Prompt routing | Model calls "ask_user" tool | Not authoritative. Model can bypass |
| Custom IF/ELSE logic | Evaluates state dynamically | Messy graph, hard to audit |
| KiLu integration | Decides based on external policy | Clean graph, durable receipts |