LangGraph

Add Fuze protection to a LangGraph project by wrapping tools registered with ToolNode, names, descriptions, and types are preserved.

Installation

bash
pip install fuze-ai langgraph

Usage

python
from fuze_ai.adapters.langgraph import fuze_tools
from langgraph.prebuilt import ToolNode

# Your existing tools
tools = [search_tool, calculator_tool, email_tool]

# Wrap all tools with Fuze protection
guarded_tools = fuze_tools(tools, config={
    "max_cost_per_step": 0.50,
    "max_iterations": 25,
})

# Use in your graph as normal
tool_node = ToolNode(guarded_tools)

What it does

fuze_tools() wraps each tool's _run method with @guard, preserving the tool name, description, and input/output types, while adding loop detection, budget tracking, and audit logging.

Marking side-effects

python
guarded_tools = fuze_tools(tools, side_effects={
    "send_email": cancel_email,
    "create_record": delete_record,
})

Per-tool configuration

python
guarded_tools = fuze_tools(tools, per_tool={
    "search": {"max_cost": 0.10},
    "send_email": {"side_effect": True, "max_retries": 1},
})

Full example

python
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode
from fuze_ai.adapters.langgraph import fuze_tools

tools = [search, calculator, send_email]
guarded = fuze_tools(tools, side_effects={"send_email": recall_email})

graph = StateGraph(MessagesState)
graph.add_node("tools", ToolNode(guarded))
# ... rest of graph setup

result = graph.compile().invoke({"messages": [("user", "find recent revenue")]})

Expected output (from fuze-traces.jsonl after the run):

jsonl
{"event":"step.start","tool":"search","run_id":"run_..."}
{"event":"step.end","tool":"search","cost":0.012,"tokens_in":18,"tokens_out":94}
{"event":"step.start","tool":"calculator","run_id":"run_..."}
{"event":"step.end","tool":"calculator","cost":0.0,"tokens_in":0,"tokens_out":0}