Files
doczyai-pipelines/documentation/CONTEXT_CACHING_IMPLEMENTATION.md
Katon Minhas 0d00d581b1 Merged in DEV (pull request #913)
DEV

* Apply formatting fix

* Merged in DAIP2-1898-one-to-one-issues-filename-tin-auto-renewal-and-contract-title (pull request #888)

DAIP2-1898 one to one issues filename tin auto renewal and contract title

* contract title fixes

* Add instruction to strip hyphens from TIN and NPI

* prompt update

* Merge branch 'bugfix/auto-renewal-term' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* removed print statements

* pipeline error fixed

* signed_ind logic changed

* signatory_ind logic updated

* prompt update

* prompt update

* pipeline error fixed

* Merge branch 'DEV' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* Merge branch 'DEV' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* requested changes applied

* test case added

* prompt update

* contract title prompt update

* prompt update

* Merge branch 'DEV' into DAIP2-1898-one-to-one-issues-filename-tin-auto-renewal-and-contract-title


Approved-by: Siddhant Medar

* Merged in feature/DAIP2-1803-add-aarete-derived-provider-name (pull request #884)

Feature/DAIP2-1803 add aarete derived provider name

* Merged DEV into feature/DAIP2-1562-add-aarete_derived_payer_name

* state logic added in clustering

* removed print statements

* pull request updates

* black format fix

* Merged DEV into feature/DAIP2-1562-add-aarete_derived_payer_name

* added scalability feature and optimization

* black format

* Pull Request Changes

* generalised funcs from aarete derived payer name

* updated remove states and updated docstring for build similarity matrix

* derived payer name functionality added

* config and main file changes

* sync dev into ADD AARETE DERIVED PROVIDER GROUP NAME FULL

* updated derived_provider name

* pipeline fixes

* Merged DEV into feature/DAIP2-1803-add-aarete-derived-provider-name

* config changes

* field name updated to AARETE_DERIVED_PROVIDER_NAME

* Merged DEV into feature/DAIP2-1803-add-aarete-derived-provider-name

* black format fix

* Fix docstr…
* Merged in improve-logging (pull request #886)

Improve logging

* Add timing blocks for comprehensive pipeline logging

- Add timing_utils.timed_block() to key extraction functions in one_to_n_funcs.py:
  - exhibit_level sub-functions (prompt_exhibit_level, dynamic_primary, etc.)
  - reimbursement_level extraction and cleaning
  - breakout functions (methodology_breakout, special_case_breakout)
  - carveout_and_special_case parallel processing
  - one_to_n_cleaning sub-steps (crosswalk, lob_relationship, split_reimb_dates)

- Add timing to dynamic_funcs.py:
  - dynamic_assignment parallel processing

- Add timing to postprocess.py:
  - standard_postprocess, contract_config_postprocess, dashboard_postprocess

- Add timing to preprocess.py:
  - exhibit_chunking sub-steps (get_exhibit_pages, link_exhibit_pages, chunk_by_exhibit)

- Add info-level logging statements for completed operations with row/item counts

* Standardize logging levels and remove deprecated code

DAIP2-1798: Ensure logging statements are at …
* Merged in bugfix/DAIP2-1913-lesser-of-indicator-issues (pull request #889)

Bugfix/DAIP2-1913 lesser of indicator issues

* contract title fixes

* Add instruction to strip hyphens from TIN and NPI

* prompt update

* Merge branch 'bugfix/auto-renewal-term' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* removed print statements

* pipeline error fixed

* signed_ind logic changed

* signatory_ind logic updated

* prompt update

* prompt update

* pipeline error fixed

* Merge branch 'DEV' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* Merge branch 'DEV' into bugfix/DAIP2-1699-issue-tracker-fixes-one-to-one-dates-prov-info

* requested changes applied

* test case added

* prompt update

* contract title prompt update

* prompt update

* Merge branch 'DEV' into DAIP2-1898-one-to-one-issues-filename-tin-auto-renewal-and-contract-title

* handle nested cases of lesser_of and greater_of

* Merge branch 'DEV' into bugfix/DAIP2-1913-lesser-of-indicator-issues

* pi…
* Merged in bugfix/reimb_primary (pull request #890)

Update reimbursement prompts for consistent PMPM handling, time-unit dedup, and validation improvements

* Update reimbursement prompts for consistent PMPM handling, time-unit dedup, and validation improvements

- REIMBURSEMENT_PRIMARY: append unit of measure (PMPM, per visit, etc.) from table headers into REIMB_TERM
- METHODOLOGY_BREAKOUT: collapse mathematically equivalent time-unit rates into single entry
- VALIDATE_REIMBURSEMENTS: add umbrella terms as valid service terms, accept CPT/HCPCS percentage as concrete rate, narrow COB disqualifier to primary subject only

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Approved-by: Siddhant Medar

* Merged in feature/update-postprocessing-columns (pull request #893)

move column order to final step

* move column order to final step

* Black


Approved-by: Siddhant Medar

* Merged in bugfix/update-postprocessing-paths (pull request #896)

Update postprocessing paths

* Update postprocessing paths


Approved-by: Siddhant Medar

* Merged in feature/TIN_stats_update (pull request #898)

Feature/TIN stats update

* Tin_stats_report

* black formatting

* minor changes

* black format applied

* Addressed the katons comments

* Merged DEV into feature/TIN_stats_update

* black reformat


Approved-by: Katon Minhas

* Merged main into DEV

* Merged in feature/exhibit-smart-chunking (pull request #883)

Feature/exhibit smart chunking

* exhibit processing per page

* header dict deduplication

* dedup prompt refinment

* refinment for header extraction proecess

* Merge remote-tracking branch 'origin/DEV' into feature/exhibit-smart-chunking

* merge updates

* minor fix

* prompt fix for reimb type

* COB defenition for clear understanding

* black formatting

* remove quit statement

* pipiline test

* pipeline test

* black formatting

* Merge remote-tracking branch 'origin/DEV' into feature/exhibit-smart-chunking

* black formating

* Merge remote-tracking branch 'origin/DEV' into feature/exhibit-smart-chunking

* typo

* PR comment fixes

* exhibit funcs refactored

* black formatting

* Refactor exhibit chunking config into dedicated class

Created ExhibitChunkingConfig class to centralize exhibit smart chunking
configuration parameters (DEFAULT_SUBCHUNK_SIZE, MIN_PARENT_CHUNK_SIZE,
CHUNK_RELEVANCE_THRESHOLD). This improves code organization …
* Merged in bugfix/DAIP2-1870-dynamic-issues (pull request #892)

Bugfix/DAIP2-1870 dynamic issues

* updated list format appending

* fill bill type from claim type cd

* Fixed remaining format fixes

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues

* changed crosswalk mapping from PRODUCT to AARETE_DERIVED_PRODUCT

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues

* updating LOB field values as well from PRODUCT AND PROGRAM

* updated apply crosswalk for reverse mapping

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues

* added QHP and BHP

* removed lob reverse mapping

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues

* Remove Bill Type/Claim Type fill

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues

* Black format

* Merged DEV into bugfix/DAIP2-1870-dynamic-issues


Approved-by: Katon Minhas

* Merged in bugfix/prov_info_json_fixes (pull request #899)

Bugfix/prov info json fixes

* fix: robust PROV_INFO_JSON sanitization and TIN backfill logic

json_utils:
- Add sanitize_prov_info_json with layered parsing (JSON, literal_eval,
  empty-value-after-colon fix, best-effort dict extraction).
- Add _normalize_prov_entries and _prov_value_to_str for uniform
  str-valued output; flatten list values, strip TIN hyphens.
- format_prov_info_json now delegates to sanitize_prov_info_json.

postprocessing_funcs:
- Add fill_prov_info_tin_from_filename_tin for TIN backfill.
- Add validate_and_reformat_date (pipe-wrapped, datetime strings).
- Add format_as_json_list (pipe-delimited, comma-separated, quote
  stripping).

postprocess:
- Integrate new postprocessing helpers into pipeline flow.

postprocess_existing_output:
- Support CSV and Excel input, configurable paths, fillna for CSV.

tests:
- Add test_json_parsers.py for PROV_INFO_JSON parsing coverage.
- Add test_postprocess.py for date/list formatting and defau…
* Merged in bugfix/reimb_primary_issues (pull request #900)

Bugfix/reimb primary issues

* Update lesser of distribution prompt to preserve reimb term langauge

* Added prompt change to extract correct service when there are multiple sub-rates; Updated validate reimb term to prevent filtering out erm with valid rate

* Make reimb primary prompt change

* Revert "Make reimb primary prompt change"

This reverts commit 55f7d73b9cb523097c96ea50b6614c1db53b46d2.


Approved-by: Katon Minhas

* Merged in dtc_report (pull request #902)

Dtc report

* dtc_report_added

* lint format fixed

* Changed regex location call


Approved-by: Katon Minhas

* Merged in feature/historical-cost-analysis (pull request #901)

Feature/historical cost analysis

* Initial commit

* Finalize cost_analysis

* Black format

* Merged DEV into feature/historical-cost-analysis

* Refactor

* Black

* Merged DEV into feature/historical-cost-analysis


Approved-by: Siddhant Medar

* Merged in feature/ai-pr-review-agent (pull request #906)

Add AI code review agent to pull request pipeline

* Add AI code review agent to pull request pipeline

Adds a pull-requests pipeline that runs CI checks (lint, type check,
unit tests) followed by an AI code review step. The AI review uses
OIDC to authenticate with AWS Bedrock - no hardcoded AWS keys. It
clones the code-review-agent repo and posts a review comment on the PR.

* Fix AI code review step: install git in python:3.12-slim image

* Trigger pipeline

* Trigger pipeline

* Trigger pipeline

* Trigger pipeline

* Trigger pipeline

* Trigger pipeline

* Trigger pipeline

* Remove debug token decode line

* Update guide: all checklist items complete, agent working

* Remove guide file from repo

* Trigger pipeline


Approved-by: Katon Minhas

* Merged in DAIP2-1980-aarete-derived-effective-dt-issues (pull request #904)

DAIP2-1980 aarete derived effective dt issues

* fixed earlier of a and b

* prompt update

* prompt shortened

* test changes reverted

* Merge branch 'DEV' into DAIP2-1980-aarete-derived-effective-dt-issues

* test changes reverted

* Merged DEV into DAIP2-1980-aarete-derived-effective-dt-issues

* Fix effective date prompt

* Replace em-dashes with readable version


Approved-by: Katon Minhas

* Merged in feature/DAIP2-2023-eliminate-full-context-processing (pull request #905)

Feature/DAIP2-2023 eliminate full context processing

* testing full context fields

* remove full context processing

* merge Dev with DAIP2-2-23

* full context removal in client codes

* AARETE_DERIVED_PROVIDER_NAME field changes

* Merged DEV into feature/DAIP2-2023-eliminate-full-context-processing

* optimized provider name

* black format fix

* contract title fixes

* PAYER NAME AUTO RENEWAL IND fixes

* Merged DEV into feature/DAIP2-2023-eliminate-full-context-processing

* Merge branch 'DEV' into feature/DAIP2-2023-eliminate-full-context-processing

* Remove prints


Approved-by: Katon Minhas

* Merged in feature/code_optimization (pull request #903)

Feature/code optimization

* Ran Black

* made a small change in code_last_check, fixed so it returns string and not single char

* Made changes to make sure that default_ind postprocess only happens to the cc output and not dashboard

* Merge bugfix/default_ind_postprocess into feature/code_optimization

- Parent-child: child_rank column init and cols_to_keep filter
- Postprocess: default_ind only on cc output
- code_last_check: parser str/list return handling + exception logging
- Prompt: FIELD ASSIGNMENT for code extraction (no CRITICAL prefix)

* More prompt changes and debugging print statements

* Added system to group same service term + bill type cd + claim type cd and then parallelize the code extraction (will improve consistency)

* Revert one-time PROV_INFO_JSON ad hoc logic; retain json_utils and output format

- Remove temporary postprocess step that filled empty TIN in PROV_INFO_JSON from
  FILENAME_TIN (fill_prov_info_tin_from_filename_ti…
* Merged in DAIP2-2121-prov-info-fields-issue-fixes (pull request #908)

empty prov_info_json fixed

* empty prov_info_json fixed

* Merged DEV into DAIP2-2121-prov-info-fields-issue-fixes

* format of PROV_OTHER_TIN fixed

* Revert "format of PROV_OTHER_TIN fixed"

This reverts commit 580847de03265520b1b4fad473bbf38ef1573753.

* formatting and deduplication

* pipeline error fixed

* test cases added

* pipeline error fixed


Approved-by: Katon Minhas

* Merged in feature/context-caching (pull request #909)

Feature/context caching

* Initial commit - context caching for DYNAMIC_PRIMARY

* implement context caching for all relevant prompts

* Remove option to not context cache

* IndentationError fixed

* Merge branch 'DEV' into feature/context-caching

* Merge and format

* Move documentation

* Merged DEV into feature/context-caching

* Update unit tests

* Merged DEV into feature/context-caching

* Update signatures

* Fix test coverage gap


Approved-by: Praneel Panchigar
Approved-by: Karan Desai

* Merged in bugfix/DAIP2-2138-reimbursement-primary-testing (pull request #910)

Bugfix/DAIP2-2138 reimbursement primary testing

* updated table instructions for reimb term extraction

* updated split tables to include header rows

* issue fix

* Merged DEV into bugfix/DAIP2-2138-reimbursement-primary-testing

* black format fix


Approved-by: Katon Minhas

* Merged in feature/doczy_reports (pull request #911)

Feature/doczy reports

* Added post_doczy_reports

* black format fix

* Merged DEV into feature/doczy_reports

* fixed code review


Approved-by: Katon Minhas

* Merged in feature/median-cost-analysis (pull request #912)

Add median

* Add median


Approved-by: Siddhant Medar


Approved-by: Siddhant Medar
2026-03-16 19:39:05 +00:00

262 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Context Caching Implementation - Complete
## Summary
Successfully implemented context caching for **6 high-value prompts** across all 3 client pipelines. This enables Anthropic's prompt caching at the exhibit/context level, where the same context is cached and reused across multiple field extractions, reducing token costs by **~84%** for repeated context processing.
### Prompts with Context Caching
1. **DYNAMIC_PRIMARY** (pilot) - Primary term field extraction
2. **EXHIBIT_LEVEL** - Exhibit-level metadata extraction
3. **DYNAMIC_ASSIGNMENT** - Dynamic term assignment to exhibit rows
4. **REIMB_DATES_ASSIGNMENT** - Reimbursement date assignment (specialized)
5. **LESSER_OF_DISTRIBUTION** - Lesser-of logic distribution across codes
6. **LESSER_OF_CHECK** - Lesser-of presence validation
### Pipelines Updated
-**bcbs_promise** - All 5 applicable functions updated
-**clover** - All 5 applicable functions updated
-**saas** - All 5 applicable functions updated
## What Changed
### 1. Extended LLM API (`llm_utils.py`)
Added `context_for_caching` parameter throughout the call chain:
- `invoke_claude()` - New optional parameter
- `_build_claude_3_request_body()` - Structures multi-block messages with cache control
- `get_cache_key()` - Includes context in cache key generation
- `local_claude_3_and_up()` - Passes parameter through
- `ec2_claude_3_and_up()` - Passes parameter through
**Key Innovation**: Messages now support multiple content blocks where specific blocks can be marked for caching:
```python
"messages": [{
"role": "user",
"content": [
{
"type": "text",
"text": "Large exhibit text (40k tokens)",
"cache_control": {"type": "ephemeral"} # CACHED
},
{
"type": "text",
"text": "Field-specific question (200 tokens)" # NOT CACHED
}
]
}]
```
### 2. Updated Existing Prompt Templates (`prompt_templates.py`)
Updated 6 existing functions to always split prompts into cacheable and fresh components:
1. **DYNAMIC_PRIMARY()** - Caches exhibit text, field question stays fresh
2. **EXHIBIT_LEVEL()** - Caches exhibit text, field questions stay fresh
3. **DYNAMIC_ASSIGNMENT()** - Caches exhibit simplified text, term questions stay fresh
4. **REIMB_DATES_ASSIGNMENT()** - Specialized for REIMB_DATES assignment
5. **LESSER_OF_DISTRIBUTION()** - Caches exhibit text and cross-exhibit context
6. **LESSER_OF_CHECK()** - Caches exhibit title context
Each returns `(context_text, prompt, parser)` instead of `(prompt, parser)`.
These functions now always return `(context_text, prompt, parser)` for context caching.
### 3. Updated All Client Prompt Calls
Updated functions across all 3 pipelines:
**bcbs_promise/prompts/prompt_calls.py**:
- `prompt_exhibit_level()`
- `prompt_dynamic_primary()`
- `prompt_dynamic_assignment()`
- `prompt_lesser_of_distribution()`
- `prompt_lesser_of_check()`
**clover/prompts/prompt_calls.py**:
- `prompt_exhibit_level()`
- `prompt_dynamic_primary()`
- `prompt_dynamic_assignment()`
- `prompt_lesser_of_distribution()`
- `prompt_lesser_of_check()`
**saas/prompts/prompt_calls.py**:
- `prompt_exhibit_level()`
- `prompt_dynamic_primary()`
- `prompt_dynamic_assignment()`
- `prompt_lesser_of_distribution()`
- `prompt_lesser_of_check()`
Each function now:
1. Uses the original template function (always split for caching)
2. Receives `(context_text, prompt, parser)` tuple
3. Passes `context_for_caching=context_text` to `invoke_claude()`
4. Logs context length for monitoring
## Cost Impact Analysis
### Current Structure (Before)
1. **System message** (cached): Field extraction instruction (~2k tokens)
2. **User message** (NOT cached): Combined exhibit + field question (~40k tokens)
For 20 fields on same exhibit:
- Instruction: 2k × 1 creation = cached once ✓
- Content: 40k × 20 calls = 800k tokens at $0.003/1k = **$2.40**
### New Structure (After)
1. **System message** (cached): Field extraction instruction (~2k tokens)
2. **User message block 1** (cached): Exhibit context (~40k tokens)
3. **User message block 2** (not cached): Field question (~200 tokens)
For 20 fields on same exhibit:
- Instruction: 2k × 1 creation = cached once ✓
- Context: 40k × 1 creation at $0.00375/1k = $0.15
- Context: 40k × 19 reads at $0.0003/1k = $0.228
- Field questions: 20 × 200 tokens at $0.003/1k = $0.012
- **Total: $0.39 (84% cost reduction)**
### Break-Even Analysis
- **1st field**: Pay 25% premium for cache creation
- **2nd field**: Start saving with 90% cheaper cache reads
- **3+ fields**: Massive savings accumulate
## How It Works
### Caching Layers (Claude API)
```
Layer 1: System Instruction (cached) ← Already implemented
Layer 2: Exhibit Context (cached) ← NEW - This implementation
Layer 3: Field Question (fresh) ← Changes per call
```
### Flow Example
```python
# Processing LOB field for exhibit
context_text, prompt, parser = DYNAMIC_PRIMARY(
exhibit_text="[40k token exhibit]",
field_name="LOB",
field_prompt="Line of Business definition",
)
llm_utils.invoke_claude(
prompt=prompt, # Just the field question
context_for_caching=context_text, # Exhibit text (cached)
instruction=DYNAMIC_PRIMARY_INSTRUCTION(), # Rules (already cached)
cache=True
)
# First call: Cache creation for exhibit
# Cost: (2k instruction + 40k context) × cache multiplier + 200 tokens fresh
# Processing PROGRAM field for SAME exhibit
context_text, prompt, parser = DYNAMIC_PRIMARY(
exhibit_text="[SAME 40k token exhibit]", # Same content
field_name="PROGRAM",
field_prompt="Program definition",
)
llm_utils.invoke_claude(
prompt=prompt, # Different field question
context_for_caching=context_text, # SAME exhibit (cache hit!)
instruction=DYNAMIC_PRIMARY_INSTRUCTION(),
cache=True
)
# Second call: Cache read for exhibit
# Cost: (2k + 40k) × cache read rate (90% cheaper) + 200 tokens fresh
```
## Testing
Created comprehensive test suite in `src/tests/test_context_caching.py`:
`test_dynamic_primary_returns_three_values()` - Validates always-split signature
`test_dynamic_primary_original_still_works()` - Backward compatibility
`test_build_request_body_with_context_caching()` - Message structure verification
`test_build_request_body_without_context_caching()` - Fallback behavior
`test_cache_key_includes_context()` - Cache key uniqueness
## Monitoring & Validation
To verify the implementation is working:
1. **Check usage logs** for cache metrics:
```python
# In usage_tracking.py logs, look for:
cache_creation_tokens: 40000 # First call
cache_read_tokens: 40000 # Subsequent calls
```
2. **Monitor cost per file** in usage reports:
- Should see dramatic cost reduction for files with many dynamic fields
- Exhibits with 10+ fields should show 80%+ savings on exhibit processing
3. **Log analysis**:
```
DEBUG: Context length for caching: 42567 chars
```
This confirms context is being passed to caching layer.
## Implementation Status
### ✅ Completed
All high-value prompts have been migrated to context caching across all 3 client pipelines:
1. **DYNAMIC_PRIMARY** ✅ - Primary term field extraction (pilot implementation)
2. **EXHIBIT_LEVEL** ✅ - Exhibit-level metadata extraction
3. **DYNAMIC_ASSIGNMENT** ✅ - Dynamic term assignment to exhibit rows
4. **REIMB_DATES_ASSIGNMENT** ✅ - Reimbursement date assignment (specialized)
5. **LESSER_OF_DISTRIBUTION** ✅ - Lesser-of logic distribution across codes
6. **LESSER_OF_CHECK** ✅ - Lesser-of presence validation
**Cost Savings**: Estimated 80-85% reduction in token costs for repeated exhibit/context processing across these 6 prompts.
### Future Considerations
**Lower Priority Candidates** (evaluate after monitoring current implementation):
- **METHODOLOGY_BREAKOUT** - Could cache reimbursement terms for multiple breakout operations
- **Other exhibit-level prompts** - If processing changes to single-field-at-a-time pattern
**Monitoring Required**:
- Track cache hit rates and actual cost savings in production
- Validate that 5-minute cache TTL aligns with typical processing patterns
- Identify any additional prompts with repeated context usage patterns
### Implementation Pattern (For Future Extensions)
For any new prompt to extend:
1. Update `[PROMPT_NAME]()` to return `(context, prompt, parser)`
2. Update corresponding `prompt_[name]()` function to use caching version
3. Pass context via `context_for_caching` parameter
4. Monitor cache metrics to validate savings
## Backward Compatibility
✅ Original `DYNAMIC_PRIMARY()` function remains unchanged
✅ Other templates continue to work without modification
✅ `context_for_caching` parameter is optional (defaults to None)
✅ When None, behavior is identical to previous implementation
✅ All tests should pass without modification
## Files Modified
**Core Infrastructure:**
- [src/utils/llm_utils.py](src/utils/llm_utils.py) - Extended API with `context_for_caching` parameter
- [src/prompts/prompt_templates.py](src/prompts/prompt_templates.py) - Added 6 context-caching template variants
**Pipeline Updates (All 3 Clients):**
- [src/pipelines/clients/bcbs_promise/prompts/prompt_calls.py](src/pipelines/clients/bcbs_promise/prompts/prompt_calls.py) - Updated 5 functions
- [src/pipelines/clients/clover/prompts/prompt_calls.py](src/pipelines/clients/clover/prompts/prompt_calls.py) - Updated 5 functions
- [src/pipelines/saas/prompts/prompt_calls.py](src/pipelines/saas/prompts/prompt_calls.py) - Updated 5 functions
**Testing & Documentation:**
- [src/tests/test_context_caching.py](src/tests/test_context_caching.py) - Comprehensive test suite
- [CONTEXT_CACHING_IMPLEMENTATION.md](CONTEXT_CACHING_IMPLEMENTATION.md) - This documentation
## Technical Notes
- Anthropic prompt caching requires minimum 1024 tokens for cache block
- Cache TTL is 5 minutes for `ephemeral` type
- Only works with Claude 3.5+ Sonnet v2 models (checked via `_supports_prompt_cache()`)
- Cache keys include both instruction and context to ensure uniqueness
- Multiple content blocks in user messages is supported by Bedrock Messages API