Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,20 @@ def transform_request(
instructions,
) = self.convert_chat_completion_messages_to_responses_api(messages)

# OpenAI's Responses API rejects an empty input. For a system-only
# request, carry the system message as a system-role input item instead
# of instructions, mirroring how non-string system content is already
# handled in convert_chat_completion_messages_to_responses_api.
if not input_items and instructions is not None:
input_items = [
{
"type": "message",
"role": "system",
"content": [{"type": "input_text", "text": instructions}],
}
]
instructions = None

optional_params = self._extract_extra_body_params(optional_params)

# Build responses API request using the reverse transformation logic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
0, os.path.abspath("../../..")
) # Adds the parent directory to the system-path
import litellm
from litellm.completion_extras.litellm_responses_transformation.transformation import (
LiteLLMResponsesTransformationHandler,
)


def test_convert_chat_completion_messages_to_responses_api_image_input():
Expand Down Expand Up @@ -860,6 +863,39 @@ def test_extract_extra_body_params_reasoning_effort_override():
assert "extra_body" not in result


def test_transform_request_system_only_message_maps_to_system_input_item():
"""System-only requests must not send input=[] to the Responses API.

OpenAI rejects both input=[] and input="". When the only message is a
system message, carry it as a system-role input item (single copy, correct
role) rather than leaving input empty or duplicating it into instructions.
"""
handler = LiteLLMResponsesTransformationHandler()
logging_obj = Mock()
messages = [{"role": "system", "content": "You are a helpful assistant."}]

result = handler.transform_request(
model="gpt-5.3-codex",
messages=messages,
optional_params={},
litellm_params={},
headers={},
litellm_logging_obj=logging_obj,
)

assert result["input"] == [
{
"type": "message",
"role": "system",
"content": [
{"type": "input_text", "text": "You are a helpful assistant."}
],
}
]
# System content lives in input only; not duplicated into instructions.
assert not result.get("instructions")


def test_transform_request_single_char_keys_not_matched():
"""Test that single-character keys are not incorrectly matched to 'metadata' or 'previous_response_id'

Expand Down
Loading