Skip to content

feat(cache): add cache_ttl config knob for opt-in 1h prompt-cache TTL - #91

Open
Sam Schillace (ramparte) wants to merge 2 commits into
microsoft:mainfrom
ramparte:hq9/cache-ttl-1h
Open

feat(cache): add cache_ttl config knob for opt-in 1h prompt-cache TTL#91
Sam Schillace (ramparte) wants to merge 2 commits into
microsoft:mainfrom
ramparte:hq9/cache-ttl-1h

Conversation

@ramparte

Copy link
Copy Markdown
Contributor

Feature: Optional 1-hour Prompt Cache TTL

Introduces an opt-in cache_ttl configuration knob that enables 1-hour prompt-cache time-to-live (TTL) support via the extended-cache-ttl-2025-04-11 beta. The knob is off by default — when absent, payloads are byte-identical to pre-patch versions (flag-deletable).

Configuration:

  • Key: cache_ttl
  • Valid values: `"1h"" (enables TTL) | any other value or absent (disabled)
  • Beta header: extended-cache-ttl-2025-04-11 appended to per-model header builder when enabled

Why This Is NOT a Duplicate of cache_stable_region_ttl_1h

These are fundamentally different knobs serving different purposes:

cache_stable_region_ttl_1h (existing, #86):

  • Controls cache breakpoint placement strategy: stable (long-lived) vs ephemeral (request-scoped) messages
  • Sets a single placement flag that applies uniformly; one toggle value alters strategy
  • Problem solved: stop caching the trailing ephemeral messages that are re-generated every request anyway

cache_ttl (this PR):

  • Controls cache control values (TTL parameters) at four distinct cache_control sites independently
  • Patches each of the four cache_control blocks individually with {"type": "ephemeral", "ttl": "1h"}
  • Problem solved: opt-in to extended cache TTL for organizations that want the cost/token savings and can tolerate 1h staleness

Different config keys, different implementation sites, different semantic meaning. The cache_ttl knob operates at the payload level (per-block cache_control structure); cache_stable_region_ttl_1h operates at the strategy level (which messages get cached).

Testing

Unit tests: 19 new tests in tests/test_cache_ttl.py validating:

  • Knob on/off behavior
  • TTL value propagation to all 4 cache_control sites
  • Beta header presence/absence
  • Interaction with enable_prompt_caching flag

Full suite: 548 tests passing, zero regressions

Live validation: Verified against live API (HQ9 E2 environment):

  • Ephemeral_1h_input_tokens accounting confirmed
  • Cache TTL applied and honored by Anthropic backend
  • Run bash verify.sh to validate: unit tests + full suite + grep assertions on cache_ttl guard sites

Commits

  1. 6d6bbef - Test harness fix: MockStreamManager async-iterator protocol (pre-existing failure at base 2e7232a)
  2. 133abbb - Core feature: cache_ttl knob with 4-site cache_control patching

Proof of Production Usage

This branch has been running in production as a local source override on the author's machine (live since 2026-07-20), validating real-world stability and correctness.

Sam Schillace (ramparte) and others added 2 commits July 20, 2026 19:25
…ilure at base 2e7232a)

note that at base 2e7232a, tests in test_tool_repair.py fail with TypeError ('async for' requires __aiter__); fix is test-only, adds __aiter__/__anext__ emitting zero events to match the real SDK MessageStream contract; verified failing with all other changes reverted.

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…che-ttl-2025-04-11)

opt-in knob, OFF by default (flag-deletable: absent key => payloads byte-identical to pre-patch); exact value "1h" adds ttl to all 4 cache_control sites and appends the extended-cache-ttl-2025-04-11 beta header in the per-model header builder; any other value behaves as off; validated against live API (HQ9 E2: ephemeral_1h_input_tokens accounting confirmed); 19 unit tests in tests/test_cache_ttl.py, full suite 548 passed; verify via `bash verify.sh`.

Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
@Joi

Copy link
Copy Markdown

This covers the config and wiring half of microsoft/amplifier#337 (linking for cross-reference; it can't auto-close from a comment, and the cost half below is still open). I had a branch for the same knob and retracted it because the TTL never reached _apply_message_cache_control; this PR patches both message paths with tests, which is the part I got wrong. Thanks.

Remaining gaps and follow-ups:

  1. Cost accounting. _cost.py still prices every cache write at the 5m rate (1.25x base input). With cache_ttl: "1h" on, 1h writes cost 2x, so the cache-write component of reported cost is 37.5% low whenever a 1h write happens. The usage object now returns cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens, so the split is available, and the comment at _cost.py:142 ("returns a single cache_creation_input_tokens count and does not distinguish TTLs") is stale. I have working, tested code for this at https://github.com/Joi/amplifier-module-provider-anthropic/tree/feat/prompt-cache-1h-ttl (the _cost.py hunk is the part of that branch that was correct). You're welcome to lift it into this PR; otherwise I'll open a follow-up PR on top of yours once it merges, and #337 stays open until that lands.

  2. Discoverability. cache_ttl is not in the README config section and not surfaced by get_info() next to enable_prompt_caching. VERIFY.md documents the verification, not the configuration surface.

  3. The extended-cache-ttl-2025-04-11 beta header is not required. I verified on 2026-07-20 that ttl: "1h" returns 200 with the per-TTL usage breakdown and no beta header. Sending it is harmless today, but worth dropping or noting as optional in VERIFY.md so future maintainers know it isn't load-bearing. Also, _build_request_beta_headers appends it based on _cache_ttl alone, so it is sent even when enable_prompt_caching is false and no cache_control blocks exist.

  4. The PR body says the tests cover "interaction with enable_prompt_caching flag", but none of the 19 tests in test_cache_ttl.py sets that flag. A test for enable_prompt_caching: false + cache_ttl: "1h" (no cache_control, and arguably no beta header) would close that gap.

  5. Only the exact string "1h" enables the 1h tier; "5m" is fine (that's the default), but "1H" or a typo silently leaves you on 5m. A warning on unrecognized values would save someone a confusing cost bill.

Separately: your first commit fixes the test_tool_repair.py::test_streaming_* mock failures I reported as pre-existing in microsoft/amplifier#336, so that issue can reference this too.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants