Skip to main content

LangChain

Install

pip install comply54 langchain-core langgraph langchain-anthropic

Imports

from comply54.langchain import Comply54Guard, comply54_route, compliance_node, comply54_tool

Comply54Guard is a LangGraph node that intercepts every tool call from an AIMessage and blocks it if any compliance pack returns deny. Blocked calls inject a ToolMessage error back to the agent; the agent then explains the refusal to the user.

from comply54.sectors import NigeriaFintechCompliance
from comply54.langchain import Comply54Guard, comply54_route
from langgraph.graph import StateGraph, MessagesState
from langgraph.prebuilt import ToolNode

compliance = NigeriaFintechCompliance()
tools = [your_tool_1, your_tool_2]

guard = Comply54Guard(compliance, tools)

graph = StateGraph(MessagesState)
graph.add_node("agent", agent_node)
graph.add_node("guard", guard)
graph.add_node("tools", ToolNode(tools))

graph.set_entry_point("agent")
graph.add_conditional_edges("agent", comply54_route, {"guard": "guard", "__end__": "__end__"})
graph.add_edge("guard", "tools")
graph.add_edge("tools", "agent")

comply54_route(state) routes to "guard" if the last message has tool calls, or "__end__" otherwise.

The guard reads compliance context from state["compliance_context"] — pass KYC tier, consent flags, etc. as a dict in this state key.

compliance_node(compliance) (legacy pattern)

Returns a LangGraph-compatible state node function for pipelines where compliance is a mandatory explicit step (not tool-call-level):

from comply54.sectors import NigeriaFintechCompliance
from comply54.langchain import compliance_node
from langgraph.graph import StateGraph

compliance = NigeriaFintechCompliance()
node = compliance_node(compliance)

graph = StateGraph(YourState)
graph.add_node("check_compliance", node)

State keys read: state["action"], state["params"], state["output"], state["context"]

State keys written: state["compliance_result"], state["blocked"]

comply54_tool(compliance)

Returns a langchain_core.tools.StructuredTool the LLM can call when compliance checking should be model-driven:

from comply54.langchain import comply54_tool
from langchain_anthropic import ChatAnthropic

compliance = NigeriaFintechCompliance()
tools = [comply54_tool(compliance)]

llm = ChatAnthropic(model="claude-sonnet-4-6").bind_tools(tools)

Full LangGraph example

See the LangChain integration guide for a complete working example with Comply54Guard, conditional routing, and output guards.

API reference

Comply54Guard(compliance: SectorCompliance, tools: list) -> Callable[[MessagesState], MessagesState]
comply54_route(state: MessagesState) -> str # "guard" | "__end__"
compliance_node(compliance: SectorCompliance) -> Callable[[dict], dict]
comply54_tool(compliance: SectorCompliance, name: str = "check_compliance") -> StructuredTool