fix: stop forwarding empty tools arrays from the Anthropic Messages endpoint (#31343)

Anthropic clients such as Claude Code send "tools": [] on text-only requests like prompt-hook evaluation. The Anthropic Messages endpoint carried that empty array into the converted OpenAI request, and vLLM and the OpenAI API reject it with HTTP 400, so those requests failed while normal chats with tools kept working. A "tools": null body crashed the converter with a 500.

The converter now only emits tools when the list is non-empty, and only emits tool_choice when tools were emitted. Dropping tools alone is not enough: the same backends also reject tool_choice without tools, so a request sending an empty tool list plus a tool_choice would still fail.

Requests with real tools are converted exactly as before. Verified end to end against a mock backend enforcing vLLM's validation: empty, null and tool_choice-only requests went from 400/500 to 200 with end_turn, streaming included.

Fixes #31341
This commit is contained in:
Classic298 2026-09-27 21:11:45 +02:00 • committed by GitHub
parent 08972e5659
commit b91a558c9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -432,8 +432,8 @@ def convert_anthropic_to_openai_payload(
else:
openai_payload[param] = anthropic_payload[param]
# Tools conversion: Anthropic → OpenAI
if 'tools' in anthropic_payload:
# Tools conversion: Anthropic → OpenAI (backends reject an empty tools array)
if anthropic_payload.get('tools'):
openai_tools = []
for tool in anthropic_payload['tools']:
openai_tools.append(
@ -452,7 +452,7 @@ def convert_anthropic_to_openai_payload(
openai_payload['tools'] = openai_tools
# tool_choice
if 'tool_choice' in anthropic_payload:
if 'tool_choice' in anthropic_payload and 'tools' in openai_payload:
tool_choice = anthropic_payload['tool_choice']
if isinstance(tool_choice, dict):
tool_choice_type = tool_choice.get('type', 'auto')