Skip to content

feat(bedrock): default cache_config to auto - #3689

Draft
arielnabavian wants to merge 9 commits into
strands-agents:mainfrom
arielnabavian:feat/cache-10-default-on
Draft

feat(bedrock): default cache_config to auto#3689
arielnabavian wants to merge 9 commits into
strands-agents:mainfrom
arielnabavian:feat/cache-10-default-on

Conversation

@arielnabavian

Copy link
Copy Markdown
Contributor

Summary

Flips the default: BedrockModel now constructs with CacheConfig(strategy="auto") instead of no caching. For models that support Anthropic-style caching (Claude family, us./eu./global.anthropic.* cross-region profiles), this places cache points on the system prompt and last user message on every request; tools caching still requires the explicit cache_tools knob.

For non-Anthropic models on Bedrock (Amazon Nova, DeepSeek, Meta Llama, Mistral, Amazon Titan, etc.) the runtime silently skips injection — _shouldEnableCaching / _cache_strategy returns null — and logs a "model does not support automatic caching" warning at request time. No request payload changes for those models.

Callers who want to opt out pass cache_config=None (Python) or cacheConfig: undefined (TypeScript) explicitly.

Compatibility

Behavior change is technically breaking, but a cache miss falls back to normal input pricing so the worst case is neutral, and the best case is ~90% off input on repeated prefixes. Recommend a release-note callout.

The AnthropicModel default flip is intentionally deferred until upstream #3571 lands (adds cache_config to AnthropicModel); this stack composes on top.

Stack

10/10 — the finale. Closes #2970.

Test plan

  • 189 Python bedrock tests pass (2 new)
  • 178 TS bedrock tests pass (extensive snapshot updates)
  • Full Python suite: 4805 tests
  • Full TS suite: 3940 tests
  • mypy, ruff, prettier, eslint clean
  • Real-API smoke test on Claude Sonnet 4.6 (default cache write on turn 1, cache read on turn 2)
  • Real-API smoke test confirming Nova/DeepSeek/Llama/Mistral models still work with the new default (warning + no cachePoint injection)
  • Verify Agent(model=BedrockModel()) and Agent() (default model) both cache with no config

arielnabavian added 9 commits August 5, 2026 23:40
CacheConfig(strategy="auto") previously only wrote a cache breakpoint on
the last user message, leaving the (usually largest and most static)
system prefix uncached. For workloads that share a system prompt across
calls with varying user messages, every call wrote to cache and none
read — a net cost regression versus no caching.

Append a cachePoint to the system prompt when caching resolves to
"anthropic" for the model and the caller hasn't already placed one at
the end. Both SDKs mirror the change. TS adds a systemTTL knob to
BedrockCacheConfig to match toolsTTL/messagesTTL.

Fixes strands-agents#3144.
LiteLLM wraps many provider APIs behind one interface, so an SDK-level
cache_config has to route to whatever the underlying provider actually
supports:

- Anthropic-family (anthropic/, bedrock/anthropic., vertex_ai/claude,
  vertex_ai_beta/claude) accept cache_control markers. Auto mode
  injects a cachePoint on the last stable system block and the last
  user message; the existing translator turns them into
  cache_control: ephemeral markers before dispatch.
- OpenAI-compatible providers (openai/, deepseek/, xai/, azure/)
  cache automatically server-side. cache_config is accepted for
  portability and is a documented no-op.
- Unrecognized underlying providers warn once per resolution and skip
  injection.

Cache breakpoints on earlier turns are stripped before injection so a
long conversation stays within Anthropic's 4-breakpoint request budget.

Related: strands-agents#2970.
OpenAI's Chat Completions and Responses APIs cache prompts automatically
server-side once they exceed the vendor threshold, so an SDK-level
cache_config is accepted for cross-provider portability but is a
documented no-op — the SDK does not inject anything into the request.

Two vendor knobs that DO matter are now exposed as first-class config:

- prompt_cache_key: routes similar requests to the same cache node
  under load, improving cache-hit rates when many agents share a
  stable system prefix.
- prompt_cache_retention: "in_memory" (default, up to 1h absolute) or
  "24h" (extended retention on eligible models).

Both flow verbatim into the request body on Chat Completions and
Responses. Both SDKs mirror the surface (promptCacheKey /
promptCacheRetention in TypeScript).

Related: strands-agents#2970.
Meta's Llama API caches prompt prefixes automatically server-side, so
an SDK-level cache_config is accepted for cross-provider portability
but is a documented no-op — the SDK does not inject anything into the
request.

Two useful vendor knobs are now exposed:

- prompt_cache_key: groups similar requests when caching. Useful when
  many agents share a stable system prefix.
- prompt_cache_retention: Responses API only, "in_memory" (default)
  or "24h" on models that support extended retention.

Both flow verbatim into the request body. TypeScript SDK does not vend
a Meta-Llama provider — this change is Python-only.

Related: strands-agents#2970.
Mistral's chat completions cache requests that share a stable
prompt_cache_key and a common prefix; cached tokens bill at 10% of
standard input. Unlike Anthropic/Bedrock, Mistral has no per-block
cache marker to inject — the whole surface is the caller-supplied
identifier.

cache_config is accepted for cross-provider portability and is a
documented no-op — set prompt_cache_key to actually opt in to caching.
prompt_cache_key flows verbatim into the request body.

TypeScript SDK does not vend a Mistral provider — this change is
Python-only.

Related: strands-agents#2970.
GPT-5.6 on Bedrock Mantle (openai.gpt-5-6-sol/terra/luna) supports a
prompt_cache_options field to switch between "implicit" (default,
server-auto) and "explicit" (caller-marked cache breakpoints on
specific content blocks) caching modes.

Adds prompt_cache_options as a first-class Responses-only config field.
It flows verbatim into the request body. Explicit-mode breakpoint
marking on specific content blocks is not exposed as an SDK surface
yet — callers passing "explicit" today must know to route breakpoints
through raw content blocks.

Related: strands-agents#2970.
Vercel's AI SDK does not vend a cross-provider caching abstraction —
each provider package accepts caching hints under its own
providerOptions.<provider> slot with a different shape (cacheControl
on Anthropic, cachePoint on Bedrock, promptCacheKey on OpenAI,
cachedContent on Google).

This change accepts cacheConfig on VercelModel for cross-SDK
portability with a documented effect matrix:

- openai.* / openai-responses.*: server-auto; no-op
- google.*: implicit caching on Gemini 2.5+ paid tier; no-op
- anthropic.* / amazon-bedrock.*: warns once per model that per-block
  markers must be set via providerOptions on individual message parts;
  the adapter cannot inject them automatically

cacheConfig is stripped from the downstream call settings so it does
not leak into the vendor call.

Related: strands-agents#2970.
Gemini 2.5+ models on the paid tier already cache prompt prefixes
automatically (implicit caching), so an SDK-level cache_config is
accepted for cross-provider portability but is a documented no-op —
the SDK injects nothing into the request.

Gemini also offers *explicit* caching via a separate CachedContent
resource, which has a create/reference/delete lifecycle and bills for
storage while the cache is alive. That is a distinct feature with real
cost implications; we deliberately do not wire it up on the default
path — callers who need it should use the underlying google-genai SDK
directly. This scope decision is documented on the field.

Both SDKs mirror the surface (cacheConfig on GoogleModelConfig,
cache_config on GeminiConfig).

Related: strands-agents#2970.
Flips the default: BedrockModel now constructs with
CacheConfig(strategy="auto") instead of no caching. For models that
support Anthropic-style caching (Claude family, us./eu./global.anthropic.*
cross-region profiles), this places cache points on the system prompt
and last user message on every request; tools caching still requires
the explicit cache_tools knob.

For non-Anthropic models on Bedrock (Amazon Nova, DeepSeek, Meta Llama,
Mistral, Amazon Titan, etc.) the runtime silently skips injection —
_shouldEnableCaching / _cache_strategy returns null — and logs a
"model does not support automatic caching" warning at request time.
No request payload changes for those models.

Callers who want to opt out pass cache_config=None (Python) or
cacheConfig: undefined (TypeScript) explicitly.

Behavior change is technically breaking, but a cache miss falls back
to normal input pricing so the worst case is neutral, and the best
case is 90% off input on repeated prefixes. Ship note recommended.

Related: strands-agents#2970. The AnthropicModel default flip is intentionally
deferred until upstream PR strands-agents#3571 lands (adds cache_config to
AnthropicModel); this stack composes on top.
@github-actions github-actions Bot added size/xl area-model Related to models or model providers labels Aug 6, 2026
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.66667% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
strands-py/src/strands/models/litellm.py 86.81% 5 Missing and 7 partials ⚠️

📢 Thoughts on this report? Let us know!

@yonib05 yonib05 added complexity/high A touched function exceeds cognitive complexity 25; may be worth splitting size/l and removed size/xl labels Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-model Related to models or model providers complexity/high A touched function exceeds cognitive complexity 25; may be worth splitting size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Default Agents to turn on caching

2 participants