CrewAI Integration
Enforce Control Zero policies across multi-agent CrewAI crews and tasks.
Overview
CrewAI orchestrates multiple AI agents working together on complex tasks. Control Zero integrates with CrewAI through step callbacks and tool wrappers, giving you policy enforcement over which tools each agent can use, which models they can call, and what actions they can take.
Installation
pip install controlzero crewai crewai-tools
Setup
Step Callback Approach
The simplest integration uses the built-in create_step_callback() from the SDK:
import controlzero
from controlzero.integrations.crewai import create_step_callback
from crewai import Agent, Task, Crew
cz = controlzero.init()
callback = create_step_callback(cz, agent_id="docs-crew")
# Create agents with policy enforcement
researcher = Agent(
role="Senior Researcher",
goal="Find and summarize relevant information",
backstory="Expert research analyst",
)
crew = Crew(
agents=[researcher],
tasks=[...],
step_callback=callback,
)
The callback enforces both agent.step (with the agent role as resource) and tool.call (with the tool name as resource) at every step.
Tool Wrapper Approach
Wrap individual CrewAI tools with policy enforcement:
import controlzero
from crewai_tools import SerperDevTool, FileReadTool
cz = controlzero.ControlZero()
cz.initialize()
def enforced_tool(tool, agent_id: str = ""):
"""Wrap a CrewAI tool with Control Zero policy enforcement."""
original_run = tool._run
def wrapped_run(*args, **kwargs):
cz.enforce(
action="tool.call",
resource=f"tool/{tool.name}",
context={"agent_id": agent_id},
)
return original_run(*args, **kwargs)
tool._run = wrapped_run
return tool
# Wrap tools with enforcement
search_tool = enforced_tool(SerperDevTool(), agent_id="researcher")
file_tool = enforced_tool(FileReadTool(), agent_id="researcher")
Full Example: Document Analysis Crew
import controlzero
from crewai import Agent, Task, Crew, Process
# -- Control Zero --
cz = controlzero.ControlZero()
cz.initialize()
def enforce_step(step_output):
"""Policy enforcement callback for all agent steps."""
if hasattr(step_output, "tool") and step_output.tool:
cz.enforce(
action="tool.call",
resource=f"tool/{step_output.tool}",
context={"agent_id": str(step_output.agent)},
)
# -- Agents --
researcher = Agent(
role="Document Researcher",
goal="Analyze documents and extract key findings",
backstory="Expert at reading and summarizing technical documents",
step_callback=enforce_step,
verbose=True,
)
writer = Agent(
role="Report Writer",
goal="Write clear, concise reports based on research findings",
backstory="Professional technical writer",
step_callback=enforce_step,
verbose=True,
)
# -- Tasks --
research_task = Task(
description="Analyze the quarterly sales report and extract key metrics",
expected_output="A list of key findings with supporting data",
agent=researcher,
)
writing_task = Task(
description="Write an executive summary based on the research findings",
expected_output="A one-page executive summary",
agent=writer,
)
# -- Crew --
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
verbose=True,
)
# Run with policy enforcement active
try:
result = crew.kickoff()
print(result)
except controlzero.PolicyDeniedError as e:
print(f"Crew blocked by policy: {e.message}")
Example Policy
Allow the researcher to use search tools but deny file writes. Allow the writer to use text tools but deny web access:
{
"name": "document-crew-policy",
"rules": [
{
"effect": "allow",
"action": "llm.generate",
"resource": "model/*"
},
{
"effect": "allow",
"action": "tool.call",
"resource": "tool/search_web"
},
{
"effect": "allow",
"action": "tool.call",
"resource": "tool/read_file"
},
{
"effect": "deny",
"action": "tool.call",
"resource": "tool/write_file"
},
{
"effect": "deny",
"action": "tool.call",
"resource": "tool/execute_code"
}
]
}
Per-Agent Policies
Control Zero supports context-based policy conditions. Use the agent_id in your context to apply different rules to different agents in the same crew:
# The researcher gets broader tool access
cz.enforce(
action="tool.call",
resource="tool/search_web",
context={"agent_id": "researcher"}, # allowed
)
# The writer is restricted
cz.enforce(
action="tool.call",
resource="tool/search_web",
context={"agent_id": "writer"}, # denied by policy
)
Next Steps
- See the Automated Documentation Guide for a full CrewAI demo application.
- Learn about LangChain integration for single-agent workflows.
- Review the Python SDK for the full API reference.