Repository navigation
fix(claude): resolve web_search tool_choice and invalid reasoning summary when routing Claude Desktop to OpenAI models #1426
Copy link
Copy link
Closed
Labels
providerProvider adapters, OpenAI-compat presets, upstream API quirksProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportsProvider compatibility reports
Description
Client or integration
Other
Provider or upstream service
OpenAI (Codex login / Responses API)
OpenCodex version
2.7.38
Endpoint or capability
/v1/responses (Claude Desktop Messages -> Responses translation)
Current behaviour
When routing Claude Desktop requests to OpenAI upstream models (gpt-5.6-luna, gpt-5.4-mini):
- Turns with disabled thinking (
thinking: { type: "disabled" }) setreasoning: { effort: "none", summary: "none" }. OpenAI rejectssummary: "none"withHTTP 400 invalid_request_error: Invalid value: 'none'. Supported values are: 'concise', 'detailed', and 'auto'. - Enforced
web_searchtool choice (tool_choice: { type: "tool", name: "web_search" }) setstool_choice: { type: "function", name: "web_search" }whiletoolsarray contains{ type: "web_search" }. OpenAI rejects withHTTP 400 invalid_request_error: Tool choice 'function' not found in 'tools' parameter.
Expected behaviour
- Explicitly disabled thinking in
inbound.tsshould setreasoning: { effort: "none" }without emitting invalidsummary: "none". - Hosted
web_searchtool choice should map to{ type: "web_search" }instead of{ type: "function", name: "web_search" }. - Unmatched function tool choices should be sanitized or downgraded to
"auto"inopenai-responses.tsbefore upstream dispatch.
Minimal redacted request or reproduction
// Inbound Anthropic request from Claude Desktop on WebSearch:
{
"model": "gpt-5.6-luna",
"thinking": { "type": "disabled" },
"tools": [{ "name": "web_search", "type": "web_search" }],
"tool_choice": { "type": "tool", "name": "web_search" }
}Actual response or error
HTTP 400 Bad Request
{
"error": {
"type": "invalid_request_error",
"message": "Invalid value: 'none'. Supported values are: 'concise', 'detailed', and 'auto'."
}
}
// and subsequently:
{
"error": {
"type": "invalid_request_error",
"message": "Tool choice 'function' not found in 'tools' parameter."
}
}Upstream documentation
https://docs.anthropic.com/en/api/messages
Suggested mapping or implementation notes
In src/claude/inbound.ts:
- Remove
summary: "none"frombody.reasoningwhenthinkingDisabledis true. - Use
isClaudeWebSearchToolName(choice.name)intoolChoiceToResponsesto maptool_choiceto{ type: "web_search" }when target is a hosted web_search tool.
In src/responses/schema.ts:
- Add
"web_search"tohostedToolTypeenum.
In src/adapters/openai-responses.ts:
- Add
stripInvalidReasoningSummaryto strip invalidsummaryvalues (like"none"). - Add
sanitizeUnmatchedToolChoiceto sanitize function tool choices that don't match any function declared intools.
Additional context and attachments
Verified fix locally on Windows with Claude Desktop 3P mode.
Checks
- I searched existing provider and compatibility issues.
- The request and response were redacted.
- The expected behaviour is based on an upstream specification or a concrete client requirement.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
providerProvider adapters, OpenAI-compat presets, upstream API quirksProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportsProvider compatibility reports
Activity
Ingwannu commentedon Aug 10, 2026
Confirmed on current
dev(08e7e0fda): this is a real Claude Messages to Responses translation bug, not only a 2.7.38 report.The current translator emits
reasoning: { effort: "none", summary: "none" }for explicit disabled thinking even though the OpenAI Responses endpoint rejectssummary: "none". It also translates every Anthropic named tool choice into a function choice, while the same request translates a Claude hosted web-search declaration into{ type: "web_search" }; the choice and declaration therefore cannot match. The request schema also does not currently admit{ type: "web_search" }as a hosted choice.I will make the narrow protocol fix:
{ effort: "none" }without the invalid summary value;{ type: "web_search" };web_searchto the hosted Responses tool-choice schema;responsesRequestSchemaand the realparseRequestboundary while preserving ordinary named function choices.I will not generically downgrade an unmatched forced function choice to
auto: that would silently relax the caller's required-tool intent and could select a different tool. Other mismatches should remain fail-closed unless a separate, evidence-backed mapping exists. I will link the draft PR and exact verification here after the focused fix is pushed.Ingwannu commentedon Aug 10, 2026
Implemented in draft PR #1428: #1428
The current-
devfix removes the invalidreasoning.summary: "none", preserves explicit disabled thinking aseffort: "none", and maps a forced Claude WebSearch/web_search choice to the hosted Responses{ type: "web_search" }declaration. Ordinary named function choices remain unchanged; arbitrary mismatches are not silently weakened toauto.Verification: 28 focused inbound tests passed, including both
responsesRequestSchemaand realparseRequestboundaries; typecheck, privacy scan, the 221-page docs build, and diff checks also passed. Leaving the issue open until exact-head CI and independent review complete and the PR is integrated intodev.Wibias commentedon Aug 11, 2026
Fixed by #1428