Repository navigation
Chat Completions allowed_tools tool_choice takes one object, not a list - #43
Merged
Merged
Conversation
The Chat Completions API defines tool_choice {"type": "allowed_tools"} with a
single allowed_tools object ({mode, tools}). The type modelled it as a list, so
a request in OpenAI's shape failed to deserialize, and the list shape this type
did accept was serialized to OpenAI, which rejects it with 400
"Missing required parameter: 'tool_choice.function'".
…ools-object # Conflicts: # async-openai/tests/ser_de.rs
lukekim
approved these changes
Oct 9, 2026
There was a problem hiding this comment.
🟢 Approved
The focused schema correction matches the documented API and is adequately covered by regression tests.
0 open findings
What changed in this PR
Corrects Chat Completions allowed_tools serialization to match the OpenAI API schema.
Changes:
- Replaces the erroneous list field with one
ChatCompletionAllowedToolsobject. - Removes the invalid
Defaultimplementation. - Adds round-trip and legacy-shape rejection tests.
| File | Description |
|---|---|
async-openai/src/types/chat/chat_.rs |
Corrects the allowed_tools field type and documentation. |
async-openai/tests/ser_de.rs |
Verifies valid object serialization and rejects the former list shape. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
krinart
added a commit
to spiceai/spiceai
that referenced
this pull request
Oct 10, 2026
…istory, MCP tools/call errors (fixes #14910) - tool_choice `allowed_tools` takes OpenAI's single object; async-openai is pinned at the merge of spiceai/async-openai#43. - /v1/evaluate: every non-200 response marks its `ai_evaluate` task failed; every invalid request is a 400 `{"error"}` (415 for a non-JSON body); the question rules apply to every model; responses name the Spicepod model; error bodies name the model and the kind of failure. - mistral.rs: a tool_choice naming a tool the request does not list is a 400. - Provider errors keep their status: `ApiErrorKind` reads `code`, then `type`, for /v1/chat/completions and the chat evaluator alike. - MCP tools/call: an unknown tool is -32602 naming it; a tool that fails returns a result with `isError: true`. - A completed chat stream ends with `data: [DONE]`; the Responses API load warning states its fix once.
wangyusheng1985
pushed a commit
to wangyusheng1985/spiceai
that referenced
this pull request
Oct 15, 2026
…esponse model (fixes spiceai#14910) (spiceai#14977) * fix(models, mcp): allowed_tools shape, /v1/evaluate errors and task history, MCP tools/call errors (fixes spiceai#14910) - tool_choice `allowed_tools` takes OpenAI's single object; async-openai is pinned at the merge of spiceai/async-openai#43. - /v1/evaluate: every non-200 response marks its `ai_evaluate` task failed; every invalid request is a 400 `{"error"}` (415 for a non-JSON body); the question rules apply to every model; responses name the Spicepod model; error bodies name the model and the kind of failure. - mistral.rs: a tool_choice naming a tool the request does not list is a 400. - Provider errors keep their status: `ApiErrorKind` reads `code`, then `type`, for /v1/chat/completions and the chat evaluator alike. - MCP tools/call: an unknown tool is -32602 naming it; a tool that fails returns a result with `isError: true`. - A completed chat stream ends with `data: [DONE]`; the Responses API load warning states its fix once. * docs(evaluate): state which /v1/evaluate failures reach task history, and that a model that failed to load is a 404 A body the handler cannot read is refused before the `ai_evaluate` task starts, so it leaves no row (as on /v1/chat/completions); every other non-200 response records an error_message. A configured model that failed to load answers 404 as an undefined one does.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Chat Completions API defines
tool_choice: {"type": "allowed_tools", "allowed_tools": {"mode", "tools"}}with a singleallowed_toolsobject (ChatCompletionAllowedToolsChoiceinopenapi.documented.yml).ChatCompletionAllowedToolsChoice.allowed_toolswas aVec, so:Missing required parameter: 'tool_choice.function'.allowed_toolsis nowChatCompletionAllowedTools.Defaultis dropped from the choice, sinceChatCompletionAllowedToolshas no meaningful default mode.Test:
tests/ser_de.rs::allowed_tools_tool_choice_round_trips_in_the_chat_completions_shapedeserializes OpenAI's shape, checks it serializes back unchanged, and checks the list shape is rejected. It does not compile against the old field type.Found in spiceai/spiceai#14910.