anthropics / anthropics/claude-code

Channel messages are merged into the previous user message and re-rendered on the next request, losing the prompt cache on non-Anthropic backends

Aperta
#93,622 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
area:cost area:plugins bug platform:wsl
Lingua principale
Python
Stelle
145k
Fork
23.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

**Environment:** Claude Code 2.1.268 (Linux/WSL2), Channels (experimental) via the Atrium plugin (`inject directly`), `ANTHROPIC_BASE_URL` → CLI Proxy API → OpenAI Responses (`gpt-5.6-sol` / `gpt-6-astra`). Also observed on 2.1.26x sessions routed to `gpt-6-astra`.

**What I observe.** With a metadata-only diff of consecutive upstream requests (per-item hashes and byte lengths, no content), a session receiving channel messages produces requests that are not append-only: the previous user message is re-rendered (1,516 B → 2,552 B when a channel message is delivered, then split into 364/436/317 B + a new item on the next request), and `reasoning`/thinking items of the affected turns are inserted or removed before an earlier assistant message. Example windows from the trace: `assistant:88 | user:1516` → `assistant:88 | user:2552`; `reasoning:1835 | reasoning:1535 | reasoning:1515 | assistant:86` → `reasoning:1835 | assistant:86 | user:…`.

It happens whether the channel message arrives during an open turn or while the session is idle (tested with a channel-side hold that delivers only after the Stop hook: same rewrites).

**Why it matters.** On Anthropic the change costs a small cache write (cache_control breakpoints + lookback). On OpenAI's GPT-5.6+ prefix cache, any change before the end of the prompt invalidates everything after it, and explicit breakpoints are rejected by the Codex/ChatGPT-OAuth backend. Measured: on ~300K-token sessions, 8–15 % of requests re-billed the whole context (e.g. 46 requests × ~250K uncached tokens in one day); on a fresh session, 14–21 rewrites over 20–30 requests. Related reports: #76606 (hook system-reminder transformed later), #78660 (task_reminder attached to an old human message), #64901, #80604, #48734.

**Expected.** A delivered channel message (and hook/system-reminder attachments) should be appended as a new user item, and already-sent items should stay byte-stable across requests, so that append-only prefix caches keep working.

**Repro.** Any session with a channel plugin: send a message via the channel while the session is idle, then another one; compare the two API request bodies item by item (or watch `cache_read_input_tokens` drop when routed to a prefix-cache backend). A full dossier (traces, journal of a channel-side hold, before/after runs) is available on request.

Am I missing a setting that changes how channel messages are injected? If this is by design, is there a supported delivery mode that does not rewrite earlier items?

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Start by tracing the Channels experimental plugin's `inject directly` delivery path and the construction of consecutive upstream API request bodies. Compare item hashes and lengths across idle and open-turn deliveries, then verify that delivered messages append as new user items, earlier items remain byte-stable, and prefix-cache reads no longer drop on supported backends.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Ambito
api, backend, performance
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.