diff --git a/litellm/litellm_core_utils/get_litellm_params.py b/litellm/litellm_core_utils/get_litellm_params.py index 57adf23c99e..0925e753e5e 100644 --- a/litellm/litellm_core_utils/get_litellm_params.py +++ b/litellm/litellm_core_utils/get_litellm_params.py @@ -109,7 +109,7 @@ def get_litellm_params( # the request uses "litellm_metadata" (e.g. /v1/messages from Claude Code). _merged_metadata = metadata if litellm_metadata and isinstance(litellm_metadata, dict): - if not _merged_metadata: + if _merged_metadata is None: _merged_metadata = dict(litellm_metadata) else: _merged_metadata = dict(_merged_metadata) # don't mutate caller's dict diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index b47f27da2cd..558e30460fd 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -608,7 +608,16 @@ class Logging(LiteLLMLoggingBaseClass): if "litellm_metadata" in kwargs and isinstance( kwargs["litellm_metadata"], dict ): - base_litellm_params["litellm_metadata"] = kwargs["litellm_metadata"].copy() + base_litellm_params["litellm_metadata"] = kwargs["litellm_metadata"] + if "metadata" not in base_litellm_params: + base_litellm_params["metadata"] = kwargs["litellm_metadata"].copy() + else: + # Merge litellm_metadata into metadata without overwriting existing + # keys so API key fields are visible to callbacks even when + # Anthropic's native metadata is present (/v1/messages). + for key, value in kwargs["litellm_metadata"].items(): + if key not in base_litellm_params["metadata"]: + base_litellm_params["metadata"][key] = value if litellm_params: base_litellm_params.update(litellm_params) diff --git a/litellm/utils.py b/litellm/utils.py index 459a366c5cd..acb3c0cc571 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -1155,15 +1155,12 @@ def function_setup( # noqa: PLR0915 # populate litellm_params["metadata"] so callbacks (e.g. Langfuse) that # read API key info from litellm_params["metadata"] see the fields. if not litellm_params.get("metadata"): - litellm_params["metadata"] = dict(kwargs["litellm_metadata"]) + litellm_params["metadata"] = kwargs["litellm_metadata"].copy() else: # Merge litellm_metadata into metadata without overwriting existing # keys. This ensures API key fields (user_api_key_hash, etc.) are # visible to callbacks even when Anthropic's native metadata field # is present in /v1/messages requests from Claude Code. - litellm_params["metadata"] = dict( - litellm_params["metadata"] - ) # don't mutate caller's dict for key, value in kwargs["litellm_metadata"].items(): if key not in litellm_params["metadata"]: litellm_params["metadata"][key] = value