Skip to content

fix(bedrock): preserve cache_control ttl on message-level cache points - #32538

Merged
mateo-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_fix_bedrock_message_cache_ttl
Jul 8, 2026
Merged

fix(bedrock): preserve cache_control ttl on message-level cache points#32538
mateo-berri merged 1 commit into
litellm_internal_stagingfrom
litellm_fix_bedrock_message_cache_ttl

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #32154

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Screenshots / Proof of Fix

Two proxies running the same config (bedrock/eu.anthropic.claude-opus-4-8, eu-central-1), before on port 4001 at bfff5e8d86, after on port 4000 at 7195c2dfa2. Payload puts cache_control: {"type": "ephemeral", "ttl": "1h"} on both the system prompt and a large conversation-history user message. Turn 2 is sent 7 minutes after turn 1 so anything that only got the 5m default has expired while 1h caches survive

$ for t in 1 2; do
    curl -s localhost:4001/v1/chat/completions -H 'Content-Type: application/json' -d @payload_BASE_$t.json | jq .usage
    curl -s localhost:4000/v1/chat/completions -H 'Content-Type: application/json' -d @payload_FIXED_$t.json | jq .usage
    [ $t = 1 ] && sleep 420
  done

Real Bedrock calls, no mocks:

19:22:08 turn 1
before (4001): prompt_tokens=14607  cache_creation=14589  cache_read=0
after  (4000): prompt_tokens=14609  cache_creation=14591  cache_read=0

19:29:08 turn 2, 7 min later
before (4001): prompt_tokens=14607  cache_creation=7294   cache_read=7295    <- message breakpoint fell back to 5m and expired; half the prefix is re-created on every turn
after  (4000): prompt_tokens=14609  cache_creation=0      cache_read=14591   <- full prefix served from the 1h cache

Type

🐛 Bug Fix

Changes

AmazonConverseConfig._get_cache_point_block only preserves the ttl from cache_control when it receives a model that supports extended caching; with model=None the ttl is silently stripped and Bedrock falls back to the 5m default. The system-prompt and tools paths already pass model, but none of the 8 message-level call sites in _bedrock_converse_messages_pt / _bedrock_converse_messages_pt_async did, so message-level cache breakpoints (the ones that cache conversation history) always lost their requested ttl: "1h"

This produced mixed TTLs on models that support 1h caching (Opus 4.8 etc after the JSON-driven gate landed in #31929): the system prompt got 1h while conversation-history breakpoints silently got 5m, so multi-turn agent workloads re-created the history prefix every turn; cache_read_input_tokens froze at the system-prefix size while cache_creation_input_tokens grew, driving large cost increases

The fix passes model through at all 8 message-level call sites. Regression tests assert the message-level cachePoint keeps ttl: "1h" on both the sync and async paths; they fail on the base commit and pass with this change

Link to Devin session: https://app.devin.ai/sessions/2cd3570c8b8a4986bec41d701aa44a87
Requested by: @ishaan-berri

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
@ishaan-berri ishaan-berri self-assigned this Jul 8, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where message-level Bedrock cache breakpoints silently dropped the ttl field from cache_control because the 8 call sites inside _bedrock_converse_messages_pt / _bedrock_converse_messages_pt_async never forwarded model to _get_cache_point_block. Without model, is_claude_4_5_on_bedrock returned False and the TTL was stripped, causing conversation-history prefixes to fall back to the 5-minute default even on models (e.g. Claude Opus 4.8) that support 1h caching.

  • Adds model=model to all 8 message-level _get_cache_point_block call sites in both the sync (_bedrock_converse_messages_pt) and async (BedrockConverseMessagesProcessor._bedrock_converse_messages_pt_async) paths.
  • Adds parametrized sync and async regression tests that assert the cachePoint block carries ttl: "1h" for user and assistant message content on a model with extended-TTL support; these tests fail on the base commit and pass with this fix.

Confidence Score: 5/5

Safe to merge — the change is a targeted one-argument fix at 8 symmetric call sites with direct regression test coverage on both the sync and async paths.

The fix is minimal and mechanical: passing model that was already in scope to call sites that had been omitting it. The underlying _get_cache_point_block / is_claude_4_5_on_bedrock / _build_cache_point_block chain is unchanged. The new tests cover the exact regression path (user list content and assistant list content, plus the async path) and do not make real network calls. No existing tests are modified.

No files require special attention.

Important Files Changed

Filename Overview
litellm/litellm_core_utils/prompt_templates/factory.py Adds model=model to all 8 message-level _get_cache_point_block call sites across sync and async paths; no logic changes, just passes the missing argument through.
tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py Adds new parametrized sync and async regression tests verifying that message-level cache points retain ttl="1h"; tests are pure unit tests with no real network calls.

Reviews (1): Last reviewed commit: "fix(bedrock): preserve cache_control ttl..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will improve performance by 24.36%

⚡ 1 improved benchmark
✅ 29 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
test_completion_simple_message 4.8 ms 3.9 ms +24.36%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing litellm_fix_bedrock_message_cache_ttl (7195c2d) with litellm_internal_staging (b00877c)

Open in CodSpeed

@mateo-berri
mateo-berri self-requested a review July 8, 2026 20:57
@mateo-berri
mateo-berri enabled auto-merge (squash) July 8, 2026 21:00

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; thanks!

@mateo-berri
mateo-berri merged commit 0f1e29b into litellm_internal_staging Jul 8, 2026
124 checks passed
@mateo-berri
mateo-berri deleted the litellm_fix_bedrock_message_cache_ttl branch July 8, 2026 21:00
edelauna pushed a commit to edelauna/litellm that referenced this pull request Jul 22, 2026
BerriAI#32538)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
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.

[Bug]: Bedrock message-level cache_control ttl silently degrades to 5m (system-level works)

3 participants