Summary
With a real Qwen3.5 server, forced tool choice can return a synthetic tool call with {} arguments even when the selected tool's JSON schema requires fields. The response says finish_reason: "tool_calls", so clients may execute a call that Rapid-MLX already knows is invalid.
Environment
- Local wheel built from
main at 93981cf4 (package version 0.11.0)
- Qwen3.5-4B
- Tested both streaming and non-streaming chat completions
Reproduction
Provide one tool:
{
"name": "add",
"parameters": {
"type": "object",
"properties": {
"a": {"type": "integer"},
"b": {"type": "integer"}
},
"required": ["a", "b"]
}
}
Prompt: Call add with a=7 and b=8.
Send the request with tool_choice: "required".
Actual behavior
Both streaming and non-streaming responses returned:
{
"finish_reason": "tool_calls",
"tool_calls": [{"function": {"name": "add", "arguments": "{}"}}]
}
The server log shows that parsing produced no tool call and the required-tool fallback synthesized one:
SSE-FORCED-SYNTH ... synthesizing terminal call
tool_choice='required' ... produced no tool_calls; synthesising ...
As a control, the same prompt and schema with tool_choice: "auto" produced the correct {"a":7,"b":8} arguments.
Expected behavior
Rapid-MLX should never report a successful forced tool call whose arguments fail the supplied schema. It should either recover/generate valid arguments (ideally through the constrained path) or fail explicitly so the client cannot mistake the result for an executable tool call.
Summary
With a real Qwen3.5 server, forced tool choice can return a synthetic tool call with
{}arguments even when the selected tool's JSON schema requires fields. The response saysfinish_reason: "tool_calls", so clients may execute a call that Rapid-MLX already knows is invalid.Environment
mainat93981cf4(package version0.11.0)Reproduction
Provide one tool:
{ "name": "add", "parameters": { "type": "object", "properties": { "a": {"type": "integer"}, "b": {"type": "integer"} }, "required": ["a", "b"] } }Prompt:
Call add with a=7 and b=8.Send the request with
tool_choice: "required".Actual behavior
Both streaming and non-streaming responses returned:
{ "finish_reason": "tool_calls", "tool_calls": [{"function": {"name": "add", "arguments": "{}"}}] }The server log shows that parsing produced no tool call and the required-tool fallback synthesized one:
As a control, the same prompt and schema with
tool_choice: "auto"produced the correct{"a":7,"b":8}arguments.Expected behavior
Rapid-MLX should never report a successful forced tool call whose arguments fail the supplied schema. It should either recover/generate valid arguments (ideally through the constrained path) or fail explicitly so the client cannot mistake the result for an executable tool call.