diff --git a/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py b/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py index 8955bffc125..b8a1566160e 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py +++ b/litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py @@ -545,7 +545,9 @@ class GraySwanGuardrail(CustomGuardrail): if "metadata" in dynamic_body: payload["metadata"] = dynamic_body["metadata"] - litellm_metadata = request_data.get("litellm_metadata") + litellm_metadata = request_data.get("litellm_metadata") or request_data.get( + "_guardrail_litellm_metadata" + ) if isinstance(litellm_metadata, dict) and litellm_metadata: cleaned_litellm_metadata = dict(litellm_metadata) # cleaned_litellm_metadata.pop("user_api_key_auth", None) diff --git a/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py b/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py index 367e6b2f150..e861a67278b 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py +++ b/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py @@ -53,8 +53,13 @@ endpoint_guardrail_translation_mappings = None def _ensure_litellm_metadata(data: dict, user_api_key_dict: UserAPIKeyAuth) -> None: - """Populate data['litellm_metadata'] from user_api_key_dict if absent.""" - if "litellm_metadata" not in data: + """Populate data['litellm_metadata'] from user_api_key_dict if absent. + + Uses '_guardrail_litellm_metadata' as the key when 'litellm_metadata' is not + already present, to avoid interfering with get_metadata_variable_name_from_kwargs() + which switches metadata routing when 'litellm_metadata' exists. + """ + if "litellm_metadata" not in data and "_guardrail_litellm_metadata" not in data: from litellm.llms.base_llm.guardrail_translation.base_translation import ( BaseTranslation, ) @@ -63,7 +68,7 @@ def _ensure_litellm_metadata(data: dict, user_api_key_dict: UserAPIKeyAuth) -> N user_api_key_dict ) if user_metadata: - data["litellm_metadata"] = user_metadata + data["_guardrail_litellm_metadata"] = user_metadata class UnifiedLLMGuardrails(CustomLogger): diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_grayswan.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_grayswan.py index 14cf732aa7c..d5f9d66870d 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_grayswan.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_grayswan.py @@ -477,8 +477,28 @@ def test_prepare_payload_includes_litellm_metadata( assert payload["litellm_metadata"]["user_api_key_team_id"] == "team-456" +def test_prepare_payload_includes_guardrail_litellm_metadata( + grayswan_guardrail: GraySwanGuardrail, +) -> None: + """Verify _prepare_payload reads from _guardrail_litellm_metadata fallback.""" + messages = [{"role": "user", "content": "hello"}] + request_data = { + "_guardrail_litellm_metadata": { + "user_api_key_user_id": "user-pre", + "user_api_key_team_id": "team-pre", + } + } + + payload = grayswan_guardrail._prepare_payload(messages, {}, request_data) + + assert payload is not None + assert "litellm_metadata" in payload + assert payload["litellm_metadata"]["user_api_key_user_id"] == "user-pre" + assert payload["litellm_metadata"]["user_api_key_team_id"] == "team-pre" + + def test_ensure_litellm_metadata_populates_from_user_api_key_dict() -> None: - """Verify _ensure_litellm_metadata populates from user_api_key_dict.""" + """Verify _ensure_litellm_metadata populates _guardrail_litellm_metadata.""" from litellm.proxy.guardrails.guardrail_hooks.unified_guardrail.unified_guardrail import ( _ensure_litellm_metadata, ) @@ -488,9 +508,11 @@ def test_ensure_litellm_metadata_populates_from_user_api_key_dict() -> None: _ensure_litellm_metadata(data, user_auth) - assert "litellm_metadata" in data - assert data["litellm_metadata"]["user_api_key_user_id"] == "u1" - assert data["litellm_metadata"]["user_api_key_team_id"] == "t1" + # Uses _guardrail_ prefix to avoid interfering with metadata routing + assert "_guardrail_litellm_metadata" in data + assert "litellm_metadata" not in data + assert data["_guardrail_litellm_metadata"]["user_api_key_user_id"] == "u1" + assert data["_guardrail_litellm_metadata"]["user_api_key_team_id"] == "t1" def test_ensure_litellm_metadata_noop_when_already_present() -> None: @@ -505,3 +527,4 @@ def test_ensure_litellm_metadata_noop_when_already_present() -> None: _ensure_litellm_metadata(data, user_auth) assert data["litellm_metadata"] == {"existing": "value"} + assert "_guardrail_litellm_metadata" not in data