What is @before_tool_call_crew?
Tool calls are the highest-risk surface area for autonomous agents: they touch production databases, send email, and mutate external state. @before_tool_call_crew gives you a ToolCallHookContext with the tool name, serialized arguments, and agent metadata so you can deny calls, rewrite parameters (for example forcing sandbox hosts), or emit structured audit events before execution begins.
Return False to veto the call entirely — the agent should receive a refusal without invoking the tool. Return None to continue. Avoid truthy values like True thinking they mean allow; CrewAI documents None as the pass-through signal. Pair with @after_tool_call_crew to redact outputs or trim large payloads once results return.
Remember hooks are global within the interpreter: FastAPI apps sharing workers need per-request scoping discipline, and pytest suites should clear hooks between tests to prevent ordering flakes.
When to Use
Approval gates on side-effecting tools, audit logging.
Use Cases
- • Approval gates
- • Audit logging
- • Rate limiting
Key Features
- ✓ Crew-scoped
- ✓ Can block calls
- ✓ Receives full args
When NOT to Use
In-tool validation — do it inside _run().
Notes
False versus None
Only False vetoes the call. Accidentally returning strings or booleans can produce confusing runtime behavior — stick to None or False explicitly.
Latency
Agents block on tool calls. Heavy policy engines should cache decisions or run async approvals before the agent reaches the tool.
Argument shapes
Arguments arrive serialized per CrewAI version. Validate keys defensively before rewriting nested dicts.
Import
from crewai.hooks import before_tool_call_crew
How to Apply
@before_tool_call_crew
def audit(ctx):
log.info('%s called', ctx.tool_name)
What It Enables
- ✓ Tool-call gating
- ✓ Audit trail
Code Examples
Block deletes
@before_tool_call_crew
def guard(ctx):
if ctx.tool_name == 'delete_record': return False
Allowlist side-effecting tools
SAFE = {'search', 'read_file'}
@before_tool_call_crew
def rbac(ctx):
if ctx.tool_name not in SAFE:
return False
return None
Structured audit
@before_tool_call_crew
def audit(ctx):
audit_log.info('tool=%s args=%s', ctx.tool_name, getattr(ctx, 'tool_input', ''))
return None
Integration Patterns
Pairs with @after_tool_call_crew
Common Mistakes
❌ Returning True (truthy) thinking it allows the call
✅ Return None to allow, False to deny.
Related: Task class reference, Agent class reference, and the first Crew tutorial.
@before_tool_call_crew FAQ
What is @before_tool_call_crew in CrewAI?
Runs before every tool call within the crew — gate, log, or rewrite tool arguments. Tool calls are the highest-risk surface area for autonomous agents: they touch production databases, send email, and mutate external state. @before_tool_call_crew gives you a ToolCallHookContext with the tool name, serialized arguments, and agent metadata so you can deny calls, rewrite parameters (for example forcing sandbox hosts), or emit structured audit events before execution begins. Return False to veto the call entirely — the agent should receive a refusal without inv…
Which module defines the CrewAI decorator @before_tool_call_crew?
DevShelfHub maps @before_tool_call_crew to Python module crewai.hooks. Pin your installed crewai version and match imports to the import snippet on this page.
When should I use @before_tool_call_crew?
Approval gates on side-effecting tools, audit logging.
When should I avoid @before_tool_call_crew?
In-tool validation — do it inside _run().
How do I apply @before_tool_call_crew in Python?
@before_tool_call_crew def audit(ctx): log.info('%s called', ctx.tool_name)
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.