Skip to content

LangGraph Integration

ShadowAudit integrates with LangGraph by wrapping tools before they are passed to graph nodes. Enforcement applies at every tool invocation, including within loops and conditional branches.

Installation

pip install "shadowaudit[langchain]"

Wrapping tools for a graph

from shadowaudit import ShadowAuditTool
from langchain.tools import ShellTool
from langgraph.prebuilt import create_react_agent

safe_shell = ShadowAuditTool(
    tool=ShellTool(),
    agent_id="graph-agent",
    capability="shell.execute",
    policy_path="policies/shell.yaml"
)

# Pass wrapped tools to the graph agent
graph = create_react_agent(model, tools=[safe_shell])

Manual graph nodes

When defining graph nodes manually, gate tool calls within the node function:

from shadowaudit.core.gate import Gate
from langgraph.graph import StateGraph

gate = Gate()

def tool_node(state):
    command = state["command"]
    result = gate.evaluate(
        agent_id="graph-agent",
        task_context="shell",
        risk_category="shell_execution",
        capability="shell.execute",
        policy_path="policies/shell.yaml",
        payload={"command": command}
    )
    if not result.passed:
        return {"error": f"Blocked: {result.reason}"}
    # execute tool
    output = run_shell(command)
    return {"output": output}

builder = StateGraph(MyState)
builder.add_node("tool", tool_node)

Multi-agent graphs

In graphs where one agent hands off to another, propagate the agent lineage:

gate.evaluate(
    agent_id="executor-agent",
    task_context="database",
    risk_category="database_write",
    capability="database.write",
    policy_path="policies/database.yaml",
    payload={"query": sql}
)

Use FlowTracer when you need to track data movement across planner and executor agents.