Governed LangGraph in 3 Minutes
LangGraph’s most popular pattern is a supervisor with workers: the supervisor node routes to a researcher, a coder, or a reviewer based on state, then loops until done. It’s the reference architecture for every serious multi-agent system built on LangChain.
It’s also a delegation chain. Nobody calls it that, but that’s what it is — one agent decides, hands work to another, and expects a result back. The supervisor is accountable for what the workers do.
Which is a problem, because LangGraph gives you zero tools for enforcing that accountability. The workers share credentials with the supervisor. Their tool access is whatever you happened to put in the tools list. Their spend is unbounded. And when something goes wrong, the trace shows which node ran but not what permissions that node actually had at the time.
Agentic Control Plane fixes this at the call layer — so you don’t have to rewrite your graph.
The 3-minute setup
LangGraph’s ChatOpenAI (or ChatAnthropic via the OAI-compatible shim) takes a base_url. Point it at ACP.
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
governed = ChatOpenAI(
base_url="https://api.agenticcontrolplane.com/v1",
api_key=os.environ["ACP_API_KEY"], # gsk_yourslug_xxxxx
model="claude-sonnet-4-6",
)
def supervisor(state):
# The supervisor picks the next worker.
...
return {"next": "researcher"}
def researcher(state):
result = governed.invoke(state["messages"])
return {"messages": state["messages"] + [result]}
graph = StateGraph(State)
graph.add_node("supervisor", supervisor)
graph.add_node("researcher", researcher)
graph.add_node("coder", coder)
graph.add_edge("researcher", "supervisor")
graph.add_edge("coder", "supervisor")
graph.add_conditional_edges("supervisor", lambda s: s["next"])
Every LLM call in every node now flows through ACP. Every MCP tool call the agents make is scoped against the workspace policy. Every spend is metered against the budget.
What changes
Each graph node becomes a delegation hop. Register supervisor/researcher/coder as distinct ACP agent profiles. Give each different scopes and enabledTools. The researcher gets web.* and vector.*. The coder gets github.* and npm.*. The supervisor gets neither — it’s pure routing. If the coder’s LLM gets creative and tries to search the web, ACP rejects it. Scope narrowing is enforced server-side, not by the graph.
Budget is hierarchical, not flat. LangGraph’s token counter is a number in state. ACP’s budget is structural: the supervisor starts with $5.00, the researcher gets a max of $1.00, the coder gets $2.00. When a worker’s budget hits zero, its next call returns BUDGET and the supervisor can decide — retry with a different worker, return partial results, or stop. Runaway loops stop at the worker that started them.
The audit log is a graph, not a list. Every tool call carries delegation.chain and delegation.runChain. Your monitoring dashboard already shows traces — now pipe the NDJSON export into Splunk or Datadog and you can query “show me every tool call made through the coder node last Tuesday, and who the human at the root was.” That’s a question your current LangSmith trace cannot answer.
Mapping LangGraph to ACP
| LangGraph | ACP |
|---|---|
| Graph node | AgentProfile with its own scopes, tools, and budget |
| Supervisor node | canDelegate: true, delegatable: false |
| Worker node | delegatable: true, canDelegate: false |
state["messages"] |
Conversation stays in-graph; tool calls routed through ACP |
tools=[...] |
Registered as ACP-enabled tools; runtime-checked per hop |
| Recursion limit | Enforced at the LLM-budget layer, not just step count |
The supervisor-loops-forever test
The most common LangGraph failure mode: the supervisor can’t decide, routes to the researcher again, researcher returns, supervisor routes to the researcher again. A few thousand tokens later, you notice.
With ACP, two things bound it. First, the researcher’s maxBudgetCents: after $1.00, the next call returns BUDGET and the supervisor has to route somewhere else. Second, the chain’s maxDelegationDepth: if the supervisor somehow triggers a re-entry into itself, ACP’s cycle detection fires with -32003 CYCLE.
Neither is a LangGraph config. Both are structural invariants ACP enforces outside the graph.
What this unlocks
LangGraph is the most popular multi-agent framework in production. ACP is the only governance layer built for multi-agent from day one. Pair them and you can ship supervisor-worker graphs into regulated environments without inventing your own audit plumbing.
Your graph stays a graph. Your governance becomes a chain. They stay out of each other’s way.
Try it: install ACP free · see the PR reviewer demo · delegation chains deep dive
- Governing the Anthropic Agent SDK Apr 2026
- Governed CrewAI in 3 Minutes Apr 2026
- Governance for Claude Code in 60 seconds Apr 2026