Skip to content

Compaction requests write an Anthropic prompt cache entry that is never read (1.28M cache-write tokens, 0 reads in 7 days) #48542

Closed as not planned

Description

@sergioorestes

Summary

When compaction runs against an Anthropic model, every request writes a prompt cache entry that is never read back. Over 7 days on this machine, 70 successful compactions wrote 1,278,055 cache tokens and read exactly 0.

Cache writes are billed at a premium over ordinary input tokens, so this is a pure surcharge on every compaction with no possibility of payback. The compaction payload is unique by construction, because the window that selects the conversation slice slides forward each time, so no prefix is ever shared between two compaction requests.

Measurement

Read from ~/.local/share/opencode/opencode.db, 7-day window, provider anthropic, model claude-haiku-4-5 configured as agent.compaction.model.

Class Count tokens.total cache.write cache.read
summary produced 70 present 1,278,055 total 0 in all 70
summary empty 15 key absent 0 0

Representative rows from the successful group, showing that essentially the whole prompt goes to a cache write while billed input stays at 3 tokens:

3780 chars  {"total": 8995,  "input": 3, "output": 1486, "cache": {"write": 7506,  "read": 0}}
7675 chars  {"total": 14596, "input": 3, "output": 3049, "cache": {"write": 11544, "read": 0}}
7637 chars  {"total": 19457, "input": 3, "output": 2985, "cache": {"write": 16469, "read": 0}}
7586 chars  {"total": 19631, "input": 3, "output": 2971, "cache": {"write": 16657, "read": 0}}
8894 chars  {"total": 27165, "input": 3, "output": 3533, "cache": {"write": 23629, "read": 0}}

cache.read is 0 in every one of the 70, not merely low on average.

Reproduction

Configure an Anthropic model as the compaction model, run sessions long enough to compact several times, then query the database:

import sqlite3, json, time
from pathlib import Path

db = Path.home() / ".local/share/opencode/opencode.db"
c = sqlite3.connect(f"file:{db}?mode=ro", uri=True)
since = int((time.time() - 7 * 86400) * 1000)

reads = writes = 0
for mid, _, data in c.execute(
    "select id,time_created,data from message where time_created>?", (since,)
):
    r = json.loads(data)
    if not (r.get("summary") is True and r.get("mode") == "compaction"):
        continue
    if r.get("providerID") != "anthropic":
        continue
    cache = (r.get("tokens") or {}).get("cache") or {}
    reads += cache.get("read", 0)
    writes += cache.get("write", 0)

print("cache read:", reads, " cache write:", writes)

Expected

Compaction requests should not request prompt caching, or the cache scope for them should be configurable. The summarization system prompt is small and stable and could reasonably stay cached; the conversation payload is what carries the volume and it is never reused.

Notes on cause

I did not trace this in source, so treat this part as a hypothesis rather than a finding. Reading the shipped bundle, the Anthropic request builder appears to attach cache_control: {type: "ephemeral"} to the system prompt and to the last two messages without a condition that would exclude compaction requests. The measurement above stands on its own regardless of where the marker is attached.

I also could not find any user-facing setting that would turn this off. The top-level config keys in the shipped build are logLevel, server, command, reference, snapshot, plugin, autoshare, disabled_providers, enabled_providers, small_model, mode, agent, provider, permission, tools, attachment and layout, none of which covers caching. There is an internal structure shaped like {tools, system, messages, ttlSeconds} that looks purpose-built for this, but I found nothing wiring it to user configuration.

Environment

  • opencode-ai 1.18.30, Linux x64
  • Compaction model: anthropic/claude-haiku-4-5, set via agent.compaction.model

Activity

  1. github-actions commented on Sep 11, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of an existing issue. Please check:

  2. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the careful measurement and the reproduction script, it makes the problem very clear.

    This report is about OpenCode v1 (opencode-ai 1.18.30). v1 now only gets fixes for critical bugs such as data loss, security problems or crashes with no workaround. The extra cache-write cost on compaction requests doesn't fall into that group, so it's unlikely to be fixed in v1.

    We'd encourage you to try v2 (the @opencode/cli package, opencode command), where active work on the prompt cache and compaction is happening. Related v2 issues:

    If you see the same 0-read / all-write pattern for compaction on v2, or you think this is critical for v1, please reply here with the details.

  3. opencodejr commented on Oct 29, 2026

    @opencodejr

    We haven't heard back, so I'm closing this as not planned. The report is about OpenCode v1 (opencode-ai 1.18.30). v1 only gets fixes for critical bugs, and the extra cache-write cost on compaction requests isn't one of them.

    Thanks again for the detailed measurements. Prompt cache and compaction work is happening in v2 (see #52761, #54107, #53927 and #51109). If compaction requests on v2 also write cache entries that are never read, please open a new issue with your v2 version and the same numbers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions