Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Bug] Responses combo treats completed text as success despite tool_choice=required (NVIDIA target)

Open
#7,456 8 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Ingwannu is already working on this.

Since Oct 21, 2026.

  • #7463 by @Ingwannu — open

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
30/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript

Research direction

Start with src/server/responses/core-combo.ts and src/server/responses/combo-stream-preflight.ts, then trace how the Responses request's required tool choice reaches the upstream adapter and how completed child responses are validated. Add isolated tests for required calls, zero-call completions, safe retries before output, and committed streaming output, including the 151-tool and continuation cases. Done means a completed response with no required function call is never accepted as a successful tool round, while streaming is not replayed after commitment.

Written by the indexing model from the issue text.

Description

bug tools
Client or integration

Direct HTTP/API client. Also affects Codex CLI when its RHODIZ combo selects the NVIDIA target.

Area

Proxy and routing; Streaming; Tools / MCP / web search.

Summary

A Responses request with a declared function and tool_choice: "required" can return HTTP 200, status: "completed" but zero function_call items when the selected target is NVIDIA Nemotron Ultra. The combo accepts that response as a successful target outcome, instead of identifying that the required-tool contract was unsatisfied. Consequently a Codex tool round-trip may make no progress, despite the client seeing a successful completion.

This differs from the existing issues about forwarding tool-choice settings on the Chat Completions path (e.g. #5211) and DeepSeek rejecting forced choices (#4631). This is a successful-but-semantically-invalid Responses result that a combo marks terminal-success.

Reproduction

Use a separately authorized OpenCodex instance with a configured NVIDIA provider; credential details are not needed in the report.

{
  "model": "nvidia/nvidia/nemotron-3-ultra-550b-a55b",
  "input": [
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "Call get_fixture_marker with key=status. Do not answer with text before the tool result."
        }
      ]
    }
  ],
  "tools": [
    {
      "type": "function",
      "name": "get_fixture_marker",
      "description": "Return a fixed test value",
      "parameters": {
        "type": "object",
        "properties": { "key": { "type": "string" } },
        "required": ["key"],
        "additionalProperties": false
      }
    }
  ],
  "tool_choice": "required",
  "store": false,
  "stream": false,
  "max_output_tokens": 750
}

Observed against the installed OpenCodex 2.89.0:

Route HTTP Response status Output item types Required function?
NVIDIA direct 200 completed reasoning, message No (0 calls)
GPT-6.1 Sol direct 200 completed function_call Yes (1 call)
Claude Opus 5.5 direct 200 completed function_call Yes (1 call)

With the exact same one-function request sent to the 11-target combo alias RHODIZ, the combo selected NVIDIA and returned completed without a function call. This reproduced 2/2 times. A separate 151-declared-function test reproduced the same outcome via the combo, whereas the GPT-6.1 Sol route completed the required function call and the subsequent function_call_output continuation 2/2 times.

An earlier 25-turn text-response stress test with 127/128/129/151 declared (but unused) tools had 25/25 HTTP 200 success. That test did not establish actual tool-call correctness: a real Codex CLI read-tool test subsequently showed intermittent failures on the combo (1/5 passes in one batch) versus GPT-6.1 Sol direct (5/5). This comparison is corroborating context, not proof of which exact model served every failed Codex CLI turn.

Version

@bitkyc08/opencodex 2.89.0, Codex CLI 0.163.0.

Operating system

Linux, x86_64 (VM; distribution not independently verified).

Provider and model

NVIDIA / nvidia/nemotron-3-ultra-550b-a55b; controls: openai/gpt-6.1-sol and anthropic/claude-opus-5-5.

Logs or error output

In src/server/responses/core-combo.ts, the combo returns a child immediately when response.ok after its stream preflight and success bookkeeping. The existing preflight in src/server/responses/combo-stream-preflight.ts detects certain retryable zero-output terminals, but does not enforce the caller's required-function selection contract for a completed 200 response. The upstream adapter may be disregarding required; the proxy currently does not detect that and makes the misbehavior a successful combo result.

See the same-issue streaming follow-up comment for per-event SSE counts. No raw user prompts or access logs are included.

Screenshots and supporting files

A minimal synthetic JSON reproducer and comparative results are embedded above. The follow-up comment documents streaming response.completed with zero calls and the isolated test counts. No sensitive attachments.

Redacted configuration
{
  "combos": {
    "rhodiz-coding-primary": {
      "alias": "RHODIZ",
      "strategy": "failover",
      "targets": [
        {"provider": "nvidia", "model": "nvidia/nemotron-3-ultra-550b-a55b"},
        {"provider": "openai", "model": "gpt-6.1-sol"},
        {"provider": "anthropic", "model": "claude-opus-5-5"}
      ]
    }
  }
}

The snippet is illustrative: the actual 11-target combo contains additional routes, whose details do not affect the minimal required-function reproduction.

Expected behavior / proposed acceptance
  1. Preserve explicit tool_choice: "required" or a named mandatory tool at the upstream adapter boundary, and verify the upstream wire really supports it.
  2. For a fully buffered, successful non-streaming Responses child, a completed response with zero required function_call items must not be reported as a valid completed tool round. Either safely select an eligible alternative before any output/effects, or return a typed compatibility error rather than a false success.
  3. Streaming handling must remain conservative: never replay or hop after client-visible output, a tool side effect, or ambiguous commitment. Do not turn every text-only 200 into a retry. Handle only requests explicitly requiring a tool and only if it is provably safe.
  4. Preserve complete tool catalogs (including 151 tools), tool call IDs, function_call_output continuation, caller model identity, authorization boundaries, and cancellation.
  5. Add isolated positive/negative tests for direct and combo paths, no output vs. committed output, one required tool and 151 declared tools. A passing end-to-end sequence is: request with required → exactly one declared function call → caller-provided function result → completed answer using that result.
Privacy and provenance

Reported by the affected operator via their connected GitHub account. Examples use synthetic markers only; no account IDs, internal addresses, tokens, raw user prompts, or private logs are attached. The production installation has not been modified as part of this upstream report.

Checks
  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.
Dominant language
TypeScript
Stars
16.9k
Forks
1.3k
Avg merge
7h 46m
Merged PRs (30d)
638

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lidge-jun/opencodex

All issues in lidge-jun/opencodex

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.