Veto/docs

CrewAI Integration

Use Veto with CrewAI tools to validate agent actions before execution.

Veto integrates with CrewAI by wrapping BaseTool instances.

You can use either:

  • wrap_crewai_tools(veto, tools) for an explicit integration call, or
  • veto.wrap([...]), which auto-detects CrewAI BaseTool instances and delegates to the CrewAI integration.

Python only — CrewAI is a Python framework.

Installation

pip install veto crewai

Quick start

from crewai.tools import BaseTool
from pydantic import BaseModel, Field
from veto import Veto
from veto.integrations.crewai import wrap_crewai_tools

veto = await Veto.init()

class TransferInput(BaseModel):
    amount: float = Field(description="Amount to transfer")
    to_account: str = Field(description="Destination account")

class TransferFundsTool(BaseTool):
    name: str = "transfer_funds"
    description: str = "Transfer money between accounts"
    args_schema: type[BaseModel] = TransferInput

    def _run(self, amount: float, to_account: str) -> str:
        return f"Transferred ${amount} to {to_account}"

# Wrap tools with Veto validation
tools = [TransferFundsTool()]
safe_tools = wrap_crewai_tools(veto, tools)

# Equivalent auto-detection path:
# safe_tools = veto.wrap(tools)

How it works

For each BaseTool, Veto:

  1. Reads tool.name
  2. Builds an args dict using args_schema.model_fields + runtime args/kwargs
  3. Calls await veto.guard(tool_name, args_dict)
  4. Executes _run() (or _arun() when present) only if allowed
CrewAI calls _run/_arun
       |
       v
  veto.guard(...)
       |
  +----+----+
  |         |
allow     deny
  |         |
  v         v
run tool  ToolCallDeniedError
  • Allowed: _run() / _arun() executes normally
  • Denied: Raises ToolCallDeniedError

Using with Crew

from crewai import Agent, Task, Crew

# Wrap tools before passing to the agent (either API works)
safe_tools = wrap_crewai_tools(veto, [TransferFundsTool()])
# safe_tools = veto.wrap([TransferFundsTool()])

agent = Agent(
    role="Financial Assistant",
    goal="Help users manage their finances safely",
    tools=safe_tools,
)

task = Task(
    description="Transfer $500 to ACC-001",
    agent=agent,
)

crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()

Example output

Tool: transfer_funds (type: TransferFundsTool)
Tool: get_balance (type: GetBalanceTool)

transfer_funds(200) -> Transferred $200 to ACC-001          # allowed
transfer_funds(5000) -> DENIED: Tool call denied:           # blocked by policy
  transfer_funds - Amount 5000 exceeds limit of 1000
get_balance('ACC-001') -> Balance for ACC-001: $5,000       # allowed

total_calls:    3
allowed_calls:  2
denied_calls:   1

Notes

  • CrewAI requires Python < 3.14. If you're using Python 3.14+, use a compatible Python version.
  • The args_schema (Pydantic model) is used by CrewAI for input validation. Veto adds policy-level validation on top.
  • Both _run() and _arun() methods are wrapped when available.