Skip to content

[Bug]: 2026.6.9 re-busts prompt prefix caching — per-run :run:<UUID> injected into the system-prompt "Runtime:" line (regression of #43148) #96677

Description

@lujiaweichn

Summary

Since 2026.6.9 (still present in 2026.6.10, current latest), isolated cron runs embed a per-run UUID inside the session= field of the system prompt's Runtime: line. Because that UUID changes every run, byte-exact prefix caching is broken for everything after it — notably the ~8k-token tool catalog. Every cron LLM call then pays full uncached input. 2026.6.8 is unaffected. This re-introduces the class fixed in #43148 (related: #19989, #26750).

Affected versions

  • Introduced: 2026.6.9 · Confirmed still broken: 2026.6.10 (npm latest) · Last good: 2026.6.8

Mechanism

The Runtime: line changed from (6.8):

Runtime: agent=<agent> | session=agent:<agent>:cron:<jobid> | host=… | os=…

to (6.9 / 6.10):

Runtime: agent=<agent> | session=agent:<agent>:cron:<jobid>:run:<RUN_UUID> | host=… | os=…

<RUN_UUID> is unique per run → the cached prefix is no longer byte-stable → tool catalog etc. miss cache and are re-billed every call. Provider-agnostic.

Likely origin: #91685 ("refuse keyless implicit isolated cron delivery inherited from shared agent-main bucket", in 2026.6.9) gives each isolated cron run a distinct per-run session key, which is rendered verbatim into the cached system prompt.

Evidence

Same job, only the version changed:

version Runtime: has :run:<UUID> input_tokens / call
2026.6.8 no ~200 (cached)
2026.6.9 / 2026.6.10 yes ~11,500 (uncached)

Reproduced on two independent metered providers (both jumped identically → not provider-specific). For multi-iteration cron agents (10–25 calls/run, each re-sending growing context) this compounds to ~1.5–2M tokens/run — a ~10x cost increase on metered providers.

Suggested fix

Keep the volatile per-run id out of the cached system prefix:

  1. Don't render the cron delivery run-id into the system prompt at all (keep it internal to delivery routing); or
  2. Move the Runtime: line (or just its volatile fields) below the cache breakpoint / into a separate non-cached system message — the approach already discussed in [Bug]: Changing system prompt causes cache invalidations #43148; or
  3. Split static (agent/host/os/model + tool catalog, above the breakpoint) from volatile fields (session/run id, timestamps, below it).

Repro

  1. Create an isolated cron job (sessionTarget: isolated) on a metered provider that reports input_tokens.
  2. Run on 2026.6.8 → note input_tokens/call and that the session field is …:cron:<jobid> (no :run:).
  3. Upgrade to 2026.6.9/2026.6.10, run again → session field is now …:cron:<jobid>:run:<UUID> and input_tokens jumps ~50x.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions