Skip to content
← plyra.ai

CrewAI Integration

Plyra Guard wraps CrewAI @tool definitions. Blocked actions surface as ActionGuardExecutionError, which CrewAI's task loop handles natively.

Basic Usage

from crewai_tools import tool
from plyra_guard import ActionGuard

guard = ActionGuard()

@tool("Read File")
def read_file(path: str) -> str:
    """Read a file and return its contents."""
    with open(path) as f:
        return f.read()

@tool("Write File")
def write_file(path: str, content: str) -> str:
    """Write content to a file."""
    with open(path, "w") as f:
        f.write(content)
    return f"Written to {path}"

# Wrap tools
safe_tools = guard.wrap([read_file, write_file])

# Use with CrewAI agents
from crewai import Agent, Task, Crew

analyst = Agent(
    role="Data Analyst",
    goal="Analyse reports and write summaries",
    tools=safe_tools,
    verbose=True,
)

What Happens on a Block

When a blocked tool is called, Plyra Guard raises ActionGuardExecutionError. CrewAI's internal task retry logic catches this and surfaces it as a task failure with the block reason included.

The agent's verbose output will show:

Action: Write File
Action Input: {"path": "/etc/config", "content": "..."}
Observation: [BLOCKED] System config is off-limits (rule: protect-system)

Custom Policy

from plyra_guard import Policy, Rule

policy = Policy(rules=[
    Rule(pattern=r"^/etc/",    action="block", reason="System config is off-limits"),
    Rule(pattern=r"\.env$",    action="block", reason="No .env access"),
    Rule(pattern=r"^/tmp/",    action="allow"),
    Rule(pattern=r"^/reports/",action="allow"),
])

guard = ActionGuard(policy=policy)
safe_tools = guard.wrap([read_file, write_file])

Multi-Agent Crew

Share one guard across all agents for unified audit logging:

guard = ActionGuard(policy=policy)

researcher_tools = guard.wrap([search_web, read_file])
writer_tools     = guard.wrap([write_file, format_report])

researcher = Agent(role="Researcher", tools=researcher_tools, ...)
writer     = Agent(role="Writer",     tools=writer_tools, ...)

crew = Crew(agents=[researcher, writer], tasks=[...])
crew.kickoff()

# After — see what both agents did
for action in guard.history():
    print(f"{action.agent_hint} | {action.tool_name} | {action.outcome}")

Tips

Tool descriptions matter

Plyra Guard uses the tool name + arguments to build the intent string. Clear tool names (e.g. "Delete File" not "df") make policy rules easier to write and audit logs easier to read.

Test your policy before running a crew

Use guard.evaluate(intent) to dry-run your policy against expected tool calls before starting a long crew job.