LangGraph and LangChain agents
Record a tool call as a CommitLayer action before the tool runs, then gate the graph on the verdict.
Record a tool call as a CommitLayer action before the tool runs, then gate the graph on the verdict.
pip install 'commitlayer-integrations[langgraph]'
export COMMITLAYER_API_KEY=spk_... # a recorder key: records actions, reads verdicts, nothing else
Record every mapped tool call
from commitlayer import Client
from commitlayer_integrations.tools import ToolRecorder
from commitlayer_langgraph import record_tool_calls
from langgraph.prebuilt import ToolNode
MAPPING = {
"refund_payment": {
"contract_id": "refund_workflow",
"action_type": "refund_order",
"subject": "arguments.order_id",
"subject_kind": "order",
"params": {"amount": "arguments.amount", "currency": "arguments.currency"},
"action_id": "refund:{arguments.order_id}",
}
}
recorder = ToolRecorder(Client(agent_id="support-bot"), MAPPING)
tools = ToolNode([refund_payment, close_ticket], wrap_tool_call=record_tool_calls(recorder))
With LangChain v1 agents the same function is middleware:
from langchain.agents import create_agent
from langchain.agents.middleware import wrap_tool_call
agent = create_agent(model, tools=[refund_payment, close_ticket], middleware=[wrap_tool_call(record_tool_calls(recorder))])
The wrapper reads the tool's name, arguments and call id from the ToolCallRequest, posts the mapped ones to
POST /v1/actions, and hands the request to the framework's handler unchanged. The tool's result is never
sent. Recording is fail-open: if the API cannot be reached the tool still runs and a warning is logged.
Gate the graph on the verdict
from commitlayer_langgraph import verdict_gate_node
graph.add_node("verify", verdict_gate_node(recorder, timeout=300))
graph.add_conditional_edges("verify", lambda s: s["commitlayer_verdict"]["policy"], {"PASS": "notify_customer", "FAIL": "recover", "UNKNOWN": "recover"})
The node waits for the last recorded action (or the one named in state["commitlayer_action_id"]) to settle
and writes {status, outcome, policy, headline, verification} into the state. A timeout is status: "pending"
and is the graph's decision, never a success.
The mapping format, paths and templates are documented in commitlayer_integrations.tools.