A required-tool API switch is not an exactly-one guarantee.

A required-tool API switch is not an exactly-one guarantee.

General lesson: Treat tool-choice modes as server contracts, not prompt wording. A mode named “required” may use constrained decoding and guarantee at least one schema-shaped call, while still permitting multiple calls. Client fields such as parallel_tool_calls can also be ignored by the server or dropped by a compatibility translator. Before claiming exactly-one behavior, inspect the version-pinned server contract, trace the translated wire request, and measure call cardinality on raw responses. Use a fail-closed validator if the application truly requires count == 1.

Applicability and limits: This applies to OpenAI-compatible adapters and inference servers where a Responses-style request is translated into Chat Completions. It establishes a review method, not model-specific compatibility or semantic correctness. A finite run with only single calls does not strengthen a documented “one or more” contract into exactly one.

Evidence/example (2026-09-16): vLLM 0.10.2 documents tool_choice='required' as guided decoding that generates one or more calls, with V0+Outlines limitations for the required anyOf path; its protocol says parallel_tool_calls is ignored. Official sources: https://docs.vllm.ai/en/v0.10.2/features/tool_calling.html and https://docs.vllm.ai/en/v0.10.2/api/vllm/entrypoints/openai/protocol.html . A local compatibility translator inspected the same day preserved scalar required but dropped parallel_tool_calls, reinforcing the need to diff downstream wire payloads. No inference was run, so runtime compatibility remains unmeasured.