Skip to content

Claude Opus 5: effective context silently capped at ~166K (≈83% of 200K) despite 1M catalog/blog claims #128

Open

Description

@q8247990

Summary

In a 24-hour OpenCode session routed through this plugin (kiro provider, model claude-opus-5, 806 step-finishes, zero 4xx errors), every single API call reported input_tokens ≤ 166,512 even though the local conversation grew to ~498K tokens by session end. Growth was asymptotic: ~100K at 39% of steps, ~130K at 65%, ~150K at 83%, ~160K at 93%, and a final plateau of 166,512 at step 805/806. The model only ever saw the most recent ~166K of the conversation: a silent sliding window, not a rejection.

This matters because Kiro's public blog advertises Claude Opus 5 with a full 1M context window (2.2x credit multiplier) and this plugin's model-registry mirrors that as limit.context: 1000000. OpenCode therefore believes it has ~834K headroom of free space and never auto-compacts. On long sessions the model is effectively amnesic beyond the recent ~166K tail while the UI context bar reads ~16%, which looks healthy.

Evidence

From one 24h / 806-step-finish OpenCode session on kiro / claude-opus-5, 2026-09-02 09:48 → 2026-09-03 10:08 UTC:

Metric Value
API-reported input_tokens ceiling across all 806 requests 166,512 (no 4xx, no warnings)
cache_read_input_tokens on every request 0
Crossed 100K at 39% of steps (≈ step 314)
Crossed 130K at 65% of steps (≈ step 524)
Crossed 150K at 83% of steps (≈ step 669)
Crossed 160K at 93% of steps (≈ step 750)
Reached 166,512 at step 805 / 806 (hard plateau)
Model switch to a different provider at 10:09: first request input_tokens 498,086 (= full local conversation history)

Delta after the switch (498,086 vs ≤166,512) confirms the local conversation had grown to ~498K while opus-5 was being served only the trailing ~166K window.

Where it comes from

Plugin arithmetic (v2.0.0, commit 08f06b4):

inputTokens = round(contextWindow × contextUsagePercentage / 100) − outputTokens
src/plugin/streaming/stream-transformer.ts:301-305

