By MAREF Engineering
If you're building production agents in 2026, there's a good chance they're a LangGraph state graph. Nodes, edges, conditional routing — elegant, testable, and — until you add a governance layer — completely unsupervised. This guide shows the two ways to govern a LangGraph app with MAREF, and it's honest about which is ready today.
TL;DR: the protocol-level path (MCP + A2A) is live and tested; the native LangGraphAdapter
documented in the quickstart is on the roadmap, with the AutoGen sidecar adapter already shipped.
The honest status, first #
MAREF's quickstart documents a sidecar.adapters.langgraph.LangGraphAdapter
with three methods — evaluate_node_safety
, observe_transition
, and inject_governance
. We want to be direct with you: that adapter is specified but not yet merged. The AutoGen adapter (sidecar.adapters.autogen.AutoGenAdapter
) is live; LangGraph's native adapter is being built to the same contract.
What that means for you: you should not block on the adapter. The protocol-level integration below uses only shipped, tested code paths and gives you the same governance guarantees today.
Path 1 — Govern tool calls inside a LangGraph node (MCP) #
LangGraph nodes call tools. Those tools are where the blast radius lives. Wrap them with MCPBridge
and every call from any node goes through the security gate — with the same event stream you can feed your audit log:
from langgraph.graph import StateGraph
from maref.integration.mcp_client import MCPClient, MCPServerConfig
from maref.integration.mcp_bridge import MCPBridge
client = MCPClient()
conn = client.register_server(MCPServerConfig(
command=["npx", "-y", "@your/tool-server"],
transport_type="stdio",
server_name="tool-server",
))
bridge = MCPBridge(client) # wraps calls in the security gate
def tool_node(state):
return bridge.invoke_tool(
conn,
tool_name=state["tool"],
args=state["args"],
)
graph = StateGraph(dict)
graph.add_node("tools", tool_node)
graph.add_edge("__start__", "tools")
A DENY verdict returns {"error": "Tool blocked by security gate", ...}
— the external server is never called, and the node's __error__
edge or fallback logic can route around it. Your LangGraph topology stays exactly as designed; MAREF just sits at every tool boundary.
Path 2 — Govern whole tasks across agents (A2A) #
For multi-agent LangGraph deployments — several graphs, maybe a supervisor — the A2ABridge
makes MAREF itself an A2A-governed agent that creates, delegates, and halts tasks across the federation:
from maref_lite.state_machine import GovernanceStateMachine
from maref.governance.audit import AuditLogger
from maref.integration.a2a_bridge import A2ABridge
bridge = A2ABridge(
state_machine=GovernanceStateMachine(),
audit_logger=AuditLogger(log_path="maref-audit.jsonl"),
agent_name="langgraph-supervisor",
)
task_id = bridge.create_task("Summarize Q3 report") # governed lifecycle
bridge.delegate_task(task_id, "https://other-agent.local:8000")
bridge.force_halt_task(task_id, reason="scope change")
Every create_task
, delegation, and state change is HMAC-signed into the audit log and runs through the same governance state machine — OBSERVE → ANALYZE → EVALUATE → DECIDE → ACT → VERIFY → STABILIZE → REPORT
, with HALT
reachable by any authorized human or the circuit breaker.
The result: your LangGraph graphs keep their orchestration logic, while MAREF owns the "is this safe?" decision at every boundary — tool calls, inter-agent handoffs, and task lifecycle.
Which path should you pick? #
Single graph, several tools→ Path 1 (MCP bridge on tool calls). Minimal change, immediate audit trail.** Multiple graphs / supervisor pattern→ Path 2 (A2A). You get task lifecycle governance, delegation, and a kill-switch across the whole fleet. Both**→ They compose. MAREF governs tool callsandtask orchestration simultaneously — that's the 8-layer architecture working as designed.
*🛡️ Sources: MAREF source — src/maref/integration/mcp_bridge.py (MCPBridge.invoke_tool), src/maref/integration/a2a_bridge.py (A2ABridge.create_task / delegate_task / force_halt_task), src/sidecar/adapters/autogen.py (shipped sidecar adapter). LangGraph adapter contract defined in docs/quickstart.md §3.3 (roadmap — AutoGen adapter shipped). *