[Bugfix] Fix Anthropic Thinking Disabled with P/D (#58786)

Signed-off-by: Robert Shaw <robshaw@redhat.com> Co-authored-by: Robert Shaw <robshaw@redhat.com>

Robert Shaw committed Sep 26, 2026 at 09:50 UTC d64f277c54d444284bdbcd16e7fd1073b0a3b50e
2 files changed +26
tests/entrypoints/anthropic/test_anthropic_messages_conversion.py
+22
@@ -1804,6 +1804,28 @@ class TestThinkingConfig:
1804 thinking=thinking,
1805 )
1806
1807 + def test_pd_prefill_leg_skips_budget_check(self):
1808 + """P/D sidecars resend the request to the prefill node with
1809 + max_tokens=1; the budget is enforced on the decode leg instead."""
1810 + thinking = {"type": "enabled", "budget_tokens": 1024}
1811 + request = AnthropicMessagesRequest(
1812 + model="test-model",
1813 + max_tokens=1,
1814 + messages=[{"role": "user", "content": "Hello"}],
1815 + thinking=thinking,
1816 + kv_transfer_params={"do_remote_decode": True},
1817 + )
1818 +
1819 + assert _convert(request).thinking_token_budget == 1024
1820 + with pytest.raises(ValidationError):
1821 + AnthropicMessagesRequest(
1822 + model="test-model",
1823 + max_tokens=1,
1824 + messages=[{"role": "user", "content": "Hello"}],
1825 + thinking=thinking,
1826 + kv_transfer_params={"do_remote_decode": False},
1827 + )
1828 +
1829 def test_adaptive_pins_nothing_and_keeps_effort_ceiling(self):
1830 """`adaptive` lets the model choose depth, so only the ceiling from
1831 output_config.effort should survive."""
vllm/entrypoints/anthropic/protocol.py
+4
@@ -233,6 +233,10 @@ class AnthropicMessagesRequest(BaseModel):
233
234 @model_validator(mode="after")
235 def validate_thinking_budget(self) -> "AnthropicMessagesRequest":
236 + # P/D prefill legs are sent with max_tokens=1 and never decode; the
237 + # decode leg carries the client's max_tokens and is still checked.
238 + if self.kv_transfer_params and self.kv_transfer_params.get("do_remote_decode"):
239 + return self
240 if (
241 isinstance(self.thinking, AnthropicThinkingConfigEnabled)
242 and self.thinking.budget_tokens >= self.max_tokens