From ea98d8e116af74809aab1149ad34003fba0f516f Mon Sep 17 00:00:00 2001 From: Yang Yang Date: Fri, 19 Jun 2026 22:43:15 -0700 Subject: [PATCH] fix(xai): read tool usage details from ResponseAPIUsage extras Also inspect model_extra when attaching server_side_tool_usage_details for Responses cost tracking. --- litellm/llms/xai/responses/transformation.py | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/litellm/llms/xai/responses/transformation.py b/litellm/llms/xai/responses/transformation.py index fbff9876d49..7cf2f48f956 100644 --- a/litellm/llms/xai/responses/transformation.py +++ b/litellm/llms/xai/responses/transformation.py @@ -76,6 +76,22 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): self._attach_server_side_tool_usage_details_to_usage(response) return response + @staticmethod + def _server_side_tool_usage_details_from_usage(usage: Any) -> Any: + if usage is None: + return None + if isinstance(usage, dict): + return usage.get("server_side_tool_usage_details") + details = getattr(usage, "server_side_tool_usage_details", None) + if details is not None: + return details + model_extra = getattr(usage, "model_extra", None) or getattr( + usage, "__pydantic_extra__", None + ) + if isinstance(model_extra, dict): + return model_extra.get("server_side_tool_usage_details") + return None + @staticmethod def _attach_server_side_tool_usage_details_to_usage( response: ResponsesAPIResponse, @@ -83,9 +99,9 @@ class XAIResponsesAPIConfig(OpenAIResponsesAPIConfig): if response.usage is None: return - details = getattr(response.usage, "server_side_tool_usage_details", None) - if details is None and isinstance(response.usage, dict): - details = response.usage.get("server_side_tool_usage_details") + details = XAIResponsesAPIConfig._server_side_tool_usage_details_from_usage( + response.usage + ) if details is None: return