Skip to content

LangGraph / LangChain

pip install "guardlayer[langgraph]"

from guardlayer import GuardLayer
from guardlayer.integrations.langgraph import guard_tools
from langgraph.prebuilt import create_react_agent

guard = GuardLayer()
tools = guard_tools(guard, [search, fetch_url, run_shell])     # drop-in for ToolNode / create_react_agent
agent = create_react_agent(model, tools, checkpointer=checkpointer)

What the guarded tools do:

Situation Behaviour
Call blocked The model receives a refusal it can read and reason about; the tool doesn't run.
Call needs review The graph pauses with LangGraph's interrupt(). Resume with Command(resume=True) to approve; anything else refuses.
Result contains an injection The result is withheld; the model gets a notice to treat that source as untrusted.
Result contains a secret It's redacted before the model sees it.

The graph's thread_id becomes the GuardLayer session, so taint follows the conversation. Override it with session= (a string, a GuardSession or a callable).

from langgraph.types import Command

config = {"configurable": {"thread_id": "user-42"}}
state = agent.invoke({"messages": [("user", "clean up the repo")]}, config)
if state.get("__interrupt__"):                  # GuardLayer asked for approval
    print(state["__interrupt__"][0].value)     # what the tool wants to do, and why it needs review
    agent.invoke(Command(resume=True), config)  # approve (or resume with False to refuse)

Options: on_review="deny" refuses review-level calls instead of pausing (for unattended graphs), and withhold_at="flag" withholds results at a lower threshold.

Interrupts need a checkpointer. Graph state must be JSON-serializable; GuardLayer's interrupt payload is.