* Consolidated change
* fix(prompt_security): update message processing to persist sanitized files and filter for API calls
* fix per krrishdholakia suggestion
- Add `should_wrap_with_default_message` parameter to GuardrailRaisedException
- Update Generic Guardrail API to use clean error messages without wrapper
- When should_wrap_with_default_message=False, exception shows the original
blocked_reason directly (e.g., "pii detected") instead of verbose format
- Update test to verify GuardrailRaisedException is raised with clean message
* fix(generic-guardrail-api): fix SerializationIterator error on multimodal requests
When sending multimodal messages (with images) through the Generic Guardrail API,
the `model_dump()` call fails with "Object of type SerializationIterator is not
JSON serializable" error.
Root cause: The `ChatCompletionAssistantMessage` type defines `content` as an
`Iterable` (not just `List`), and Pydantic's `model_dump()` creates a
`SerializationIterator` for iterables which is not JSON serializable.
Fix: Use `model_dump(mode="json")` which properly converts all iterables to
lists and ensures all complex objects are JSON serializable.
* fix(guardrails): pass tools (function definitions) to guardrail inputs
The unified guardrail handler was not passing the `tools` parameter
(function definitions) from the request to the guardrail inputs.
This meant guardrails could not inspect or validate tool definitions.
Added extraction of `data.get("tools")` and inclusion in the
GenericGuardrailAPIInputs passed to `apply_guardrail()`.
* test(guardrails): add tests for tools passed to guardrail
Added tests verifying that tools (function definitions) are correctly
passed to guardrails in the unified guardrail handler:
- test_tools_passed_to_guardrail
- test_multiple_tools_passed_to_guardrail
- test_no_tools_in_request
- test_tools_and_tool_calls_both_passed
* init guardrails
* init guardrails
* some fixes
* some fixes
* ruff
* some fixes
* some fixes
* some fixes
* some fixes
* some fixes
* some fixes
* docs
This fixes a critical issue where capitalized values in tool_permission guardrail
configurations (e.g., "Deny" instead of "deny") caused Pydantic validation errors
during proxy startup, leading to repeated initialization failures and latency issues.
Problem:
- Users could save guardrails with capitalized values through UI/API
- Data was written to database without validation (e.g., default_action: "Deny")
- On proxy startup, loading from DB triggered strict Pydantic validation
- ValidationError caused guardrail initialization to fail in a retry loop
- This resulted in startup delays and repeated error logging
Root Cause:
- Write path had no case normalization
- Read path enforced strict lowercase Literal validation
- Asymmetry between write and read caused latent data corruption
Solution:
Added field validators to normalize case before Pydantic validation:
1. ToolPermissionRule.decision ("allow"/"deny")
- Normalizes decision field in rules array
2. ToolPermissionGuardrailConfigModel.default_action ("allow"/"deny")
- Normalizes default fallback action
3. ToolPermissionGuardrailConfigModel.on_disallowed_action ("block"/"rewrite")
- Normalizes disallowed tool behavior
4. ToolPermissionGuardrail.__init__ normalization
- Defensive normalization for direct instantiation
- Ensures normalization regardless of code path
Impact:
- Prevents validation errors during guardrail initialization
- Eliminates startup retry loops and latency issues
- Handles existing database records with capitalized values
- Accepts case-insensitive input from all sources (UI, API, direct calls)
- Fully backward compatible with existing lowercase configurations
Testing:
- Added 3 comprehensive tests for case-insensitive handling
- All 27 existing tests still pass
- Tests verify normalization across all affected fields
Files Changed:
- litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py
Added @field_validator decorators for case normalization
- litellm/proxy/guardrails/guardrail_hooks/tool_permission.py
Added runtime normalization in __init__ method
- tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_permission.py
Added case-insensitive validation tests
* feat(litellm_content_filter.py): add support for content filtering categories
make it easy for proxy admin to prevent messages about violence, self harm or illegal weapons going through litellm
* feat: initial commit adding bias detection
allows admin to block inappropriate content about sexual orientation, etc.
* refactor: simplify content_filter.py
use a more exhaustive set of keywords, instead of guessing at potential phrases user can use
* feat(content_filter.py): add new denied topics for in-built content filter guardrails
allow user to automatically block content relating to certain categories from being sent to the LLML
* refactor(content-filter): document new params to litellm content filter
* feat(ui/): litellm content filter - select content categories on ui
* docs: update documentation
* docs(litellm_content_filter.md): document new content filters
* feat: initial commit adding support for inappropriate images via litellm content filter
* feat(content_filter.py): support blocking images containing blocked content
prevent images which contain disallowed content from being sent to the llm api
* docs(litellm_content_filter.md): document new image capabilities of litellm_content_filter
* fix: fix expected error code
- Add 'mask' action to SUPPORTED_ON_FLAGGED_ACTIONS
- Automatically sanitizes sensitive content using masked_session_messages
- Allows requests to proceed with masked content instead of blocking
- Add MCP call support
- Add pre_mcp_call and during_mcp_call to supported_event_hooks
- Verify mcp_call is supported in call_type Literal types
- Control exception details based on config
- Conditionally include scanners/evidence in exceptions based on
include_scanners and include_evidence settings
- Reduces payload size when detailed exception info isn't needed
- Add comprehensive test coverage
- Tests for masking functionality
- Tests for conditional exception details
- Tests for MCP call support
- Update documentation
- Add Mask section explaining masking functionality
- Clarify exception details control
All changes maintain backward compatibility.
* prioritized bedrock guardrail blocking by removing early return based on masking flags
When mask_request_content: true or mask_response_content: true, the method immediately returning False.
The Result: Even when Bedrock Guardrails returned action: "BLOCKED" for dangerous content, LiteLLM would not raise an exception and allowing the content through the response.
So removed that early condition which will return true for the blocked actions based on guardrails.
* Added test case for bedrock guardrail block content precedence
* fix(unified_guardrails.py): send all chunks on completion of final stream
* feat(generic_guardrail_api.py): handle tool call response on streaming LLM responses
* fix(anthropic/chat/guardrail_translation): initial commit adding anthropic tool response streaming guardrails
enables guardrail checks on tool response from llm's to work via `/v1/messages`
* feat(anthropic/): working guardrail checks on tool response from LLMs
ensures guardrail checks on anthropic /v1/messages works as expected
* feat(responses/guardrail_translation): support tool call response guardrails on streaming for /v1/responses
ensures complete coverage of tool call responses
* refactor(openai.py): refactor to use consistent pydantic model for responses api tool response on streaming
enables non-openai model tool call response to work correctly with guardrail checks on /v1/responses
* test: update tests
* fix: fix linting error
* fix: fix failing tests
* fix: fix import errors
* fix(openai/chat/guardrail_transformation): fix final chunk returned on streaming
* attempt to implement the passthrough feature
* Formatting and small change
* Fix formatting
* feat: grayswan guardrail overwrite ModelResponse in passthrough mode
* fix missing exception error catching on certain
endpoints
* fix wrong call site
* fix: patch anthropic endpoint internal error on streaming obj
* fix grayswan testcase
* feat: update the violation response to more natural
* Formatting
* move passthrough exception definition to custom_guardrail.
* Enhancement: show whether the blocked at input or output
* update exception name
* fix a typo in testing unit.
---------
Co-authored-by: Xiaohan Fu <xiaohan@grayswan.ai>
- Skip empty/whitespace text before calling Presidio API
- Handle error dict responses gracefully (e.g., {'error': 'No text provided'})
- Add defensive error handling for invalid result items
- Add comprehensive test coverage for empty content scenarios
Fixes crash in tool/function calling where assistant messages have empty content.
* fix(unified_guardrail.py): support during_call event type for unified guardrails
allows guardrails overriding apply_guardrails to work 'during_call'
* feat(generic_guardrail_api.py): support new 'tool_calls' field for generic guardrail api
returns the tool calls emitted by the LLM API to the user
* fix(generic_guardrail_api.py): working anthropic /v1/messages tool call response
send llm tool calls to guardrail api when called via `/v1/messages` API
* fix(responses/): run generic_guardrail_api on responses api tool call responses
* fix: fix tests
* test: fix tests
* fix: fix tests
Fixes#17517
- Fixed bug where only the first matching blocked keyword was masked
- Now iterates through ALL blocked keywords and masks each one
- Added 3 regression tests for multiple keyword masking
* fix(unified_guardrail.py): correctly map a v1/messages call to the anthropic unified guardrail
* fix: add more rigorous call type checks
* fix(anthropic_endpoints/endpoints.py): initialize logging object at the beginning of endpoint
ensures call id + trace id are emitted to guardrail api
* feat(anthropic/chat/guardrail_translation): support streaming guardrails
sample on every 5 chunks
* fix(openai/chat/guardrail_translation): support openai streaming guardrails
* fix: initial commit fixing output guardrails for responses api
* feat(openai/responses/guardrail_translation): handler.py - fix output checks on responses api
* fix(openai/responses/guardrail_translation/handler.py): ensure responses api guardrails work on streaming
* test: update tests
* test: update tests
* fix: support multiple kinds of input to the guardrail api
* feat(guardrail_translation/handler.py): support extracting tool calls from openai chat completions for guardrail api's
* feat(generic_guardrail_api.py): support extracting + returning modified tool calls on generic_guardrails_api
allows guardrail api to analyze tool call being sent to provider - to run any analysis on it
* fix(guardrails.py): support anthropic /v1/messages tool calls
* feat(responses_api/): extract tool calls for guardrail processing
* docs(generic_guardrail_api.md): document tools param support
* docs: generic_guardrail_api.md
improve documentation
* fix(unified_guardrail.py): correctly map a v1/messages call to the anthropic unified guardrail
* fix: add more rigorous call type checks
* fix(anthropic_endpoints/endpoints.py): initialize logging object at the beginning of endpoint
ensures call id + trace id are emitted to guardrail api
* feat(anthropic/chat/guardrail_translation): support streaming guardrails
sample on every 5 chunks
* fix(openai/chat/guardrail_translation): support openai streaming guardrails
* fix: initial commit fixing output guardrails for responses api
* feat(openai/responses/guardrail_translation): handler.py - fix output checks on responses api
* fix(openai/responses/guardrail_translation/handler.py): ensure responses api guardrails work on streaming
* test: update tests
* test: update tests
* test: update tests
* fix(bedrock_guardrails.py): fix post call streaming iterator logic
* fix: fix return
* fix(bedrock_guardrails.py): fix
* fix(initial-commit): adding a way to get the right response type based on the api route
* feat(unified_guardrail.py): support streaming guardrails
* test: update tests
* fix: fix linting errors
* test: update tests
* refactor(generic_guardrail_api.py): refactor to update to new guardrail api logic
* refactor: refactor llm api integrations to support passing in text as a list[str] instead of one at a time
* refactor: fix linting errors
* refactor: pass request type to guardrail api
allows request vs. response processing to occur
* feat: pass user api key dict information to the guardrail api
* fix: pass user api key dict information to the guardrail api
* feat: pass litellm call id + trace id, if present
* docs: update docs
* store and fetch lasso-conversation id from cache
* include gateway/v# in the baseUrl to allow simpler version migrations in the future
* add tests for cached conversation ID