Repository navigation
[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
Description
Client or integration
Codex CLI
Area
Provider adapter
Summary
Kiro 라우팅 모델을 쓰면 클라이언트에 보고되는 input token 수가 현재 turn 분량만 담기고 누적 컨텍스트가 빠집니다. 결과적으로
- Codex CLI: 컨텍스트 잔량이 계속 100%에 가깝게 표시됩니다. 실제로는 200k 토큰 이상 쌓인 상태인데도
model_context_window332,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
- provider
kiro, modelkiro/claude-opus-5로 Codex CLI 세션 실행 - 도구 호출을 여러 번 반복해 대화를 키움(수십 turn, 실제 payload 20만 토큰 이상)
- Codex의 컨텍스트 잔량 표시가 계속 100% 근처에 머무름
- 같은 세션에서
/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에는 동일한 정리가 적용되지 않은 것으로 보입니다.
제안
- 클라이언트에 보고하는 input token을
estimateKiroLogInputTokens()와 동일한 전체 컨텍스트 기준으로 맞춰 주세요. 증분 추정이 과금 목적으로 필요하다면 별도 필드로 분리하는 편이 안전합니다. - 업스트림
metadata.contextUsagePercentage를 클라이언트 컨텍스트 표시의 SOT로 승격하는 방안을 검토해 주세요(cursor adapter와 동일한 방향). 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_window332,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
- Run a Codex CLI session with provider
kiro, modelkiro/claude-opus-5 - Repeat tool calls several times to engage in conversation (tens of turns, actual payload over 200k tokens)
- The context remaining display for Codex remains near 100%
- When switched to
anthropic/claude-opus-5in 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 ofparsed.context.messages+ systemPrompt + tools. This value goes intorequest.usageLog.inputTokensand is only used for logging inusage.jsonl(L1138).estimateKiroInputTokens()(L141) —currentTurnUsageMessages()(L104) only cuts off after the last assistant message and excludes the assistant role. systemPrompt/tools are only included inshouldCountStablePromptOverhead()(L137) when there is nopreviousResponseIdand no assistant messages, that is, only included in the first turn. This value is returned asinputTokens(L1143) and goes through streamusage()(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
- 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. - Consider promoting the upstream
metadata.contextUsagePercentageto the client context display SOT (same direction as the cursor adapter). - The current state of
usage.totalTokens < usage.inputTokensoccurring in the same row is incomprehensible also from the perspective of log consumers.
Activity
[-][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)[/+]github-actions commentedon Jul 26, 2026
jhste102lab commentedon Jul 26, 2026
관련: #507 (같은 Kiro adapter의 429 처리 문제). 두 이슈는 원인이 다르지만 같은 세션 조사에서 함께 발견되었습니다.
Wibias commentedon Jul 26, 2026
Closing as fixed in v2.7.41 (c517004). Please reopen with a fresh sample if context still looks empty after upgrading.
Wibias commentedon Jul 26, 2026
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_tokenscame from the current-turn estimator (estimateKiroInputTokens/currentTurnUsageMessages), while the full-context estimate stayed inusageLogonly. 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 absolutecontextTotalTokenscheckpoint (payload estimate ∪ upstreamcontextUsagePercentage∪ turn usage) andresponsesUsage()maps that into clientinput_tokens. That commit is in v2.7.41 / currentdev.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).