Skip to content

[Bug] Kiro Final answer rendered twice when the model ends with plain text instead of codex_kiro_final_answer #6270

Closed

Description

@twinn1013

Client or integration

Claude Code

Area

CLI

Summary

Version: 2.71.0, Claude Code 2.1.285, model claude-opus-5.5 via Kiro

What happens
In tool-enabled (completionMode "required") turns, when Kiro ends with plain text + END_TURN
and never calls codex_kiro_final_answer, the full answer is shown twice in Claude Code.
Reproduces across sessions.

Cause (from source)

  • stream.ts:809 flushes the held text to the client (emitRetained(deferred)).
  • stream.ts:876-885 then sets needsFallback for nativeCompletionStop.
  • adapter.ts:200-206 replays that text as commentary and appends KIRO_COMPLETION_RETRY_MESSAGE.
  • The model complies and calls codex_kiro_final_answer with the complete answer again,
    which is emitted as final_answer (stream.ts:814-821).
    Already-flushed first-attempt text cannot be retracted, so the answer appears twice.
    (Comment at stream.ts:1057-1060 / fix(kiro): treat pre-output stream socket closes as retryable #520 confirms the flush is intentional.)

Expected
The answer appears once.

Possible fixes

  • Keep holding the first attempt's text through the bounded fallback; if the fallback yields a
    completionAnswer, drop the held text (same as consumeSupersededByCompletion) instead of flushing it.
  • Or, when the replayed commentary already looks complete, have the retry prompt ask for a
    short/empty completion call rather than "the complete final answer".

Reproduction

  1. ocx running as the Claude Code gateway (ANTHROPIC_BASE_URL=http://127.0.0.1:10100), started via ocx claude.
  2. In Claude Code, select model ocx-claude-kiro--claude-opus-5.5[1m] (Kiro provider).
  3. Ask anything that makes the model use at least one tool, then answer in plain text
    (e.g. "check whether X exists and tell me where to put the files").
  4. Observe: the model ends with plain text + END_TURN and does not call codex_kiro_final_answer.
    The answer is shown, then an almost identical answer is shown again ("Thought for 13s" answer,
    followed by "Thought for 1s" answer).

Frequency: most tool-using turns that end with plain text; reproduces across separate sessions.
Observed live: right after a plain-text answer, the next model turn contains
KIRO_COMPLETION_RETRY_MESSAGE verbatim (kiro-constants.ts:35), so the bounded fallback fires every time.

Version

2.71.0 (also verified unchanged in 2.72.0)

Operating system

macOS 26.2 (25C56), Apple Silicon

Provider and model

kiro / claude-opus-5.5 (Claude Code model id: ocx-claude-kiro--claude-opus-5.5[1m])

Logs or error output

No error or stack trace — both sends return 200. Evidence is in the local usage log (~/.opencodex/usage.jsonl):

Kiro requests on this machine: 114 total, 11 with a second physical send.
Every one of those 11 has attempts[0].sendCount = 2 and recoveryKinds = ["empty-completion"],
which is the label kiro/adapter.ts:251 assigns to the bounded completion fallback send.

Recent examples (local time, requestId, sendCount, recoveryKinds, durationMs, outputTokens):
09-30 08:58:17  ocx-b5fff5fc9bec78dd9c4060f5e4774c15  2  ["empty-completion"]  46218  2198
09-30 09:01:47  ocx-a90c55c46f32dc6605af00dba05cd66b  2  ["empty-completion"]  28419  1419
09-30 09:03:13  ocx-08fef81997eb941afe29cabbbeac78e7  2  ["empty-completion"]  15139   718   <- matches the screenshot turn
09-30 09:07:01  ocx-23844856a1269a5ba69192c1d852ea99  2  ["empty-completion"]  43538  1609
09-30 09:10:35  ocx-cb9b743137e951c6ccdcbd01ff02525a  2  ["empty-completion"]  24309  1040

Requests without the fallback (sendCount = 1) render a single answer.
Model-side evidence: the turn following a plain-text answer receives KIRO_COMPLETION_RETRY_MESSAGE
(kiro-constants.ts:35) verbatim.

Screenshots and supporting files

Image

Redacted configuration

Claude Code settings.json: "model": "ocx-claude-kiro--claude-opus-5.5[1m]"
Env: ANTHROPIC_BASE_URL=http://127.0.0.1:10100, CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
No custom Kiro adapter config.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. lidge-jun commented on Sep 30, 2026

    @lidge-jun
    Owner

    Fixed by #6283, merged into dev as db6e266. Kiro now holds first-attempt prose through bounded validation and emits one final answer; validated retry tool calls release genuine progress before EOF. Focused regressions and typecheck passed. Per the updated owner instruction, Cross-platform CI is deferred to the final union run.

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 workingcliCLI, config inject, packaging flags

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions