Skip to content

copilot_chat: Serialize ToolChoice::Any as "required" instead of "any"#52015

Merged
benbrandt merged 3 commits intozed-industries:mainfrom
Vastargazing:fix/copilot-chat-tool-choice-clean
Mar 24, 2026
Merged

copilot_chat: Serialize ToolChoice::Any as "required" instead of "any"#52015
benbrandt merged 3 commits intozed-industries:mainfrom
Vastargazing:fix/copilot-chat-tool-choice-clean

Conversation

@Vastargazing
Copy link
Copy Markdown
Contributor

@Vastargazing Vastargazing commented Mar 20, 2026

Observed behavior: Inline assistant failed for GPT-4.1,
Gemini, and other non-Anthropic models. Claude worked correctly because
Anthropic's API accepts "any" as a valid value.

Fix

Renamed ToolChoice::AnyToolChoice::Required in both
copilot_chat.rs and responses.rs, matching the convention used by
other OpenAI-compatible providers (open_ai, lmstudio, open_router).

copilot_chat::ToolChoice is a wire type only for the /chat/completions
path — Anthropic models go through into_anthropic() and never touch it,
so no per-model logic is needed.

Also fixes the same serialization bug in responses::ToolChoice, which
was not covered by the original approach, and adds regression tests for
both.

Affected models

  • gpt-4.1 via copilot_chat provider
  • gemini-* via copilot_chat provider
  • Likely affects all OpenAI-compatible models routed through copilot_chat

Screenshots

Bug (only Claude works, Gemini and GPT-4.1 fail):
image

Fix:
image

Result: After the fix, all models work correctly via inline assistant.

Release Notes

  • Fix inline assistant 400 errors for GPT-4.1, Gemini, and other
    non-Anthropic models via the copilot_chat provider (tool_choice was
    sending "any" instead of "required")

… "required"

OpenAI API does not support tool_choice: "any". The correct value
is "required". This caused inline assistant to fail with 400 Bad Request
when using gpt-4.1 and other models via copilot_chat provider.

Fixes: tool_choice_not_supported error for gpt-4.1-2025-04-14
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Mar 20, 2026
@zed-codeowner-coordinator zed-codeowner-coordinator bot requested review from a team, benbrandt and mikayla-maki and removed request for a team March 20, 2026 13:39
@zed-community-bot zed-community-bot bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label Mar 20, 2026
@maxdeviant maxdeviant changed the title fix(copilot_chat): serialize ToolChoice::Any as "required" instead of "any" copilot_chat: Serialize ToolChoice::Any as "required" instead of "any" Mar 20, 2026
@zed-industries-bot
Copy link
Copy Markdown
Contributor

zed-industries-bot commented Mar 20, 2026

Warnings
⚠️

This PR is missing release notes.

Please add a "Release Notes" section that describes the change:

Release Notes:

- Added/Fixed/Improved ...

If your change is not user-facing, you can use "N/A" for the entry:

Release Notes:

- N/A

Generated by 🚫 dangerJS against 6f263a7

@SomeoneToIgnore SomeoneToIgnore added the area:ai Related to Agent Panel, Edit Prediction, Copilot, or other AI features label Mar 20, 2026
@benbrandt
Copy link
Copy Markdown
Member

Wouldn't this need to be per model then?

- Rename Any -> Required in copilot_chat.rs and responses.rs to match
  the OpenAI wire format explicitly (same as open_ai, lmstudio, open_router)
- Remove the serde(rename) workaround in favour of an accurate variant name
- Fix the same serialization bug in responses::ToolChoice, which was not
  touched by the original commit but uses the same rename_all = lowercase
- Update both match arms in the language_models copilot_chat provider
@Vastargazing
Copy link
Copy Markdown
Contributor Author

After looking at other OpenAI-compatible providers (open_ai, lmstudio, open_router) — they all use a Required variant instead of Any. copilot_chat::ToolChoice is a wire type only for the /chat/completions path; Anthropic models go through into_anthropic() and never touch it, so per-model logic isn't needed.

Updated the PR: renamed AnyRequired in both copilot_chat.rs and responses.rs (the latter had the same bug and wasn't covered by the original commit).

Also added regression tests for the serialization output.

@benbrandt
Copy link
Copy Markdown
Member

Right but copilot supports anthropic models as well, correct?

@Vastargazing
Copy link
Copy Markdown
Contributor Author

Yes, but Anthropic models are routed through a completely separate path. In stream_completion, the first check is model.supports_messages() — Anthropic models all have the /v1/messages endpoint and go through into_anthropic(), which uses anthropic::ToolChoice. That type serializes Any as "any" (with rename_all = "lowercase", tagged with type), which is exactly what Anthropic's API expects.

@benbrandt benbrandt enabled auto-merge (squash) March 24, 2026 13:14
@benbrandt benbrandt merged commit b0f2860 into zed-industries:main Mar 24, 2026
32 checks passed
@Vastargazing Vastargazing deleted the fix/copilot-chat-tool-choice-clean branch March 24, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ai Related to Agent Panel, Edit Prediction, Copilot, or other AI features cla-signed The user has signed the Contributor License Agreement first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants