Repository navigation
[Feature]: extend the no-tool-call terminal continuation guard beyond the anthropic adapter (openai-chat routed models stop early) #1651
Description
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-chatprovider. - 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_filetool available. - Occasionally the model emits a short "I'll check that for you" message,
finish_reason: stop, and notool_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 extendsterminalGuardEnabledand the analysis branch to thoseopenai-chatrouted models; or - Enable the guard for
openai-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 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
coderabbitai commentedon Aug 14, 2026
🔗 Related PRs
#304 - fix(kiro): restore hardening and complete text turns [open]
#394 - fix(anthropic): guard premature no-tool completions [merged]
#419 - [WRONG BRANCH] Local/stable [open]
#757 - feat: route GPT-5.6 Pro through standard ChatGPT [open]
#793 - fix(openai-chat): complete streams that end after output without terminal [merged]
#1468 - fix(openai-chat): tolerate null tool-call padding [merged]
#1531 - fix(openai-chat): refuse to emit an unnamed streamed tool call [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
tone-leh commentedon Aug 14, 2026
Note for triage: this is distinct from #1531. #1531 makes a stream fail closed when a tool call is malformed/unnamed. This issue is the opposite direction: a model that legitimately produces no tool call while its turn is not actually finished is treated as done and the turn stops early.
The no-tool-call terminal continuation guard (from #394) is currently bound to the anthropic adapter only. openai-chat routed models (self-hosted GLM/Kimi-family gateways) hit the same premature-completion pattern but do not get the guard, so they stop mid-work. Requesting the guard be extended to the openai-chat path. No overlap with #1531's error-termination logic.
Ingwannu commentedon Aug 14, 2026
Confirmed as a real routing gap on the current code path. The existing terminal guard is Anthropic-only, so
openai-chatproviders cannot opt into the same bounded continuation even when a model exhibits the same announce-then-stop behavior.PR #1660 is the conservative direction I would accept: a provider-level
terminalContinuationGuardopt-in, one bounded continuation, and the existing combo/compaction exclusions preserved. It should not be enabled globally because the heuristic has not been calibrated across model families and languages. Keeping this issue open until #1660 is rebased onto currentdev, leaves draft, and passes exact-head review/CI.lidge-jun commentedon Aug 14, 2026
Closing: this is a design/enhancement proposal (opt-in provider terminal guard), not a bug fix. The current behavior is intentional — the terminal continuation guard is Anthropic-specific. Extending it to other providers requires per-provider opt-in design. Reopen as a feature request if needed.
lidge-jun commentedon Aug 14, 2026
Reopened — reclassification does not justify closing. Keeping open as a valid enhancement request.
feat(terminal-guard): opt-in no-tool-call continuation guard for open…
feat(terminal-guard): opt-in no-tool-call continuation guard for open…