Codex requests routed from /responses to a /chat/completions upstream fail as soon as the input history contains a tools-on-demand additional_tools item. This also breaks automatic approval review: the reviewer request fails before an approval decision can be made.
Observed error:
Automatic approval review failed: {"type":"error","status":400,"error":{"type":"invalid_request_error","code":"invalid_request_error","message":"Invalid input item type 'additional_tools'."}}
Reproduction
Configure a model whose Responses requests are translated to a Chat Completions upstream, then send this minimal body to the Responses endpoint:
{
"model": "<configured-chat-completions-model>",
"input": [
{ "role": "user", "content": "Use lookup if needed." },
{
"type": "additional_tools",
"role": "developer",
"tools": [
{ "type": "function", "name": "lookup", "parameters": { "type": "object", "properties": {} } }
]
}
]
}
Expected: the supported function tool is available to the Chat Completions model and the request proceeds.
Actual: Floway returns Invalid input item type 'additional_tools'.
Cause
The protocol models additional_tools, but the Responses → Chat Completions request translator does not consume it before processing conversation items. It reaches the unsupported-item branch and throws. This is still present in upstream main at 14f0b7725da737a96a82d2e9daf8cd10dc0583e1:
Proposed temporary fix
Before tool validation and message conversion:
- Append tools from every
additional_tools input item to the request-level tools, preserving the initial tools and declaration order.
- Remove those declaration items from the conversation input.
- Pass the combined tools through the existing validation and tool translation, including custom-tool wrapping and response mapping.
This deliberately trades cache reuse for compatibility. Promoting newly introduced tools to the request-level tool list changes the prompt prefix and can cause cache misses, increasing latency and, on providers with cached-input pricing, cost. It also exposes the combined tool set at request scope rather than preserving the original point of introduction. This is a temporary compatibility fallback, not a complete implementation of deferred-tool semantics.
A native Responses route remains useful when the upstream supports the needed semantics. Chat Completions compatibility is still needed for existing inference deployments; the motivating discussion included a modified SGLang deployment for older GPUs whose available interface was Chat Completions. That is deployment context, not a claim about current upstream SGLang support.
Reference implementation and validation
The minimal fallback is implemented in the yyyr-p fork:
yyyr-p@bbf0623
- Six added regression cases fail against the pre-fix implementation and pass with the fix.
- Coverage includes absent/null/empty initial tools, multiple additions, existing-tool preservation, custom-tool mapping, uninterrupted tool-call history, source immutability, and validation of hoisted tools.
- All 587 translation tests passed on that fork revision; lint, installer checks, and the web build also passed.
- The full repository was not green: seven unrelated tests also failed on the pre-fix baseline, and an existing Web type error remained.
Longer-term discussion
Related: #17, which tracks the broader hosted/deferred-tool translation gap.
One alternative discussed was a stable dispatcher tool: keep its declaration fixed, represent dynamically available tool definitions in conversation context, and translate dispatcher calls/results to the original tools. This may preserve more prefix-cache reuse, but requires a deliberate protocol bridge and evaluation of tool selection, argument schemas, names, custom tools, and history round-tripping. It has not been implemented or validated by the temporary fix above.
The immediate request is to unblock supported tools carried by additional_tools on the Chat Completions translation path, with the cache tradeoff made explicit. Full tool_search/namespace/deferred-tool support can remain a separate design discussion under #17.
Codex requests routed from
/responsesto a/chat/completionsupstream fail as soon as the input history contains a tools-on-demandadditional_toolsitem. This also breaks automatic approval review: the reviewer request fails before an approval decision can be made.Observed error:
Reproduction
Configure a model whose Responses requests are translated to a Chat Completions upstream, then send this minimal body to the Responses endpoint:
{ "model": "<configured-chat-completions-model>", "input": [ { "role": "user", "content": "Use lookup if needed." }, { "type": "additional_tools", "role": "developer", "tools": [ { "type": "function", "name": "lookup", "parameters": { "type": "object", "properties": {} } } ] } ] }Expected: the supported function tool is available to the Chat Completions model and the request proceeds.
Actual: Floway returns
Invalid input item type 'additional_tools'.Cause
The protocol models
additional_tools, but the Responses → Chat Completions request translator does not consume it before processing conversation items. It reaches the unsupported-item branch and throws. This is still present in upstream main at14f0b7725da737a96a82d2e9daf8cd10dc0583e1:Proposed temporary fix
Before tool validation and message conversion:
additional_toolsinput item to the request-leveltools, preserving the initial tools and declaration order.This deliberately trades cache reuse for compatibility. Promoting newly introduced tools to the request-level tool list changes the prompt prefix and can cause cache misses, increasing latency and, on providers with cached-input pricing, cost. It also exposes the combined tool set at request scope rather than preserving the original point of introduction. This is a temporary compatibility fallback, not a complete implementation of deferred-tool semantics.
A native Responses route remains useful when the upstream supports the needed semantics. Chat Completions compatibility is still needed for existing inference deployments; the motivating discussion included a modified SGLang deployment for older GPUs whose available interface was Chat Completions. That is deployment context, not a claim about current upstream SGLang support.
Reference implementation and validation
The minimal fallback is implemented in the yyyr-p fork:
yyyr-p@bbf0623
Longer-term discussion
Related: #17, which tracks the broader hosted/deferred-tool translation gap.
One alternative discussed was a stable dispatcher tool: keep its declaration fixed, represent dynamically available tool definitions in conversation context, and translate dispatcher calls/results to the original tools. This may preserve more prefix-cache reuse, but requires a deliberate protocol bridge and evaluation of tool selection, argument schemas, names, custom tools, and history round-tripping. It has not been implemented or validated by the temporary fix above.
The immediate request is to unblock supported tools carried by
additional_toolson the Chat Completions translation path, with the cache tradeoff made explicit. Fulltool_search/namespace/deferred-tool support can remain a separate design discussion under #17.