Skip to content

Map hostedtool.CodeInterpreter to the Anthropic code_execution tool and parse its result blocks - #637

Open
PratikDhanave (PratikDhanave) wants to merge 3 commits into
microsoft:mainfrom
PratikDhanaveFork:anthropic-code-interpreter
Open

Map hostedtool.CodeInterpreter to the Anthropic code_execution tool and parse its result blocks#637
PratikDhanave (PratikDhanave) wants to merge 3 commits into
microsoft:mainfrom
PratikDhanaveFork:anthropic-code-interpreter

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

What

Wire the hosted *hostedtool.CodeInterpreter marker into the Anthropic provider (provider/anthropicprovider/agent.go):

  • Request builder: add a tool-loop branch that maps *hostedtool.CodeInterpreter onto Anthropic's server-side code_execution tool (CodeExecutionTool20250825Param), appended to params.Tools.
  • Response parsing: add buildBlock cases for the server_tool_use (code_execution) and code_execution_tool_result blocks, surfacing them as structured message.CodeInterpreterToolCallContent (code as a text/x-python DataContent) and message.CodeInterpreterToolResultContent (stdout/stderr/error as TextContent, output files as HostedFileContent).

Why

This is the code-execution sibling of the existing web-search hosted-tool support. The OpenAI Responses provider already maps *hostedtool.CodeInterpreter (responses.go, case *hostedtool.CodeInterpreter) and emits the same structured CodeInterpreterToolCall/CodeInterpreterToolResult content. The Anthropic provider had no hosted-tool branch and no code_execution result parsing, so hosted code interpretation silently did nothing on Anthropic. This change brings Anthropic in line with the OpenAI/.NET structured mapping so the same agent code works across providers.

Tests

Added to the canonical agent_test.go (black-box, reusing the existing httptest harness):

  • TestCodeInterpreterToolMapsToCodeExecution asserts the request builder emits a code_execution / code_execution_20250825 tool in tools.
  • TestCodeInterpreterResultBlocksBecomeStructuredContent feeds server_tool_use + code_execution_tool_result blocks and asserts structured CodeInterpreterToolCallContent (decoded Python source) and CodeInterpreterToolResultContent (stdout + hosted file output) are produced.

go build ./..., go vet ./provider/anthropicprovider/..., and go test ./provider/anthropicprovider/... all pass.

Open design questions

  • Tool version: this pins CodeExecutionTool20250825Param. The SDK also exposes newer variants (20260120, 20260521); should the version be configurable (e.g. via AdditionalProperties) or track the latest?
  • Container / file inputs: hostedtool.CodeInterpreter.Inputs (hosted file IDs) are not yet forwarded — Anthropic's code_execution container model differs from OpenAI's. Follow-up if pre-seeding files is needed.
  • Streaming accumulation: non-streaming is fully mapped; in streaming the server_tool_use input arrives via input_json_delta and is not yet accumulated into the call's code block. Worth a follow-up if streaming code capture is required.
  • Encrypted results: encrypted_stdout (EncryptedCodeExecutionResultBlock) is not surfaced; only plaintext stdout/stderr and output files are mapped today.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 23, 2026
@github-actions

This comment has been minimized.

Wire the hosted *hostedtool.CodeInterpreter marker into the Anthropic
provider so it enables the server-side code_execution tool, and parse the
resulting server_tool_use / code_execution_tool_result response blocks into
structured message.CodeInterpreterToolCallContent and
CodeInterpreterToolResultContent. This mirrors the existing OpenAI Responses
provider mapping so hosted code interpretation behaves the same across
providers.
@github-actions

This comment has been minimized.

# Conflicts:
#	provider/anthropicprovider/agent.go
#	provider/anthropicprovider/agent_test.go
@github-actions

This comment has been minimized.

@PratikDhanave
PratikDhanave (PratikDhanave) marked this pull request as ready for review August 4, 2026 06:06
@PratikDhanave
PratikDhanave (PratikDhanave) requested a review from a team as a code owner August 4, 2026 06:06
Copilot AI lite review requested due to automatic review settings August 4, 2026 06:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds hosted code-interpreter support to the Anthropic provider by mapping the framework’s *hostedtool.CodeInterpreter marker to Anthropic’s server-side code_execution tool, and by parsing corresponding response blocks into the framework’s structured message.CodeInterpreterToolCallContent / message.CodeInterpreterToolResultContent content types.

Changes:

  • Map *hostedtool.CodeInterpreter to Anthropic code_execution_20250825 tool parameters in request construction.
  • Parse Anthropic server_tool_use (code_execution) blocks into CodeInterpreterToolCallContent with base64-encoded Python source (text/x-python).
  • Parse Anthropic code_execution_tool_result blocks into CodeInterpreterToolResultContent including stdout/stderr and hosted file outputs, with new black-box tests covering request/response behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
