Skip to content
Agentic Control Plane

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-crewai package, 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.delete from any crew)
  • Agent policies — per-role rules (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 entire Agent’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 Memory writes or ShortTermMemory.

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.