feat: add GuardrailProvider interface for pre-tool-call authorization (#4877)#4878
feat: add GuardrailProvider interface for pre-tool-call authorization (#4877)#4878devin-ai-integration[bot] wants to merge 1 commit intomainfrom
Conversation
…#4877) - Add GuardrailRequest dataclass for tool call context - Add GuardrailDecision dataclass for allow/deny verdicts - Add GuardrailProvider runtime-checkable protocol - Add enable_guardrail() adapter wiring providers into BeforeToolCallHook - Add disable() callable returned by enable_guardrail for cleanup - Support fail_closed (default) and fail_open exception handling - Export new types from crewai.hooks - Add 29 comprehensive tests covering all scenarios Co-Authored-By: João <joao@crewai.com>
|
Prompt hidden (unlisted session) |
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| ) | ||
| return False # block tool execution | ||
|
|
||
| return None # allow tool execution |
There was a problem hiding this comment.
fail_closed bypassed when provider returns malformed result
Medium Severity
The decision.allow access on line 274 sits outside the try/except block that handles provider errors. If evaluate() returns a non-GuardrailDecision object (e.g. None), the attribute access raises an AttributeError that escapes _hook(). The executor's outer try/except catches it, hook_blocked stays False, and the tool silently executes — effectively fail-open even when fail_closed=True. For a security/authorization feature, the fail_closed contract is broken for this class of provider errors.


feat: add GuardrailProvider interface for pre-tool-call authorization
Closes #4877
Summary
Adds a
GuardrailProviderprotocol that standardizes pluggable tool-call authorization on top of CrewAI's existingBeforeToolCallHooksystem. No changes to the tool execution pipeline.New types in
crewai.hooks:GuardrailRequest– dataclass with tool call context (tool_name, tool_input, agent_role, task_description, crew_id, timestamp)GuardrailDecision– dataclass with allow/deny verdict, reason, and arbitrary metadataGuardrailProvider–@runtime_checkableprotocol requiringname,evaluate(), andhealth_check()enable_guardrail(provider, *, fail_closed=True)– adapter that registers aBeforeToolCallHookdelegating to the provider; returns adisable()callable29 new tests covering dataclass defaults, protocol conformance, context mapping, allow/deny/exception paths, fail_closed vs fail_open, multiple providers, and disable lifecycle.
Review & Testing Checklist for Human
GuardrailDecision.reasonbehavior: The docstring says reason is "surfaced to the agent when blocked," but the hook returnsFalseonly — the reason is logged vialogger.infobut not passed back to the agent. Confirm this is acceptable or if the reason should be propagated (would require changes toBeforeToolCallHookcontract).health_check()intent: The protocol declareshealth_check()butenable_guardrailnever calls it. It's for provider-side use only. Confirm this is the desired design vs. checking health before registering or on each call.@runtime_checkableprotocol behavior: Python'sruntime_checkableonly checks method presence, not class-level attributename. Testtest_partial_implementation_is_not_guardrail_providerpasses because it lackshealth_check, but an object withevaluate+health_checkbut nonameattribute might still passisinstance. Verify this edge case is acceptable.pytest lib/crewai/tests/hooks/ -vv) to confirm no regressions in existing hooks.Notes
Note
Low Risk
Low risk: adds new opt-in guardrail adapter and types without changing existing tool/LLM hook execution unless
enable_guardrail()is used.Overview
Adds an opt-in guardrail layer on top of existing
before_tool_callhooks by introducingGuardrailProvider,GuardrailRequest, andGuardrailDecision, plusenable_guardrail()to register/unregister a provider-backed authorization hook (with configurable fail-closed vs fail-open behavior).Exports the new API via
crewai.hooks.__init__and adds a comprehensive test suite covering request construction, protocol conformance, allow/deny paths, exception handling, multiple providers, and hook disable lifecycle.Written by Cursor Bugbot for commit d5100a5. This will update automatically on new commits. Configure here.