provider/anthropicprovider/agent.go Adds CodeInterpreter → Anthropic code_execution tool mapping and response block parsing for server-side code execution.
provider/anthropicprovider/agent_test.go Adds tests validating request tool emission and structured parsing of code execution call/result blocks.

Comment on lines +324 to +335
if res.Stderr != "" {
result.Outputs = append(result.Outputs, &message.TextContent{
Text: res.Stderr,
ContentHeader: message.ContentHeader{RawRepresentation: res},
})
}
if res.ErrorCode != "" {
result.Outputs = append(result.Outputs, &message.TextContent{
Text: string(res.ErrorCode),
ContentHeader: message.ContentHeader{RawRepresentation: res},
})
}
# Conflicts:
#	provider/anthropicprovider/agent_test.go
@github-actions github-actions Bot added area:provider Changes files in the provider area area:provider/anthropic Changes files in the provider / anthropic area size:large At most 300 changed lines across at most 10 files pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Parity review: PR #637 — Anthropic code_execution hosted-tool support

This PR ports the hosted CodeInterpreter tool to the Anthropic provider. The general approach (mapping hostedtool.CodeInterpreterCodeExecutionTool20250825Param, parsing server_tool_use/code_execution_tool_result blocks into structured CodeInterpreterToolCallContent/CodeInterpreterToolResultContent) is correctly aligned with the Python implementation in python/packages/anthropic/agent_framework_anthropic/_chat_client.py.

Two cross-SDK divergences were found:

1. stderr and error_code mapped to TextContent instead of ErrorContent (actionable)

Python maps both stderr and error_code to Content.from_error() (→ ErrorContent). The Go implementation uses &message.TextContent{} for both. Callers that branch on content type to detect errors will behave differently across SDKs. See inline comment at line 333.

2. Tool-call input encoding (DataContent vs TextContent) (needs clarification)

Python wraps the raw input as TextContent(text=str(input)). Go extracts the "code" key and stores it base64-encoded as DataContent{MediaType: "text/x-python"}. This is more structured but is an intentional divergence. If deliberate, it should be documented. See inline comment at line 316.


The parity-approved label has been removed because there are two cross-SDK semantic differences that should be resolved or explicitly documented before the PR is considered parity-clean.

No exported Go API surface was added by this PR (the changed types CodeInterpreterToolCallContent / CodeInterpreterToolResultContent already existed); the public-api-change label is not warranted.

Generated by Go API Consistency Review Agent · sonnet46 · 48.8 AIC · ⌖ 5.81 AIC · ⊞ 6K ·

@github-actions github-actions Bot removed the parity-approved Go API consistency review found no parity issues label Aug 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by Go API Consistency Review Agent · sonnet46 · 48.8 AIC · ⌖ 5.81 AIC · ⊞ 6K

})
}
if res.Stderr != "" {
result.Outputs = append(result.Outputs, &message.TextContent{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parity issue: stderr mapped to TextContent instead of ErrorContent

The upstream Python implementation (agent_framework_anthropic/_chat_client.py, case "code_execution_tool_result") maps stderr to Content.from_error(message=content_block.content.stderr), which produces an ErrorContent node. Here the Go implementation maps stderr to &message.TextContent{}. Callers that switch on content type (e.g., to distinguish diagnostic output from normal output) will behave differently across SDKs.

Suggestion: use &message.ErrorContent{Message: res.Stderr, ...} for stderr to match Python semantics. Similarly, error_code (line 339) maps to TextContent in Go but to Content.from_error() in Python — both should use ErrorContent.

Upstream reference: python/packages/anthropic/agent_framework_anthropic/_chat_client.py lines 1338–1356.

},
}
}
contents = append(contents, call)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parity note: code_execution tool-call input encoding differs from Python

The Python implementation (_chat_client.py, line 1252–1265) wraps the raw input block as Content.from_text(text=str(content_block.input)) — a plain TextContent containing the string representation of the input dict.

This Go implementation extracts the "code" key from the JSON payload and stores it base64-encoded as DataContent with media_type: text/x-python. While arguably more structured (and analogous to how OpenAI Responses surfaces it), this is a deliberate cross-SDK divergence: a consumer inspecting CodeInterpreterToolCallContent.Inputs[0] will receive a DataContent in Go but a TextContent in Python.

If this encoding difference is intentional, please document it (e.g., in a CHANGELOG entry or an inline comment noting the divergence from Python). If it should align, switch to &message.TextContent{Text: code} or align the Python side to emit DataContent.

@github-actions github-actions Bot added failed-auto-risk Automatic risk classification was inconclusive or failed and removed pending-auto-risk Automatic risk classification is in progress labels Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:provider/anthropic Changes files in the provider / anthropic area area:provider Changes files in the provider area failed-auto-risk Automatic risk classification was inconclusive or failed size:large At most 300 changed lines across at most 10 files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants