Govern CrewAI with Agentic Control Plane
CrewAI is multi-agent by design — researchers hand off to writers hand off to editors. That’s exactly the shape ACP’s delegation chain primitives were built for: scope narrowing at every hop, budget propagation, full audit chain rooted in the human who started the run.
Two integration paths today:
- Path 2 (OAI-compatible proxy) — works now, no SDK install
- Path 3 (native Python adapter) —
acp-governance-crewaipackage, scaffolded
TL;DR — Path 2 (works today)
CrewAI uses LangChain’s ChatOpenAI under the hood. Point its base_url at ACP and every LLM call (and the tool calls they emit) flow through the governance pipeline:
from crewai import Agent, Crew, Task
from langchain_openai import ChatOpenAI
import os
governed_llm = ChatOpenAI(
base_url="https://api.agenticcontrolplane.com/v1",
api_key=os.environ["ACP_API_KEY"], # gsk_yourslug_xxxxxxxx
model="claude-sonnet-4-6",
)
researcher = Agent(
role="Market researcher",
goal="Summarize moves in the MCP gateway space",
tools=[web_search, hn_search],
llm=governed_llm,
)
writer = Agent(
role="Writer",
goal="Turn research into a 400-word brief",
tools=[],
llm=governed_llm,
)
Crew(agents=[researcher, writer], tasks=[...]).kickoff()
Every call shows up in the ACP dashboard activity log. To see crew members as distinct rows on the Agents page, opt in to per-member metadata via the Path 3 adapter (below).
TL;DR — Path 3 (full A2A attribution)
The native Python SDK ships as acp-governance-crewai. Install once, add a decorator per crew member:
from acp_governance_crewai import govern, agent_name
researcher = Agent(
role="researcher",
llm=governed_llm,
tools=[
govern(web_search, agent_name="researcher"),
govern(hn_search, agent_name="researcher"),
],
)
Each agent_name becomes a distinct row in the dashboard’s Detected Agents table. Handoffs between crew members register as delegation chain links — researcher → writer is a real chain you can audit and apply policy to.
Status: The Python adapter package is scaffolded but not yet on PyPI. Use Path 2 today for full traffic governance; install the adapter when published for full A2A attribution.
How it works
| Layer | What ACP sees | What ACP can do |
|---|---|---|
| Path 2 (OAI proxy) | Every LLM call from CrewAI | Govern the LLM call itself; tool calls passed through the model’s tool_use blocks are audited |
| Path 3 (SDK adapter) | LLM calls + every individual tool invocation + crew handoffs | Per-tool policy enforcement, per-crew-member scope caps, delegation chain assembly with proper parentAgent and agent_name |
The OAI proxy is universal but lossy — it sees the conversation but can’t perfectly reconstruct CrewAI’s internal handoff semantics. The SDK adapter is precise — it maps CrewAI’s native multi-agent primitives onto ACP’s delegation chain model.
Mapping CrewAI to ACP
| CrewAI concept | ACP primitive |
|---|---|
Agent(role=...) |
agent_name field on tool/LLM call records |
Agent.tools |
Per-agent tool allowlist (intersected with chain) |
| Crew composition | canDelegate: true on orchestrator profiles |
crew.kickoff() |
Root of the delegation chain (originSub = the human who triggered) |
| Tool invocation | Governed via MCP with the seven-layer pipeline |
What you’ll see in the dashboard
cloud.agenticcontrolplane.com/agents shows your CrewAI traffic with each role as a distinct entry once Path 3 is wired. The Activity log shows individual tool calls; the Run Details panel renders the delegation chain when crew handoffs are detected.
Setting up policy
Three policy axes apply naturally to CrewAI:
- Tool policies — workspace-wide tool allowlist (e.g., no
github.repos.deletefrom any crew) - Agent policies — per-
rolerules (researcher gets web tools only; writer gets nothing; reviewer gets PR-comment scope) - User policies — gate which humans can trigger crews that touch sensitive data
Limitations
- Path 2 cannot enforce per-crew-member tool restrictions natively. The OAI proxy sees CrewAI’s outgoing model calls but doesn’t know which crew member made which one without the SDK adapter telling it. Wait for Path 3 if you need per-member enforcement.
- Path 3 adapter is pre-release. Functional but not on PyPI as of writing. Star the repo for release notification, or pin the dev version directly.
- CrewAI’s Tools class wrapping requires the
govern()decorator on each tool individually. No way to wrap an entireAgent’s tools en masse without a small loop. - Async tool support is partial. CrewAI 0.50+ added async tool definitions; the adapter currently wraps sync tools only. Async support tracked in the SDK roadmap.
- Memory and shared-state plumbing is out of scope for ACP. ACP governs tool calls and LLM calls; it doesn’t intercept CrewAI’s
Memorywrites orShortTermMemory.
Troubleshooting
Crew runs but nothing appears in the dashboard. Confirm ACP_API_KEY starts with gsk_ and matches your workspace slug. Check the Activity log filter — workspace dropdown in top-right.
Tool calls show but crew member name doesn’t. Path 2 doesn’t carry crew member metadata. Install the Path 3 adapter for per-member attribution.
Rate limits firing on crew runs. Free Cloud has a $1/day LLM budget per user — an active crew can hit this fast. Check Usage Limits in the dashboard.
401 Unauthorized from the OAI proxy. ACP_API_KEY is missing, malformed, or revoked. Check the Dashboard → API Keys page.
Related integrations
- LangGraph — supervisor/worker pattern, same A2A model
- Anthropic Agent SDK — Skills as agents, native delegation
- OpenAI Agents SDK — handoffs as delegation
- Agent-to-Agent governance — the delegation chain spec
- Blog: Governed CrewAI in 3 Minutes