diff --git a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py index 3ec953b5bb1..367362c7032 100644 --- a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py +++ b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py @@ -579,7 +579,9 @@ def _prepare_options( """ # Start with a copy of options, excluding keys we handle separately run_options: dict[str, Any] = { - k: v for k, v in options.items() if v is not None and k not in {"instructions", "response_format"} + k: v + for k, v in options.items() + if v is not None and k not in {"instructions", "response_format", "additional_beta_flags"} } # Framework-level options handled elsewhere; do not forward as raw Anthropic request kwargs. run_options.pop("allow_multiple_tool_calls", None) @@ -592,7 +594,9 @@ def _prepare_options( # This includes underscore-prefixed internal objects (like _function_middleware_pipeline) # and framework kwargs like 'thread' and 'middleware'. filtered_kwargs = { - k: v for k, v in kwargs.items() if not k.startswith("_") and k not in {"thread", "middleware"} + k: v + for k, v in kwargs.items() + if not k.startswith("_") and k not in {"thread", "middleware", "additional_beta_flags"} } _apply_option_translations(filtered_kwargs) run_options.update(filtered_kwargs) diff --git a/python/packages/anthropic/tests/test_anthropic_client.py b/python/packages/anthropic/tests/test_anthropic_client.py index 0992c0ed91f..8876823cc61 100644 --- a/python/packages/anthropic/tests/test_anthropic_client.py +++ b/python/packages/anthropic/tests/test_anthropic_client.py @@ -1270,6 +1270,48 @@ async def test_prepare_options_excludes_stream_option( assert "stream" not in run_options +async def test_prepare_options_consumes_additional_beta_flags( + mock_anthropic_client: MagicMock, +) -> None: + """Per-run additional_beta_flags must be folded into betas, not forwarded raw. + + Regression test for https://github.com/microsoft/agent-framework/issues/5764: + the key survived into run_options and was passed straight through to + ``AsyncMessages.create()``, which rejects it with + ``TypeError: got an unexpected keyword argument 'additional_beta_flags'``. + """ + client = create_test_anthropic_client(mock_anthropic_client) + + messages = [Message(role="user", contents=["Hello"])] + chat_options: dict[str, Any] = {"additional_beta_flags": ["extended-cache-ttl-2025-04-11"]} + + run_options = client._prepare_options(messages, chat_options) + + assert "additional_beta_flags" not in run_options + assert "extended-cache-ttl-2025-04-11" in run_options["betas"] + + +async def test_prepare_options_drops_additional_beta_flags_passed_as_kwarg( + mock_anthropic_client: MagicMock, +) -> None: + """additional_beta_flags must also be excluded when passed as a raw kwarg, + not just via the options dict. + + Flagged in code review on the fix for #5764: the initial fix only excluded + the key from the options-dict copy, but filtered_kwargs (built from + **kwargs at the call site) had no equivalent exclusion, so + ``_prepare_options(messages, {}, additional_beta_flags=[...])`` would still + forward the raw key and reproduce the same TypeError. + """ + client = create_test_anthropic_client(mock_anthropic_client) + + messages = [Message(role="user", contents=["Hello"])] + + run_options = client._prepare_options(messages, {}, additional_beta_flags=["extended-cache-ttl-2025-04-11"]) + + assert "additional_beta_flags" not in run_options + + async def test_prepare_options_filters_internal_kwargs( mock_anthropic_client: MagicMock, ) -> None: