Skip to content

Provider API /v1/responses rejects Codex's tool_search_call / tool_search_output input items with 400 "Invalid input" #893

Description

@fenton-xue

Summary

POST /provider/v1/responses returns HTTP 400 {"error":{"message":"Invalid input","type":"invalid_request_error","param":"input"}} for any request whose input array contains a tool_search_call or tool_search_output item.

Codex emits these items natively on the Responses wire (wire_api = "responses"), so every turn in which the model performs a tool search is killed before the model runs, and the task ends as a system error. On deepseek/deepseek-v4.1-flash this makes every MCP / plugin tool unusable: Codex defers MCP tools (js, js_reset, ...) behind a tool search, so the first time the agent reaches for Chrome or Computer Use the conversation history gains a tool_search_call/tool_search_output pair and the next request 400s.

Expected Behavior

The endpoint should accept tool_search_call / tool_search_output input items, or at minimum accept the request and ignore them. They are client-executed history items, the same class as function_call / function_call_output, which the endpoint already accepts today.

Actual Behavior

The whole request is rejected with 400 before any model output. Body is 84 bytes:

{"error":{"message":"Invalid input","type":"invalid_request_error","param":"input"}}

Steps to reproduce the issue

Baseline (200 OK):

curl -sS https://api.commandcode.ai/provider/v1/responses \
  -H "Authorization: Bearer $CMDCODE_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "model": "deepseek/deepseek-v4.1-flash",
    "stream": false,
    "max_output_tokens": 16,
    "input": [{"role":"user","content":[{"type":"input_text","text":"hi"}]}]
  }'

Now append one tool_search_call item to input:

"input": [
  {"role":"user","content":[{"type":"input_text","text":"hi"}]},
  {"type":"tool_search_call","call_id":"call_x1","status":"completed","execution":"client","arguments":{"query":"cua"}}
]

Result: HTTP 400, the 84-byte body above.

Same with tool_search_output:

{"type":"tool_search_output","call_id":"call_x1","status":"completed","execution":"client","tools":[]}

Result: HTTP 400, same body.

Matrix measured against https://api.commandcode.ai/provider/v1/responses with model deepseek/deepseek-v4.1-flash:

input contents result
plain user message 200
+ tool_search_call (full fields) 400
+ tool_search_call, minimal fields (type/call_id/arguments), no tools array on the request 400
+ tool_search_call, arguments as a JSON string instead of an object 400
+ tool_search_output, tools: [] 400
+ tool_search_output, one real function tool in tools 400
+ function_call and function_call_output 200

The trigger is the item type itself, not a missing or extra field.

Real-world impact (Codex Desktop 0.155.0-alpha.9.2, macOS, zsh)

Turn 01a0bcca-9210-7650-bc44-862ddf3a9baf:

  1. The user asks the agent to drive Chrome. The agent's js / js_reset calls start coming back as unsupported call: js (the mcp__cua_repl namespace is missing from the emitted calls).
  2. The model then issues one tool search (arguments: {"query": "cua_repl javascript execution browser control"}) and Codex writes a tool_search_call + tool_search_output pair into the conversation history.
  3. The next request 400s and the turn ends as:
{"type":"task_complete","error":{"message":"{\"error\":{\"message\":\"Invalid input\",\"type\":\"invalid_request_error\",\"param\":\"input\"}}","codex_error_info":"other"}}

A parallel thread on the same provider that never triggered a tool search ran to completion, matching the repro above.

Command Code Version

Provider API (gateway), server-side. Client: Codex Desktop 0.155.0-alpha.9.2, wire_api = "responses", base_url = https://api.commandcode.ai/provider/v1, model deepseek/deepseek-v4.1-flash.

Operating System

macOS

Terminal/IDE

Codex Desktop

Shell

zsh

Session file (optional)

No response

Fix prompt (optional)

POST /provider/v1/responses in the Provider API gateway rejects any request whose input array contains a tool_search_call or tool_search_output item, returning 400 {"error":{"message":"Invalid input","param":"input"}}. The endpoint already accepts function_call / function_call_output items, so extend the same history-item handling to tool_search_call / tool_search_output: parse them as client-executed history items and either carry them through the upstream translation or drop them, instead of failing request validation.

Reproduce: POST a request with a plain user message -> 200; append one tool_search_call item -> 400. Exact bodies are in the issue.

Check: both item types return a normal completion, and a Codex turn that performs a tool search no longer dies with param: "input".

Additional context

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions