diff --git a/litellm/llms/chatgpt/responses/transformation.py b/litellm/llms/chatgpt/responses/transformation.py index 2352de35b5b..3d2700c9c66 100644 --- a/litellm/llms/chatgpt/responses/transformation.py +++ b/litellm/llms/chatgpt/responses/transformation.py @@ -113,6 +113,13 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): request["instructions"] = f"{base_instructions}\n\n{existing_instructions}" else: request["instructions"] = base_instructions + # The Codex backend rejects role=system input items ("System messages are not allowed") + # but accepts role=developer, which is what an in-sequence system message means there. + if isinstance(request.get("input"), list): + request["input"] = [ + {**item, "role": "developer"} if isinstance(item, dict) and item.get("role") == "system" else item + for item in request["input"] + ] request["store"] = False request["stream"] = True include: Final = list(request.get("include") or []) diff --git a/tests/unit/llms/chatgpt/responses/test_chatgpt_responses_transformation.py b/tests/unit/llms/chatgpt/responses/test_chatgpt_responses_transformation.py index d88bdfc0b41..b30d955f09a 100644 --- a/tests/unit/llms/chatgpt/responses/test_chatgpt_responses_transformation.py +++ b/tests/unit/llms/chatgpt/responses/test_chatgpt_responses_transformation.py @@ -74,6 +74,18 @@ class TestChatGPTResponsesAPITransformation: assert "service_tier" not in request + def test_system_input_items_become_developer(self): + system_item = {"type": "message", "role": "system", "content": [{"type": "input_text", "text": "be brief"}]} + user_item = {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "hi"}]} + request = ChatGPTResponsesAPIConfig().transform_responses_api_request( + model="gpt-6.1-sol", + input=[user_item, system_item], + response_api_optional_request_params={}, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + assert request["input"] == [user_item, {**system_item, "role": "developer"}] + @pytest.mark.parametrize( "model_name", [