diff --git a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py index c1d1ac26c4..5f3dfa83c5 100644 --- a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py +++ b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py @@ -455,7 +455,13 @@ def _prepare_options( # Add the structured outputs beta flag run_options["betas"].add(STRUCTURED_OUTPUTS_BETA_FLAG) - run_options.update(kwargs) + # Filter out framework kwargs that should not be passed to the Anthropic API. + # 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"} + } + run_options.update(filtered_kwargs) return run_options def _prepare_betas(self, options: Mapping[str, Any]) -> set[str]: diff --git a/python/packages/anthropic/tests/test_anthropic_client.py b/python/packages/anthropic/tests/test_anthropic_client.py index 5df7f585f3..75c2144258 100644 --- a/python/packages/anthropic/tests/test_anthropic_client.py +++ b/python/packages/anthropic/tests/test_anthropic_client.py @@ -479,6 +479,36 @@ async def test_prepare_options_with_top_p(mock_anthropic_client: MagicMock) -> N assert run_options["top_p"] == 0.9 +async def test_prepare_options_filters_internal_kwargs(mock_anthropic_client: MagicMock) -> None: + """Test _prepare_options filters internal framework kwargs. + + Internal kwargs like _function_middleware_pipeline, thread, and middleware + should be filtered out before being passed to the Anthropic API. + """ + chat_client = create_test_anthropic_client(mock_anthropic_client) + + messages = [ChatMessage(role="user", text="Hello")] + chat_options: ChatOptions = {} + + # Simulate internal kwargs that get passed through the middleware pipeline + internal_kwargs = { + "_function_middleware_pipeline": object(), + "_chat_middleware_pipeline": object(), + "_any_underscore_prefixed": object(), + "thread": object(), + "middleware": [object()], + } + + run_options = chat_client._prepare_options(messages, chat_options, **internal_kwargs) + + # Internal kwargs should be filtered out + assert "_function_middleware_pipeline" not in run_options + assert "_chat_middleware_pipeline" not in run_options + assert "_any_underscore_prefixed" not in run_options + assert "thread" not in run_options + assert "middleware" not in run_options + + # Response Processing Tests diff --git a/python/packages/core/tests/workflow/test_sub_workflow.py b/python/packages/core/tests/workflow/test_sub_workflow.py index c413190a24..33333d2906 100644 --- a/python/packages/core/tests/workflow/test_sub_workflow.py +++ b/python/packages/core/tests/workflow/test_sub_workflow.py @@ -599,7 +599,7 @@ async def test_sub_workflow_checkpoint_restore_no_duplicate_requests() -> None: # Get checkpoint checkpoints = await storage.list_checkpoints(workflow1.id) - checkpoint_id = max(checkpoints, key=lambda cp: cp.timestamp).checkpoint_id + checkpoint_id = max(checkpoints, key=lambda cp: cp.iteration_count).checkpoint_id # Step 2: Resume workflow from checkpoint workflow2 = _build_checkpoint_test_workflow(storage)