From 423b6bad2baaf7622c4d9825442524f721558a1a Mon Sep 17 00:00:00 2001 From: Muspi Merol Date: Wed, 16 Sep 2026 17:06:41 +0800 Subject: [PATCH] fix(langfuse): preserve Responses tool namespaces --- litellm/integrations/langfuse/langfuse_otel.py | 2 ++ tests/unit/integrations/test_langfuse_otel.py | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/litellm/integrations/langfuse/langfuse_otel.py b/litellm/integrations/langfuse/langfuse_otel.py index a96fac32c2a..502435d9b2c 100644 --- a/litellm/integrations/langfuse/langfuse_otel.py +++ b/litellm/integrations/langfuse/langfuse_otel.py @@ -210,6 +210,8 @@ class LangfuseOtelLogger(OpenTelemetry): "type": "function_call", "arguments": arguments_obj, } + if (namespace := getattr(item, "namespace", None)) is not None: + langfuse_tool_call["namespace"] = namespace output_items_data.append(langfuse_tool_call) if output_items_data: safe_set_attribute( diff --git a/tests/unit/integrations/test_langfuse_otel.py b/tests/unit/integrations/test_langfuse_otel.py index 0a9ce55fe16..4b26ee9d36f 100644 --- a/tests/unit/integrations/test_langfuse_otel.py +++ b/tests/unit/integrations/test_langfuse_otel.py @@ -897,7 +897,8 @@ class TestLangfuseOtelResponsesAPI: == "The weather in San Francisco is sunny, 20°C." ) - def test_responses_api_with_function_calls(self): + @pytest.mark.parametrize("namespace", (None, "weather", "")) + def test_responses_api_with_function_calls(self, namespace: str | None): """Test Langfuse OTEL logger with Responses API function_call output.""" from litellm.types.integrations.langfuse_otel import LangfuseSpanAttributes from openai.types.responses import ResponseFunctionToolCall @@ -911,6 +912,7 @@ class TestLangfuseOtelResponsesAPI: id="fc-123", type="function_call", name="get_weather", + namespace=namespace, call_id="call-abc", arguments='{"location": "San Francisco", "unit": "celsius"}', status="completed", @@ -958,6 +960,10 @@ class TestLangfuseOtelResponsesAPI: assert output_data[0]["call_id"] == "call-abc" assert output_data[0]["arguments"]["location"] == "San Francisco" assert output_data[0]["arguments"]["unit"] == "celsius" + if namespace is None: + assert "namespace" not in output_data[0] + else: + assert output_data[0]["namespace"] == namespace def test_responses_api_function_call_with_redacted_arguments(self): """Sentinel arguments (invalid JSON) must not kill the whole observation output."""