fix(anthropic): auto-inject compact beta header for context_management - #27593
fix(anthropic): auto-inject compact beta header for context_management#27593Jwrede wants to merge 3 commits into
Conversation
get_anthropic_beta_list() did not detect context_management in optional_params, so Bedrock InvokeModel requests with compaction never received the required "compact-2026-01-12" in anthropic_beta. Bedrock rejects context_management without the beta header with "Extra inputs are not permitted". The direct Anthropic path already handled this via _ensure_context_management_beta_header (HTTP headers), but the Bedrock path builds its beta list from get_anthropic_beta_list() which feeds the request body's anthropic_beta array. Fixes BerriAI#27532
|
@greptileai review |
Greptile SummaryThis PR fixes a bug where Bedrock InvokeModel rejected requests using
Confidence Score: 3/5The fix is correct for the Anthropic dict format but leaves the OpenAI list format unhandled, which could reproduce the original rejection for callers using that shape. The core fix works for the reported case (dict-format context_management on Bedrock), but the new code diverges from the parallel implementation in _ensure_context_management_beta_header by not handling context_management passed as a plain list. Any caller routing through get_anthropic_beta_list with a list-shaped input will silently receive no beta header, reproducing the original Bedrock rejection for that input shape. litellm/llms/anthropic/common_utils.py — the list-format branch is missing from the new context_management detection block.
|
| Filename | Overview |
|---|---|
| litellm/llms/anthropic/common_utils.py | Adds context_management beta detection to get_anthropic_beta_list(), but only handles the Anthropic dict format — the OpenAI list format supported by the direct Anthropic path is not covered, leaving a gap for that input shape. |
| tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py | Adds three new unit tests for the context_management beta logic; all use mock-only patterns correctly, but the OpenAI list format for context_management is not exercised. |
Reviews (1): Last reviewed commit: "fix(anthropic): auto-inject compact beta..." | Re-trigger Greptile
| if optional_params: | ||
| context_management = optional_params.get("context_management") | ||
| if isinstance(context_management, dict) and "edits" in context_management: | ||
| for edit in context_management.get("edits", []): | ||
| edit_type = edit.get("type", "") | ||
| if edit_type in ("compact_20260112", "compaction"): | ||
| betas.append( | ||
| ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value | ||
| ) | ||
| else: | ||
| betas.append( | ||
| ANTHROPIC_BETA_HEADER_VALUES.CONTEXT_MANAGEMENT_2025_06_27.value | ||
| ) |
There was a problem hiding this comment.
The new code only handles
context_management when it's a dict with an "edits" key, but _ensure_context_management_beta_header (the direct Anthropic path) also supports the OpenAI list format (context_management as a plain list of edit objects). If a caller passes context_management as a list to the Bedrock/Vertex path, the beta headers will silently not be added, causing the same "Extra inputs are not permitted" rejection that this PR aims to fix.
| if optional_params: | |
| context_management = optional_params.get("context_management") | |
| if isinstance(context_management, dict) and "edits" in context_management: | |
| for edit in context_management.get("edits", []): | |
| edit_type = edit.get("type", "") | |
| if edit_type in ("compact_20260112", "compaction"): | |
| betas.append( | |
| ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value | |
| ) | |
| else: | |
| betas.append( | |
| ANTHROPIC_BETA_HEADER_VALUES.CONTEXT_MANAGEMENT_2025_06_27.value | |
| ) | |
| if optional_params: | |
| context_management = optional_params.get("context_management") | |
| edits: list = [] | |
| if isinstance(context_management, dict) and "edits" in context_management: | |
| edits = context_management.get("edits", []) | |
| elif isinstance(context_management, list): | |
| edits = context_management | |
| for edit in edits: | |
| edit_type = edit.get("type", "") | |
| if edit_type in ("compact_20260112", "compaction"): | |
| betas.append( | |
| ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value | |
| ) | |
| else: | |
| betas.append( | |
| ANTHROPIC_BETA_HEADER_VALUES.CONTEXT_MANAGEMENT_2025_06_27.value | |
| ) |
There was a problem hiding this comment.
Good catch -- fixed in dcba26c. Now handles both the Anthropic dict format and the OpenAI list format, matching the logic in _ensure_context_management_beta_header. Added a test for the list path too.
|
|
||
|
|
||
| class TestGetAnthropicBetaListContextManagement: | ||
| """ | ||
| Regression tests for https://github.com/BerriAI/litellm/issues/27532 | ||
| get_anthropic_beta_list must include compact/context-management betas | ||
| when context_management is in optional_params, so Bedrock InvokeModel | ||
| receives the required anthropic_beta field. | ||
| """ | ||
|
|
||
| def test_compact_edit_adds_compact_beta(self): | ||
| from litellm.llms.anthropic.common_utils import AnthropicModelInfo | ||
|
|
||
| info = AnthropicModelInfo() | ||
| betas = info.get_anthropic_beta_list( | ||
| model="claude-sonnet-4-6", | ||
| optional_params={ | ||
| "context_management": { | ||
| "edits": [{"type": "compact_20260112"}], | ||
| } | ||
| }, | ||
| ) | ||
| assert "compact-2026-01-12" in betas | ||
|
|
||
| def test_non_compact_edit_adds_context_management_beta(self): | ||
| from litellm.llms.anthropic.common_utils import AnthropicModelInfo | ||
|
|
||
| info = AnthropicModelInfo() | ||
| betas = info.get_anthropic_beta_list( | ||
| model="claude-sonnet-4-6", | ||
| optional_params={ | ||
| "context_management": { | ||
| "edits": [{"type": "summarize"}], | ||
| } | ||
| }, | ||
| ) | ||
| assert "context-management-2025-06-27" in betas | ||
|
|
||
| def test_no_context_management_no_extra_betas(self): | ||
| from litellm.llms.anthropic.common_utils import AnthropicModelInfo | ||
|
|
||
| info = AnthropicModelInfo() | ||
| betas = info.get_anthropic_beta_list( | ||
| model="claude-sonnet-4-6", | ||
| optional_params={"max_tokens": 100}, | ||
| ) | ||
| assert "compact-2026-01-12" not in betas | ||
| assert "context-management-2025-06-27" not in betas |
There was a problem hiding this comment.
Missing test for OpenAI list format
The three new tests only cover context_management as an Anthropic dict ({"edits": [...]}). The direct Anthropic path (_ensure_context_management_beta_header) also handles the OpenAI list format where context_management is a plain list of edit objects (e.g., [{"type": "compaction", ...}]). A test for this format would catch the gap identified in get_anthropic_beta_list where the list branch is absent.
There was a problem hiding this comment.
Added in dcba26c -- test_openai_list_format_adds_compact_beta covers the list branch.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The direct Anthropic path supports context_management as either a dict with an "edits" key or a plain list of edit objects. Mirror that logic in get_anthropic_beta_list so Bedrock/Vertex paths also inject the correct beta headers when the OpenAI list format is used.
jgowdy-godaddy
left a comment
There was a problem hiding this comment.
Nice fix! I noticed one edge case that might explain the 3/5 score from the bot:
Issue: When there are mixed edit types (e.g., one compact + one non-compact), the current loop adds a beta for each edit. This could result in BOTH compact-2026-01-12 AND context-management-2025-06-27 being added. Based on Anthropic's docs, if ANY edit is compact, only the compact beta should be used.
I've got a quick refactor + test case that should fix this and likely bump the bot score. Want me to open a PR against your branch, or would you prefer I just share the diff here for you to apply?
The changes are:
- Scan all edits first to check if any are compact
- If compact found, use only compact beta (more efficient, breaks early)
- Otherwise use context-management beta
- Add test for mixed edits
Happy to help get this to 5/5! 🚀
|
Here's the diff if you want to apply it directly: Changes to common_utils.pyif optional_params:
context_management = optional_params.get("context_management")
edits: list = []
if isinstance(context_management, dict) and "edits" in context_management:
edits = context_management.get("edits", [])
elif isinstance(context_management, list):
edits = context_management
# Check if ANY edit is compact - if so, use compact beta exclusively
has_compact = False
has_other_edits = False
for edit in edits:
edit_type = edit.get("type", "")
if edit_type in ("compact_20260112", "compaction"):
has_compact = True
break # Compact takes precedence
elif edit_type:
has_other_edits = True
if has_compact:
betas.append(ANTHROPIC_BETA_HEADER_VALUES.COMPACT_2026_01_12.value)
elif has_other_edits:
betas.append(
ANTHROPIC_BETA_HEADER_VALUES.CONTEXT_MANAGEMENT_2025_06_27.value
)New test case to adddef test_mixed_edits_uses_compact_beta(self):
"""When mixed edit types are present, compact should take precedence"""
from litellm.llms.anthropic.common_utils import AnthropicModelInfo
info = AnthropicModelInfo()
betas = info.get_anthropic_beta_list(
model="claude-sonnet-4-6",
optional_params={
"context_management": {
"edits": [
{"type": "summarize"},
{"type": "compact_20260112"},
],
}
},
)
assert "compact-2026-01-12" in betas
# Should NOT include both betas when compact is present
assert "context-management-2025-06-27" not in betas |
When mixed edit types are present (e.g. summarize + compact), only emit the compact beta header. Previously both betas were appended independently per edit.
|
@jgowdy-godaddy Good catch, fixed in 9e85c8b. When mixed edit types are present, compact now takes precedence and the context-management beta is not emitted alongside it. Added |
|
Friendly ping @ishaan-jaff @krrish-berri-2 -- this fixes Bedrock compaction failing with "Extra inputs are not permitted" (missing compact beta header). @jgowdy-godaddy's edge case feedback has been addressed. Ready for review. |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Summary
context_managementwith "Extra inputs are not permitted"get_anthropic_beta_list()did not detectcontext_managementin optional_params, so the requiredcompact-2026-01-12beta was never added to the request body'santhropic_betaarray_ensure_context_management_beta_header(HTTP headers), but the Bedrock path builds betas fromget_anthropic_beta_list()which feeds the bodyFixes #27532
Changes
litellm/llms/anthropic/common_utils.py: detectcontext_managementedits inget_anthropic_beta_list()and addcompact-2026-01-12for compact edits orcontext-management-2025-06-27for other editstests/test_litellm/llms/anthropic/test_anthropic_common_utils.py: 3 tests covering compact edit, non-compact edit, and no context_managementTest plan
test_compact_edit_adds_compact_beta-- context_management with compact_20260112 edit includes compact-2026-01-12test_non_compact_edit_adds_context_management_beta-- non-compact edits include context-management-2025-06-27test_no_context_management_no_extra_betas-- no context_management does not add extra betas