From 2511c28f9203f22d3050d6bd30654978bd15bc22 Mon Sep 17 00:00:00 2001 From: Mohammad Mohtashim <45242107+keenborder786@users.noreply.github.com> Date: Wed, 12 Nov 2025 20:44:51 +0500 Subject: [PATCH] feat(anthropic): support code_execution_20250825 (#33925) --- .../langchain_anthropic/chat_models.py | 19 ++--- .../cassettes/test_code_execution.yaml.gz | Bin 0 -> 10929 bytes ...gz => test_code_execution_old[v0].yaml.gz} | Bin ...gz => test_code_execution_old[v1].yaml.gz} | Bin .../integration_tests/test_chat_models.py | 79 +++++++++++++++++- 5 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 libs/partners/anthropic/tests/cassettes/test_code_execution.yaml.gz rename libs/partners/anthropic/tests/cassettes/{test_code_execution[v0].yaml.gz => test_code_execution_old[v0].yaml.gz} (100%) rename libs/partners/anthropic/tests/cassettes/{test_code_execution[v1].yaml.gz => test_code_execution_old[v1].yaml.gz} (100%) diff --git a/libs/partners/anthropic/langchain_anthropic/chat_models.py b/libs/partners/anthropic/langchain_anthropic/chat_models.py index f93456d88dc..e9f3b82b894 100644 --- a/libs/partners/anthropic/langchain_anthropic/chat_models.py +++ b/libs/partners/anthropic/langchain_anthropic/chat_models.py @@ -499,6 +499,8 @@ def _format_messages( content.append({**block, "content": tool_content}) elif block["type"] in ( "code_execution_tool_result", + "bash_code_execution_tool_result", + "text_editor_code_execution_tool_result", "mcp_tool_result", "web_search_tool_result", "web_fetch_tool_result", @@ -2543,7 +2545,6 @@ def _make_message_chunk_from_anthropic_event( message_chunk: AIMessageChunk | None = None # Reference: Anthropic SDK streaming implementation # https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/lib/streaming/_messages.py # noqa: E501 - if event.type == "message_start" and stream_usage: # Capture model name, but don't include usage_metadata yet # as it will be properly reported in message_delta with complete info @@ -2560,17 +2561,11 @@ def _make_message_chunk_from_anthropic_event( elif ( event.type == "content_block_start" and event.content_block is not None - and event.content_block.type - in ( - "tool_use", # Standard tool usage - "code_execution_tool_result", # Built-in code execution results - "document", - "redacted_thinking", - "mcp_tool_use", - "mcp_tool_result", - "server_tool_use", # Server-side tool usage - "web_search_tool_result", # Built-in web search results - "web_fetch_tool_result", # Built-in web fetch results, + and ( + "tool_result" in event.content_block.type + or "tool_use" in event.content_block.type + or "document" in event.content_block.type + or "redacted_thinking" in event.content_block.type ) ): if coerce_content_to_string: diff --git a/libs/partners/anthropic/tests/cassettes/test_code_execution.yaml.gz b/libs/partners/anthropic/tests/cassettes/test_code_execution.yaml.gz new file mode 100644 index 0000000000000000000000000000000000000000..dd71c3d67eccc498ceafc4004396b788c6390289 GIT binary patch literal 10929 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 None: @pytest.mark.vcr @pytest.mark.parametrize("output_version", ["v0", "v1"]) -def test_code_execution(output_version: Literal["v0", "v1"]) -> None: - """Note: this is a beta feature. +def test_code_execution_old(output_version: Literal["v0", "v1"]) -> None: + """Note: this tests the `code_execution_20250522` tool, which is now legacy. - TODO: Update to remove beta once generally available. + See the `test_code_execution` test below to test the current + `code_execution_20250825` tool. + + Migration guide: https://docs.claude.com/en/docs/agents-and-tools/tool-use/code-execution-tool#upgrade-to-latest-tool-version """ llm = ChatAnthropic( model=MODEL_NAME, # type: ignore[call-arg] @@ -1562,6 +1565,76 @@ def test_code_execution(output_version: Literal["v0", "v1"]) -> None: ) +@pytest.mark.default_cassette("test_code_execution.yaml.gz") +@pytest.mark.vcr +@pytest.mark.parametrize("output_version", ["v0", "v1"]) +def test_code_execution(output_version: Literal["v0", "v1"]) -> None: + """Note: this is a beta feature. + + TODO: Update to remove beta once generally available. + """ + llm = ChatAnthropic( + model=MODEL_NAME, # type: ignore[call-arg] + betas=["code-execution-2025-08-25"], + output_version=output_version, + ) + + tool = {"type": "code_execution_20250825", "name": "code_execution"} + llm_with_tools = llm.bind_tools([tool]) + + input_message = { + "role": "user", + "content": [ + { + "type": "text", + "text": ( + "Calculate the mean and standard deviation of " + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" + ), + }, + ], + } + response = llm_with_tools.invoke([input_message]) + assert all(isinstance(block, dict) for block in response.content) + block_types = {block["type"] for block in response.content} # type: ignore[index] + if output_version == "v0": + assert block_types == { + "text", + "server_tool_use", + "text_editor_code_execution_tool_result", + "bash_code_execution_tool_result", + } + else: + assert block_types == {"text", "server_tool_call", "server_tool_result"} + + # Test streaming + full: BaseMessageChunk | None = None + for chunk in llm_with_tools.stream([input_message]): + assert isinstance(chunk, AIMessageChunk) + full = chunk if full is None else full + chunk + assert isinstance(full, AIMessageChunk) + assert isinstance(full.content, list) + block_types = {block["type"] for block in full.content} # type: ignore[index] + if output_version == "v0": + assert block_types == { + "text", + "server_tool_use", + "text_editor_code_execution_tool_result", + "bash_code_execution_tool_result", + } + else: + assert block_types == {"text", "server_tool_call", "server_tool_result"} + + # Test we can pass back in + next_message = { + "role": "user", + "content": "Please add more comments to the code.", + } + _ = llm_with_tools.invoke( + [input_message, full, next_message], + ) + + @pytest.mark.default_cassette("test_remote_mcp.yaml.gz") @pytest.mark.vcr @pytest.mark.parametrize("output_version", ["v0", "v1"])