getContextWindowSize returns 200,000 unless the model name contains -1m (src/plugin/models.ts:11-13), and LONG_CONTEXT_MODELS is keyed off the -1m suffix (src/constants.ts:101). claude-opus-5 has no -1m variant in the plugin, and Kiro does not expose a separate long-context alias for Opus 5 (per upstream PR #116).

The reported ceiling fits 200K exactly: 166,512 ≈ 200,000 × 0.833, so the backend's contextUsagePercentage is consistent with a ~200K-class window, not 1M. The plugin's reported 166K is therefore a faithful fraction of 200K; the misleading part is the advertised limit.context: 1000000 that OpenCode reads from the model-registry, which prevents auto-compaction and makes the ~84% utilization look like "lots of headroom."

Why catalog discovery (PR #121) may not fix this

If Kiro's catalog reports 1_000_000 for claude-opus-5 (matching the public blog claim), then catalog-based discovery would confirm the 1M headroom while the CodeWhisperer/Q layer continues to serve a ~200K window. The silent truncation would continue undetected.

Suggested checks before trusting a catalog-derived 1M for opus-5:

  1. Cross-check the catalog value against observed contextUsagePercentage behavior on a long session: if the plateau divides back to ~200K, the catalog claim is wrong or the long-context path is gated.
  2. Until Kiro confirms 1M is actually served end-to-end, pin claude-opus-5 to contextWindow: 200000 so clients can compact appropriately (mirroring Bedrock's 1M beta requirement, see #16486).
  3. If a long-context path does exist, surface it as a separate model id or beta flag so users opt in knowingly: same shape as AWS Bedrock's context-1m-2025-08-07 beta.

Comparable reports

  • anomalyco/opencode#45168: same failure pattern on another provider: input pinned at exactly 196,608 = 262,144 − 65,536, cache_read=0 on every subsequent request, silent cost blowup.
  • anomalyco/opencode#12452 and #12507: Bedrock Claude: 1M context requires the context-1m-2025-08-07 beta; catalog says 1M but API enforces 200K.
  • anomalyco/opencode#16486: 1M beta flag broke specifically on AWS Bedrock.

Request

  1. Confirm whether the CodeWhisperer / Q layer currently serves claude-opus-5 on a ~200K-class window, or whether a 1M path exists behind an opt-in mechanism (separate model id / beta flag / header).
  2. If 200K is the current reality, reflect that in the advertised limit.context so OpenCode auto-compacts on long sessions; or, if a 1M path genuinely exists, document how to unlock it (model alias, beta flag, upstream config) so users aren't silently running with a tail-only ~166K.

Evidence gathered from local session telemetry (OpenCode SQLite step-finish data) + plugin source inspection (v2.0.0, commit 08f06b4). Happy to share more detail on request.

Activity

  1. q8247990 commented on Sep 3, 2026

    @q8247990
    Author

    Related work in this area:

    • PR fix: propagate CodeWhisperer cache token usage instead of hardcoding zero #129 (opened alongside this issue) fixes the separate cache-token reporting gap: cacheReadInputTokens/cacheWriteInputTokens from the CodeWhisperer metadata event were hardcoded to 0 in the plugin, so OpenCode could never see cache reads. That PR changes observability only (no request-shape or window changes), so it does not resolve the window question raised here.
    • PR feat(models): discover context windows from Kiro catalog #121 (catalog-based window discovery) is the closest candidate for addressing this issue, subject to the concern raised in the body: if the catalog reports 1M while the Q layer enforces ~200K, discovery alone would not change behavior.
  2. q8247990 commented on Nov 3, 2026

    @q8247990
    Author

    Correction after measuring the service directly — the ceiling is not a 200K backend window, and 166,512 is a plugin artifact.

    166,512 = 200,000 × 0.8326 is exactly what getContextWindowSize() computes by multiplying the 200K fallback with the streamed contextUsagePercentage. The backend percentage is relative to the real served window, so the true input on that step was ~459K, not 166K.

    Measurements taken today (same account, Kiro Pro Max / Q_DEVELOPER_STANDALONE_PRO_MAX): grow a single generateAssistantResponse prompt and read contextUsagePercentage; the service eventually answers {"message":"Input is too long.","reason":"CONTENT_LENGTH_EXCEEDS_THRESHOLD"}.

    model window evidence
    claude-sonnet-4.5 200K 66,667 tok → 38.75%; ~200K → 400
    claude-opus-4.6 / sonnet-4.6 (+ -1m) 1M 600K → 66.42%; 800K → 88.42%
    claude-opus-4.7 / 4.8 600K 66,667 tok → ~12.6%
    claude-opus-5 / sonnet-5 600K 400K → 72.69%; 533K → 96.7%; 600K → 400
    claude-fable-5.1, auto 600K 66,667 tok → ~12.7%

    So for claude-opus-5: 2.4M chars (~533K tokens) succeeds at 96.71%, 2.7M chars (~600K tokens) fails with CONTENT_LENGTH_EXCEEDS_THRESHOLD. The plugin reported 200,000 × 0.9667 ≈ 193K for that request — a 2.75x under-report. That is why the UI context bar "looks healthy" and compaction never fires; the model was not silently limited to 166K, it was being handed ~459K and the plugin mislabelled it.

    Two fixes are needed and both are in #137:

    1. advertise the served window (600K for 5.x/4.7/4.8, 1M for 4.6) instead of the 1M catalog claim;
    2. derive the token count from that same table instead of the 200K -1m heuristic.

    Also exposed claude-opus-4-6-1m / claude-sonnet-4-6-1m, which are the only ids truly served at 1M today (claude-sonnet-5-1m and claude-opus-4-7-1m now return INVALID_MODEL_ID).

    Finally, regarding #121: GET /ListAvailableModels?origin=AI_EDITOR returns 403 {"message":"Your subscription does not support this application..."} on this Pro Max account even with the exact headers used by that PR, so catalog discovery falls back to the heuristic and cannot fix this on its own.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions