Skip to content

Commit 67d081f

Browse files
committed
test(bedrock): add e2e coverage for cache_tools_ttl, CacheConfig.ttl, and aligned 1h TTL across checkpoints
Adds three integration tests exercising the new auto-inject TTL paths and the Bedrock non-increasing TTL ordering rule that motivated this change (Issue #2121): - test_prompt_caching_cache_tools_ttl: verifies Bedrock accepts cachePoint.ttl on the toolConfig checkpoint without ValidationException. - test_prompt_caching_cache_config_auto_with_ttl: verifies CacheConfig(strategy="auto", ttl="5m") produces a cacheWrite on the auto-injected message cache point. - test_prompt_caching_aligned_1h_ttl_across_checkpoints: regression test that sets 1h TTL on all three cache checkpoints (toolConfig, system, messages) simultaneously and verifies Bedrock accepts the non-increasing ordering.
1 parent ed6e7f4 commit 67d081f

1 file changed

Lines changed: 123 additions & 1 deletion

File tree

tests_integ/models/test_model_bedrock.py

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import strands
88
from strands import Agent
9-
from strands.models import BedrockModel
9+
from strands.models import BedrockModel, CacheConfig
1010
from strands.types.content import ContentBlock
1111

1212

@@ -576,3 +576,125 @@ def calculator(expression: str) -> float:
576576
agent('Search for "python" with tags ["programming", "language"] using the search tool.')
577577

578578
assert "search" in tools_called
579+
580+
581+
def test_prompt_caching_cache_tools_ttl():
582+
"""Test that cache_tools_ttl propagates into the auto-injected toolConfig cache point.
583+
584+
Verifies that BedrockModel(cache_tools="default", cache_tools_ttl="5m") produces a
585+
Bedrock request with cachePoint.ttl on the toolConfig checkpoint, and that the call
586+
completes without a ValidationException on the TTL field.
587+
588+
Note: we intentionally do not assert specific cacheWriteInputTokens on the toolConfig
589+
prefix because Bedrock's tool-prefix cache threshold varies by model and region.
590+
The critical behavior under test here is that the TTL field is accepted end-to-end.
591+
592+
Uses Claude Haiku 4.5 which supports TTL in CachePointBlock on Bedrock.
593+
"""
594+
model = BedrockModel(
595+
model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0",
596+
streaming=False,
597+
cache_tools="default",
598+
cache_tools_ttl="5m",
599+
)
600+
601+
@strands.tool
602+
def lookup_fact(topic: str) -> str:
603+
"""Look up a fact about the given topic.
604+
605+
This tool is useful when you need authoritative information.
606+
"""
607+
return f"Fact about {topic}: example"
608+
609+
agent = Agent(
610+
model=model,
611+
tools=[lookup_fact],
612+
load_tools_from_directory=False,
613+
)
614+
615+
# The call must succeed — Bedrock must accept cachePoint.ttl on the toolConfig checkpoint
616+
# without raising a ValidationException.
617+
result = agent("Use the lookup_fact tool to look up 'python'.")
618+
assert len(str(result)) > 0
619+
620+
621+
def test_prompt_caching_cache_config_auto_with_ttl():
622+
"""Test that CacheConfig(strategy="auto", ttl="5m") propagates TTL to the auto-injected message cache point.
623+
624+
Verifies that the cache point appended to the last user message by _inject_cache_point
625+
carries the configured TTL, and that Bedrock accepts the request.
626+
627+
Uses Claude Haiku 4.5 which supports TTL in CachePointBlock on Bedrock.
628+
"""
629+
model = BedrockModel(
630+
model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0",
631+
streaming=False,
632+
cache_config=CacheConfig(strategy="auto", ttl="5m"),
633+
)
634+
635+
unique_id = str(uuid.uuid4())
636+
# Minimum 4096 tokens required for caching with Haiku 4.5
637+
large_message = f"Context for test {unique_id}: " + ("This is important context. " * 1000) + " What is 2+2?"
638+
639+
agent = Agent(
640+
model=model,
641+
load_tools_from_directory=False,
642+
)
643+
644+
# First call: auto-injected cache point on the last user message must include ttl and be accepted
645+
result1 = agent(large_message)
646+
assert len(str(result1)) > 0
647+
648+
# Verify cache write occurred with auto-inject + ttl
649+
assert result1.metrics.accumulated_usage.get("cacheWriteInputTokens", 0) > 0, (
650+
"Expected cacheWriteInputTokens > 0 with CacheConfig(strategy='auto', ttl='5m')"
651+
)
652+
653+
654+
def test_prompt_caching_aligned_1h_ttl_across_checkpoints():
655+
"""Regression test for Bedrock TTL non-increasing ordering rule (Issue #2121).
656+
657+
Bedrock processes cache checkpoints in order: toolConfig -> system -> messages,
658+
and requires TTLs to be non-increasing. Before this change, cache_tools hardcoded
659+
an implicit 5m TTL, so any 1h TTL on a later checkpoint would raise a
660+
ValidationException.
661+
662+
This test sets 1h TTL on all three checkpoints simultaneously and verifies the
663+
call succeeds.
664+
665+
Uses Claude Haiku 4.5 which supports 1h TTL.
666+
"""
667+
model = BedrockModel(
668+
model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0",
669+
streaming=False,
670+
cache_tools="default",
671+
cache_tools_ttl="1h",
672+
cache_config=CacheConfig(strategy="auto", ttl="1h"),
673+
)
674+
675+
# Timestamp-based uniqueness to avoid cache conflicts across CI runs
676+
unique_id = str(int(time.time() * 1000000))
677+
large_context = f"Background context for test {unique_id}: " + ("This is important context. " * 1000)
678+
679+
# User-supplied 1h cache point on system prompt — third checkpoint also at 1h
680+
system_prompt_with_cache = [
681+
{"text": large_context},
682+
{"cachePoint": {"type": "default", "ttl": "1h"}},
683+
{"text": "You are a helpful assistant."},
684+
]
685+
686+
@strands.tool
687+
def echo(value: str) -> str:
688+
"""Echo the given value back."""
689+
return value
690+
691+
agent = Agent(
692+
model=model,
693+
system_prompt=system_prompt_with_cache,
694+
tools=[echo],
695+
load_tools_from_directory=False,
696+
)
697+
698+
# Must succeed without ValidationException on the non-increasing TTL rule
699+
result = agent("What is 2+2?")
700+
assert len(str(result)) > 0

0 commit comments

Comments
 (0)