diff --git a/litellm/llms/anthropic/pass_through/messages/transformation.py b/litellm/llms/anthropic/pass_through/messages/transformation.py index 35db54147c5..582b58e8817 100644 --- a/litellm/llms/anthropic/pass_through/messages/transformation.py +++ b/litellm/llms/anthropic/pass_through/messages/transformation.py @@ -706,12 +706,12 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig): messages = strip_advisor_blocks_from_messages(messages) anthropic_messages_request: Final[AnthropicMessagesRequest] = AnthropicMessagesRequest( - messages=strip_encrypted_reasoning_blocks_from_anthropic_messages( - drop_non_string_tool_result_texts(messages, getattr(litellm_params, "drop_params", None)) - ), max_tokens=max_tokens, model=model, **anthropic_messages_optional_request_params, + messages=strip_encrypted_reasoning_blocks_from_anthropic_messages( + drop_non_string_tool_result_texts(messages, getattr(litellm_params, "drop_params", None)) + ), ) return dict(anthropic_messages_request) diff --git a/tests/unit/llms/anthropic/pass_through/messages/test_anthropic_experimental_pass_through_messages_transformation.py b/tests/unit/llms/anthropic/pass_through/messages/test_anthropic_experimental_pass_through_messages_transformation.py index 457d5d5e1c8..fe434d023c3 100644 --- a/tests/unit/llms/anthropic/pass_through/messages/test_anthropic_experimental_pass_through_messages_transformation.py +++ b/tests/unit/llms/anthropic/pass_through/messages/test_anthropic_experimental_pass_through_messages_transformation.py @@ -416,3 +416,21 @@ def test_drop_params_forwards_a_non_object_message_item_as_sent_on_the_native_re assert request["messages"][1] == 7 assert request["messages"][2]["content"][0]["content"] == [{"type": "text", "text": "sunny"}] + + +def test_messages_request_body_ends_with_messages_after_system_and_tools() -> None: + messages: Final = [{"role": "user", "content": "Hello"}] + request: Final = AnthropicMessagesConfig().transform_anthropic_messages_request( + model="claude-opus-5-5", + messages=messages, + anthropic_messages_optional_request_params={ + "max_tokens": 256, + "system": [{"type": "text", "text": "You are terse."}], + "tools": [{"name": "get_weather", "input_schema": {"type": "object", "properties": {}}}], + }, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + + assert list(request)[-1] == "messages", f"key order sent upstream: {list(request)}" + assert request["messages"] == messages diff --git a/tests/unit/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py b/tests/unit/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py index ae9b9684f2d..fa7c9b383bf 100644 --- a/tests/unit/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py +++ b/tests/unit/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_messages_config.py @@ -823,3 +823,22 @@ def test_vertex_claude_4_8_plus_cost_map_entries_carry_mid_conversation_system_f and info.get("supports_mid_conversation_system") is not True ] assert missing == [] + + +def test_vertex_messages_request_body_puts_system_and_tools_before_messages() -> None: + result: Final = VertexAIPartnerModelsAnthropicMessagesConfig().transform_anthropic_messages_request( + model="claude-opus-5-5", + messages=[{"role": "user", "content": "Hello"}], + anthropic_messages_optional_request_params={ + "max_tokens": 256, + "system": [{"type": "text", "text": "You are terse."}], + "tools": [{"name": "get_weather", "input_schema": {"type": "object", "properties": {}}}], + }, + litellm_params=GenericLiteLLMParams(), + headers={}, + ) + + keys: Final = list(result) + assert keys.index("system") < keys.index("messages"), f"key order sent to Vertex: {keys}" + assert keys.index("tools") < keys.index("messages"), f"key order sent to Vertex: {keys}" + assert result["messages"] == [{"role": "user", "content": "Hello"}]