What is create_dynamic_tool_filter()?
create_dynamic_tool_filter(predicate) wraps an MCP adapter with a per-call decision function: for each tool the server advertises, CrewAI invokes predicate(tool, ToolFilterContext) where the context carries the acting agent, active task metadata, and other routing hints. Return True to expose a tool to the LLM for that invocation. This pattern implements least-privilege without maintaining dozens of static lists for every persona.
Keep predicates pure and fast — they run while building the tool manifest for a kickoff. Heavy IO belongs in tools themselves, not in filters. Log denials at debug level with structured fields so you can prove compliance without flooding production logs.
When every agent in a crew shares one MCP adapter, dynamic filters are how you still enforce per-role boundaries. If only one agent ever touches the adapter, a static filter may be simpler and easier to audit.
Use Cases
- • Role-based access
- • Task-aware narrowing
Key Features
- ✓ Predicate-based
- ✓ Receives ToolFilterContext
When NOT to Use
Static lists are fine — use create_static_tool_filter then.
Notes
Predicate bugs become total outages
Returning False for every tool leaves agents helpless. Unit-test filters against representative ToolFilterContext objects.
Observability
Dynamic decisions are harder to diff than static lists. Emit metrics for allow/deny counts per tool name when rolling out new policies.
Latency
Complex predicates multiply with the number of advertised tools. Avoid remote calls inside the filter; cache policy lookups on ctx when possible.
Fallback posture
Default-deny is safer for regulated workloads; combine with explicit allow rules for break-glass tools instead of default-allow with blocklists.
Parameters
| Parameter | Type | Required | Purpose |
|---|---|---|---|
| predicate | Callable[[Tool, ToolFilterContext], bool] | No | Decides per call. |
Code Examples
Role-based
flt = create_dynamic_tool_filter(lambda t, ctx: ctx.agent.role == 'manager' or t.name != 'delete')
Task-tag gate
from crewai.mcp.filters import create_dynamic_tool_filter
def task_tag_gate(tool, ctx):
tags = getattr(ctx.task, 'tags', []) or []
if 'readonly' in tags:
return tool.name in {'search', 'fetch'}
return True
flt = create_dynamic_tool_filter(task_tag_gate)
Deny destructive tools outside business hours
import datetime as dt
from crewai.mcp.filters import create_dynamic_tool_filter
DANGEROUS = {'delete_table', 'drop_index'}
def business_hours(tool, ctx):
if tool.name in DANGEROUS and dt.datetime.utcnow().hour >= 17:
return False
return True
flt = create_dynamic_tool_filter(business_hours)
When to Use
When tool visibility depends on runtime context.
Common Mistakes
❌ Mutating ctx or tool objects to carry side state
✅ Treat inputs as read-only; persist decisions through proper crew state or logging channels.
Related: @tool decorator reference, Agent class reference, and the first Crew tutorial.
create_dynamic_tool_filter() FAQ
What is create_dynamic_tool_filter() in CrewAI?
Builds a filter that picks tools at runtime based on a callable predicate. create_dynamic_tool_filter(predicate) wraps an MCP adapter with a per-call decision function: for each tool the server advertises, CrewAI invokes predicate(tool, ToolFilterContext) where the context carries the acting agent, active task metadata, and other routing hints. Return True to expose a tool to the LLM for that invocation. This pattern implements least-privilege without maintaining dozens of static lists for every persona. Keep predicates pure and fast — they run whi…
Which CrewAI types expose the method create_dynamic_tool_filter()?
DevShelfHub documents create_dynamic_tool_filter() on MCP. The reference maps it to Python module crewai.mcp.filters — pin your installed crewai version and match imports to the snippet on this page.
When should I use create_dynamic_tool_filter()?
When tool visibility depends on runtime context.
When should I avoid create_dynamic_tool_filter()?
Static lists are fine — use create_static_tool_filter then.
How do I call create_dynamic_tool_filter() from Python?
flt = create_dynamic_tool_filter(predicate)
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.