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
- Route GLM-5.2 through an
openai-chat provider.
- 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.
- 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.
- The same request against the anthropic adapter would get one bounded internal continuation.
Proposal (either is fine)
- Add a provider/model allowlist (e.g.
provider.terminalGuardModels: string[]) that extends terminalGuardEnabled and the analysis branch to those openai-chat routed models; or
- 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.
Client or integration
Codex App
Area
Proxy and routing
Summary
The bounded "no-tool-call terminal continuation" guard is hardwired to the
anthropicadapter only.openai-chat-routed reasoning models that end a turn with a cleanstopafter 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: stopwith notool_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-chatrouted models known to prematurely stop, not locked toadapterName === "anthropic". Either a provider/model opt-in, or applying the sameanalyzeTerminalTurnheuristic toopenai-chatwhen a tool-call was announced-but-absent.Evidence (code path)
src/server/responses/core.ts:src/server/responses/terminal-guard.ts: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 routedopenai-chatmodel that exhibits the same "announce-then-stop-without-tool-call" pattern never gets the one bounded re-ask.Reproduction
openai-chatprovider.read_filetool available.finish_reason: stop, and notool_calls. The turn ends; no continuation is attempted.Proposal (either is fine)
provider.terminalGuardModels: string[]) that extendsterminalGuardEnabledand the analysis branch to thoseopenai-chatrouted models; oropenai-chatgenerally 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 viaGET /healthz.Operating system
macOS 26.5.1 (25F80)
Provider and model
GLM-5.2 routed through an
openai-chatOpenAI-compatible gateway, and a failover combo whose children route to it. Reproducible with anyopenai-chatreasoning model that ends turns by narrating an intended tool call without emitting it.