From 3f5279cdada52444d68c5f3107843d79dc309c0e Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Tue, 10 Feb 2026 16:31:16 -0800 Subject: [PATCH] add_policy_sources_to_metadata + headers --- litellm/proxy/common_utils/callback_utils.py | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/litellm/proxy/common_utils/callback_utils.py b/litellm/proxy/common_utils/callback_utils.py index faeca9b2aed..e7964a81309 100644 --- a/litellm/proxy/common_utils/callback_utils.py +++ b/litellm/proxy/common_utils/callback_utils.py @@ -394,6 +394,13 @@ def get_logging_caching_headers(request_data: Dict) -> Optional[Dict]: _metadata["applied_policies"] ) + if "policy_sources" in _metadata: + sources = _metadata["policy_sources"] + if isinstance(sources, dict) and sources: + headers["x-litellm-policy-sources"] = ",".join( + f"{name}={reason}" for name, reason in sources.items() + ) + if "semantic-similarity" in _metadata: headers["x-litellm-semantic-similarity"] = str(_metadata["semantic-similarity"]) @@ -441,6 +448,27 @@ def add_policy_to_applied_policies_header( request_data["metadata"] = _metadata +def add_policy_sources_to_metadata( + request_data: Dict, policy_sources: Dict[str, str] +): + """ + Store policy match reasons in metadata for x-litellm-policy-sources header. + + Args: + request_data: The request data dict + policy_sources: Map of policy_name -> matched_via reason + """ + if not policy_sources: + return + _metadata = request_data.get("metadata", None) or {} + existing = _metadata.get("policy_sources", {}) + if not isinstance(existing, dict): + existing = {} + existing.update(policy_sources) + _metadata["policy_sources"] = existing + request_data["metadata"] = _metadata + + def add_guardrail_response_to_standard_logging_object( litellm_logging_obj: Optional["LiteLLMLogging"], guardrail_response: StandardLoggingGuardrailInformation,