Skip to content

[Bug][Kiro] Reporting input tokens in the client only contains the current turn amount, making the context always appear empty (100% remaining for Codex, underreported for Claude Code) #508

Closed

Description

@jhste102lab

Client or integration

Codex CLI

Area

Provider adapter

Summary

Kiro 라우팅 모델을 쓰면 클라이언트에 보고되는 input token 수가 현재 turn 분량만 담기고 누적 컨텍스트가 빠집니다. 결과적으로

  • Codex CLI: 컨텍스트 잔량이 계속 100%에 가깝게 표시됩니다. 실제로는 200k 토큰 이상 쌓인 상태인데도 model_context_window 332,500 대비 사용률이 median 0.03%로 보고됩니다.
  • Claude Code: 같은 원인으로 컨텍스트 사용량이 실제보다 훨씬 작게 보고됩니다(아래 수치 참조).

같은 세션에서 provider만 anthropic으로 바꾸면 정상 값이 나오므로, provider별 문제입니다.

이 상태의 실질적 영향은 표시 오류에 그치지 않습니다. Codex의 auto-compact는 보고된 토큰 수에 의존하므로(auto_compact_token_limit), 컨텍스트가 항상 비어 있는 것으로 보이면 compaction이 트리거되지 않고 업스트림에서 context-length 초과로 끊길 때까지 진행됩니다. 실제로 kiro-errors.ts에는 content_length_exceeds_threshold를 context_length_exceeded로 변환하는 처리가 이미 있는데, 클라이언트가 사전에 이를 회피할 수 있는 신호를 못 받습니다.

기대 동작: 클라이언트에 보고되는 input token은 요청에 실제로 실려간 전체 컨텍스트를 반영해야 합니다.

Reproduction

  1. provider kiro, model kiro/claude-opus-5로 Codex CLI 세션 실행
  2. 도구 호출을 여러 번 반복해 대화를 키움(수십 turn, 실제 payload 20만 토큰 이상)
  3. Codex의 컨텍스트 잔량 표시가 계속 100% 근처에 머무름
  4. 같은 세션에서 /model로 anthropic/claude-opus-5로 전환하면 즉시 정상 값(46% 사용 등)이 표시됨

측정 데이터 A — Codex rollout의 token_count 이벤트 (동일 세션, provider만 다름)

model 이벤트 수 model_context_window last_token_usage.input_tokens (median / max) 환산 사용률
anthropic/claude-opus-5 259 237,500 109,548 / 202,296 46.1% / 85.2%
kiro/claude-opus-5 300 332,500 98 / 5,328 0.03% / 1.6%

kiro 구간에서는 cached_input_tokens 합계도 0입니다(anthropic 구간은 3천만 이상).

