Skip to content

[Feature]: extend the no-tool-call terminal continuation guard beyond the anthropic adapter (openai-chat routed models stop early) #1651

Description

@TooSpace

Client or integration

Codex App

Area

Proxy and routing

Summary

The bounded "no-tool-call terminal continuation" guard is hardwired to the anthropic adapter only. openai-chat-routed reasoning models that end a turn with a clean stop after announcing an action (e.g. "let me check X / found it, now extracting") — but without emitting the tool call — are treated as complete. Codex renders the turn as finished, and the user has to manually prompt "continue". This is the same class of premature-termination the anthropic guard already fixes, just on the chat adapter.

In practice GLM-5.2 (and combo children routing to it) hit this: the model narrates its plan, emits finish_reason: stop with no tool_calls, and the run stops early even though a tool call was clearly intended.

What I expected

The terminal guard's eligibility and analysis should be extendable to specific openai-chat routed models known to prematurely stop, not locked to adapterName === "anthropic". Either a provider/model opt-in, or applying the same analyzeTerminalTurn heuristic to openai-chat when a tool-call was announced-but-absent.

Evidence (code path)

src/server/responses/core.ts:

const terminalGuardEnabled = activeAdapter.name === "anthropic" && !options.comboAttempt && !routedCompaction;

src/server/responses/terminal-guard.ts:

const analysis = options.adapterName === "anthropic"
  ? analyzeTerminalTurn(parsed, seen)
  : { decision: "pass" as const };

Both gates are adapter-name equality checks against "anthropic". The continuation machinery (analyzeTerminalTurn, buildContinuationRequest, maxContinuations) is adapter-agnostic — only these two eligibility checks scope it to anthropic. A routed openai-chat model that exhibits the same "announce-then-stop-without-tool-call" pattern never gets the one bounded re-ask.

Reproduction

  1. Route GLM-5.2 through an openai-chat provider.
  2. Send an executable task where the model tends to narrate intent first (e.g. "check the contents of /etc/hosts and tell me what you find") with a read_file tool available.
  3. Occasionally the model emits a short "I'll check that for you" message, finish_reason: stop, and no tool_calls. The turn ends; no continuation is attempted.
  4. The same request against the anthropic adapter would get one bounded internal continuation.

Proposal (either is fine)

  1. Add a provider/model allowlist (e.g. provider.terminalGuardModels: string[]) that extends terminalGuardEnabled and the analysis branch to those openai-chat routed models; or
  2. Enable the guard for openai-chat generally when a tool was announced-but-absent, gated behind the same bounded single-continuation and short-reply constraints the anthropic path uses, so normal long answers and plan-only turns are unaffected.

Version

opencodex 2.14.2 (ocx --version); running local service confirmed via GET /healthz.

Operating system

macOS 26.5.1 (25F80)

Provider and model

GLM-5.2 routed through an openai-chat OpenAI-compatible gateway, and a failover combo whose children route to it. Reproducible with any openai-chat reasoning model that ends turns by narrating an intended tool call without emitting it.

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

    bugSomething isn't workingproxyHTTP proxy, routing, reverse-proxy / management authtoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions