From ab2d6e4eac89ee562cd3c608641a0b182bb733e1 Mon Sep 17 00:00:00 2001 From: Jay Prajapati <79649559+jayy-77@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:48:49 +0530 Subject: [PATCH 1/2] fix(chatgpt): drop unsupported responses params for Codex Co-authored-by: Cursor --- .../llms/chatgpt/responses/transformation.py | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/litellm/llms/chatgpt/responses/transformation.py b/litellm/llms/chatgpt/responses/transformation.py index 0ce24f63a89..bcb6edd39f9 100644 --- a/litellm/llms/chatgpt/responses/transformation.py +++ b/litellm/llms/chatgpt/responses/transformation.py @@ -73,10 +73,6 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): litellm_params, headers, ) - request.pop("max_output_tokens", None) - request.pop("max_tokens", None) - request.pop("max_completion_tokens", None) - request.pop("metadata", None) base_instructions = get_chatgpt_default_instructions() existing_instructions = request.get("instructions") if existing_instructions: @@ -92,7 +88,22 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): if "reasoning.encrypted_content" not in include: include.append("reasoning.encrypted_content") request["include"] = include - return request + + allowed_keys = { + "model", + "input", + "instructions", + "stream", + "store", + "include", + "tools", + "tool_choice", + "reasoning", + "previous_response_id", + "truncation", + } + + return {k: v for k, v in request.items() if k in allowed_keys} def transform_response_api_response( self, From 35bbcf9e9889ecf0e41d81f6543f506ee9c055a7 Mon Sep 17 00:00:00 2001 From: Jay Prajapati <79649559+jayy-77@users.noreply.github.com> Date: Sat, 14 Feb 2026 23:48:53 +0530 Subject: [PATCH 2/2] test(chatgpt): ensure Codex request filters unsupported params Co-authored-by: Cursor --- .../test_chatgpt_responses_transformation.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py b/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py index bec748d8dc8..03cea8785bc 100644 --- a/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py +++ b/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py @@ -88,6 +88,45 @@ class TestChatGPTResponsesAPITransformation: "You are Codex, based on GPT-5." ) + def test_chatgpt_drops_unsupported_responses_params(self): + config = ChatGPTResponsesAPIConfig() + request = config.transform_responses_api_request( + model="chatgpt/gpt-5.2-codex", + input="hi", + response_api_optional_request_params={ + # unsupported by ChatGPT Codex + "user": "user_123", + "temperature": 0.2, + "top_p": 0.9, + "context_management": [{"type": "compaction", "compact_threshold": 200000}], + "metadata": {"foo": "bar"}, + "max_output_tokens": 123, + "stream_options": {"include_usage": True}, + # supported and should be preserved + "truncation": "auto", + "previous_response_id": "resp_123", + "reasoning": {"effort": "medium"}, + "tools": [{"type": "function", "function": {"name": "hello"}}], + "tool_choice": {"type": "function", "function": {"name": "hello"}}, + }, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + + assert "user" not in request + assert "temperature" not in request + assert "top_p" not in request + assert "context_management" not in request + assert "metadata" not in request + assert "max_output_tokens" not in request + assert "stream_options" not in request + + assert request["truncation"] == "auto" + assert request["previous_response_id"] == "resp_123" + assert request["reasoning"] == {"effort": "medium"} + assert request["tools"] == [{"type": "function", "function": {"name": "hello"}}] + assert request["tool_choice"] == {"type": "function", "function": {"name": "hello"}} + def test_chatgpt_non_stream_sse_response_parsing(self): config = ChatGPTResponsesAPIConfig() response_payload = {