측정 데이터 B — Claude Code 세션 transcript (~/.claude/projects/.../*.jsonl의 assistant message.usage)

세션 model assistant 메시지 수 effective input (median / max)
이전 세션 claude-opus-5 (native) 67 116,537 / 145,925
현재 세션 claude-ocx-kiro--claude-opus-5 121 739 / 59,868

현재 세션 transcript 파일은 이전 세션의 2배 이상 크기(800KB vs 356KB)인데 보고된 input은 median 739 토큰입니다. cache_read_input_tokens, cache_creation_input_tokens도 전 구간 0입니다.

측정 데이터 C — usage.jsonl 내부 불일치

kiro + Claude Code surface 200 응답 1,080건 중 1,079건에서 usage.totalTokens < usage.inputTokens입니다. 같은 행 안에 두 개의 서로 다른 추정치가 들어 있습니다.

logInput=311283  out=80   usage.total=363   -> 클라이언트가 보는 input ≈ 283
logInput=305581  out=78   usage.total=623   -> 클라이언트가 보는 input ≈ 545
logInput=227398  out=167  usage.total=349   -> 클라이언트가 보는 input ≈ 182

원인 추정 (설치된 2.7.40 소스 기준)

src/adapters/kiro.ts에 input token 추정 함수가 두 개 있습니다.

  • estimateKiroLogInputTokens() (L154) — parsed.context.messages 전체 + systemPrompt + tools. 이 값은 request.usageLog.inputTokens로 들어가 usage.jsonl 로깅에만 쓰입니다(L1138).
  • estimateKiroInputTokens() (L141) — currentTurnUsageMessages()(L104)가 마지막 assistant 메시지 이후만 잘라내고 assistant 역할을 제외합니다. systemPrompt/tools는 shouldCountStablePromptOverhead()(L137)가 previousResponseId가 없고 assistant 메시지가 하나도 없을 때만, 즉 첫 turn에서만 포함합니다. 이 값이 inputTokens로 반환되어(L1143) 스트림의 usage()(L563)를 거쳐 클라이언트에 보고됩니다.

즉 클라이언트가 보는 값은 의도적으로 "이번 turn 증분"이고, 누적 컨텍스트가 아닙니다. 과금 추정 관점에서는 (프롬프트 캐시가 있으면) 근사가 될 수 있지만, 컨텍스트 잔량 계산 용도로는 성립하지 않습니다.

또한 Kiro 스트림의 metadata 이벤트에는 contextUsagePercentage가 실려 옵니다. 현재 이 값은 debugProviderDiagnostic("kiro", "context_usage", ...)(L843)로 디버그 출력만 되고 클라이언트로 전달되지 않습니다. 업스트림이 이미 권위 있는 컨텍스트 사용률을 주고 있으므로 이를 활용할 여지가 있어 보입니다.

참고로 cursor adapter의 src/adapters/cursor/protobuf-events.ts:129 주석에 *"contextUsagePercentage SOT fix: absolute context and additive output must not..."*라는, 같은 계열 문제를 다룬 흔적이 있습니다. Kiro에는 동일한 정리가 적용되지 않은 것으로 보입니다.

제안

  1. 클라이언트에 보고하는 input token을 estimateKiroLogInputTokens()와 동일한 전체 컨텍스트 기준으로 맞춰 주세요. 증분 추정이 과금 목적으로 필요하다면 별도 필드로 분리하는 편이 안전합니다.
  2. 업스트림 metadata.contextUsagePercentage를 클라이언트 컨텍스트 표시의 SOT로 승격하는 방안을 검토해 주세요(cursor adapter와 동일한 방향).
  3. usage.totalTokens < usage.inputTokens가 같은 행에서 발생하는 현재 상태는 로그 소비자 입장에서도 해석이 불가능합니다.

Version

2.7.40

Operating system

macOS (Darwin 25.5.0)

Provider and model

kiro / claude-opus-5 (Claude Code에서는 claude-ocx-kiro--claude-opus-5)

Logs or error output

# Codex rollout: 동일 세션 내 provider별 token_count (last_token_usage)
# anthropic 구간
{"type":"token_count","info":{"last_token_usage":{"input_tokens":147170,
  "cached_input_tokens":142082,"output_tokens":180},"model_context_window":237500}}

# kiro 구간 — 실제 대화는 이보다 훨씬 큼
{"type":"token_count","info":{"last_token_usage":{"input_tokens":53,
  "cached_input_tokens":0,"output_tokens":124},"model_context_window":332500}}
{"type":"token_count","info":{"last_token_usage":{"input_tokens":89,
  "cached_input_tokens":0,"output_tokens":147},"model_context_window":332500}}

# Claude Code transcript: assistant message.usage (kiro 라우팅)
{"input_tokens":881,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,
 "output_tokens":632,"service_tier":"standard"}

# ~/.opencodex/usage.jsonl: 한 행 안의 두 추정치 불일치
{"provider":"kiro","surface":"claude","status":200,"usageStatus":"estimated",
 "usage":{"inputTokens":127828,"outputTokens":601,"totalTokens":729,"estimated":true},
 "totalTokens":128429}

Redacted configuration

{
  "port": 10100,
  "providerContextCaps": { "kiro": 350000 },
  "contextCapValue": 350000,
  "_catalog_kiro_entry": {
    "slug": "kiro/claude-opus-5",
    "context_window": 272000,
    "max_context_window": 272000,
    "auto_compact_token_limit": 244800,
    "effective_context_window_percent": 95
  },
  "_note": "kiro accounts: 1 (OAuth). auth material omitted."
}

codex 0.145.0

Checks

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

Original language: Korean

Client or integration

Codex CLI

Area

Provider adapter

Summary

When using the Kiro routing model, the number of input tokens reported to the client only contains the amount for the current turn, and the accumulated context is missing. As a result:

  • Codex CLI: The context remaining is continuously displayed close to 100%. In reality, it is stacked to more than 200k tokens, yet the usage rate is reported at a median of 0.03% compared to model_context_window 332,500.
  • Claude Code: For the same reason, the context usage is reported to be much smaller than it actually is (see figures below).

When the provider is changed to anthropic in the same session, normal values are returned, indicating a provider-specific issue.

The practical impact of this state goes beyond just display errors. Codex's auto-compact relies on the reported number of tokens (auto_compact_token_limit), so if the context appears to be always empty, compaction is not triggered and it continues until broken by exceeding context length upstream. In fact, kiro-errors.ts already has the process to convert content_length_exceeds_threshold to context_length_exceeded, but the client does not receive a signal to preempt this.

Expected behavior: The input tokens reported to the client should reflect the entire context actually provided with the request.

Reproduction

  1. Run a Codex CLI session with provider kiro, model kiro/claude-opus-5
  2. Repeat tool calls several times to engage in conversation (tens of turns, actual payload over 200k tokens)
  3. The context remaining display for Codex remains near 100%
  4. When switched to anthropic/claude-opus-5 in the same session via /model, it immediately shows normal values (e.g., 46% usage)

Measurement Data A — token_count events of Codex rollout (same session, only the provider differs)

model number of events model_context_window last_token_usage.input_tokens (median / max) conversion usage rate
anthropic/claude-opus-5 259 237,500 109,548 / 202,296 46.1% / 85.2%
kiro/claude-opus-5 300 332,500 98 / 5,328 0.03% / 1.6%

In the kiro range, the sum of cached_input_tokens is also 0 (over 30 million in the anthropic range).

Measurement Data B — Claude Code session transcript (~/.claude/projects/.../*.jsonl's assistant message.usage)

session model number of assistant messages effective input (median / max)
previous session claude-opus-5 (native) 67 116,537 / 145,925
current session claude-ocx-kiro--claude-opus-5 121 739 / 59,868

The current session transcript file is more than twice the size of the previous session (800KB vs 356KB), yet the reported input is a median of 739 tokens. cache_read_input_tokens, cache_creation_input_tokens are also 0 for the entire range.

Measurement Data C — Internal inconsistency in usage.jsonl

From 1,080 responses with kiro + Claude Code surface 200, 1,079 had usage.totalTokens < usage.inputTokens. There are two different estimates within the same row.

logInput=311283  out=80   usage.total=363   -> Input perceived by client ≈ 283
logInput=305581  out=78   usage.total=623   -> Input perceived by client ≈ 545
logInput=227398  out=167  usage.total=349   -> Input perceived by client ≈ 182

Cause Estimation (based on installed version 2.7.40)

There are two input token estimation functions in src/adapters/kiro.ts.

  • estimateKiroLogInputTokens() (L154) — total of parsed.context.messages + systemPrompt + tools. This value goes into request.usageLog.inputTokens and is only used for logging in usage.jsonl (L1138).
  • estimateKiroInputTokens() (L141) — currentTurnUsageMessages()(L104) only cuts off after the last assistant message and excludes the assistant role. systemPrompt/tools are only included in shouldCountStablePromptOverhead()(L137) when there is no previousResponseId and no assistant messages, that is, only included in the first turn. This value is returned as inputTokens (L1143) and goes through stream usage() (L563) to be reported to the client.

Thus, the value the client sees is intentionally "this turn increment" and not the accumulated context. From a billing estimation perspective (if there is a prompt cache), it might be an approximation, but it does not hold for context remaining calculations.

Additionally, the metadata events of the Kiro stream contain the contextUsagePercentage. Currently, this value is only debug output via debugProviderDiagnostic("kiro", "context_usage", ...)(L843) and is not relayed to the client. Since upstream is already providing authoritative context usage rates, there seems to be room for utilizing this.

For reference, a comment in src/adapters/cursor/protobuf-events.ts:129 of the cursor adapter mentions "contextUsagePercentage SOT fix: absolute context and additive output must not...", showing traces of dealing with the same category issue. It seems that the same organization has not been applied to Kiro.

Suggestions

  1. Please align the input tokens reported to the client with the overall context standard of estimateKiroLogInputTokens(). If incremental estimation is needed for billing purposes, it is safer to separate it into a different field.
  2. Consider promoting the upstream metadata.contextUsagePercentage to the client context display SOT (same direction as the cursor adapter).
  3. The current state of usage.totalTokens < usage.inputTokens occurring in the same row is incomprehensible also from the perspective of log consumers.

Activity

  1. changed the title [-][Bug][Kiro] 클라이언트 보고 input token이 현재 turn 분량만 담겨 컨텍스트가 항상 비어 보임 (Codex 100% 잔량, Claude Code 과소 보고)[/-] [+][Bug][Kiro] Reporting input tokens in the client only contains the current turn amount, making the context always appear empty (100% remaining for Codex, underreported for Claude Code)[/+] on Jul 26, 2026
  2. github-actions commented on Jul 26, 2026

    @github-actions
    Contributor
  3. jhste102lab commented on Jul 26, 2026

    @jhste102lab
    ContributorAuthor

    관련: #507 (같은 Kiro adapter의 429 처리 문제). 두 이슈는 원인이 다르지만 같은 세션 조사에서 함께 발견되었습니다.

  4. Wibias commented on Jul 26, 2026

    @Wibias
    Contributor

    Closing as fixed in v2.7.41 ( c517004). Please reopen with a fresh sample if context still looks empty after upgrading.

  5. Wibias commented on Jul 26, 2026

    @Wibias
    Contributor

    Triage

    This looks like a real opencodex bug on 2.7.40, not user misconfiguration and not "Kiro refuses to report usage."

    On 2.7.40, client-facing Kiro input_tokens came from the current-turn estimator (estimateKiroInputTokens / currentTurnUsageMessages), while the full-context estimate stayed in usageLog only. That matches your Codex ~0% context and Claude under-reporting, and it explains why auto-compact never fired.

    Already fixed upstream

    fc517004 (fix(kiro): report context pressure for compaction) ships an absolute contextTotalTokens checkpoint (payload estimate ∪ upstream contextUsagePercentage ∪ turn usage) and responsesUsage() maps that into client input_tokens. That commit is in v2.7.41 / current dev.

    Ask

    Please upgrade to ≥ 2.7.41 and re-check the same session metrics (token_count / Claude transcript). If context pressure still looks empty on 2.7.41+, comment with a fresh sample and we can reopen residual work (e.g. log-field shape). Closing this as fixed-in-release for now.

    Related but separate: #507 (429 retry signaling).

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 working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions