Skip to content

Python: Keep pending Anthropic server tool calls as server_tool_use - #9513

Open
Shivam Sharma (ShivamSharma43) wants to merge 1 commit into
microsoft:mainfrom
ShivamSharma43:fix/9478-anthropic-server-tool-use
Open

Shivam Sharma (ShivamSharma43) wants to merge 1 commit into
microsoft:mainfrom
ShivamSharma43:fix/9478-anthropic-server-tool-use

Conversation

@ShivamSharma43

Copy link
Copy Markdown
Contributor

Motivation & Context

When Claude calls a local tool and a server tool (for example get_web_search_tool()) in the same turn, the response ends with a local tool_use plus a pending server_tool_use. The parser keeps the hosted call as an informational function_call with hosted=True, but _prepare_message_for_anthropic sends every function_call back as tool_use. Anthropic then expects a local tool_result for the server call and rejects the next request with HTTP 400 (tool_use ids were found without tool_result blocks immediately after: srvtoolu_...). Per Anthropic's server-tool docs, the client returns the local result and the API runs the pending server tool on the next request, which needs the block to stay server_tool_use.

Description & Review Guide

  • What are the major changes? _prepare_messages_for_anthropic collects the hosted calls that have no function_result anywhere in the conversation and passes them down to _prepare_message_for_anthropic, which sends those calls as server_tool_use instead of tool_use. The hosted call is found from the call's own hosted flag, which survives to_dict/from_dict, so a reloaded session behaves the same.
  • What is the impact of these changes? The parallel local plus server tool turn from the issue now produces assistant [tool_use(local), server_tool_use(srv)] followed by user [tool_result(local)]. Server tool calls that already have a result in the conversation keep today's tool_use/tool_result pairing. I left those alone on purpose: the parsed web_search_tool_result content is stored stringified on the Content, so a native result block (with encrypted_content) can't be rebuilt from history. Switching only the call type would leave the result without a matching tool_use.
  • What do you want reviewers to focus on? Whether keeping completed server tool calls on the existing pairing is the right scope, or whether you'd rather round-trip them natively in a follow-up (which would need the structured result kept on the content).

Tests: test_prepare_messages_preserves_parallel_server_tool_use (in memory and after a to_dict/from_dict reload, from real BetaToolUseBlock/BetaServerToolUseBlock parsing) fails on main and passes with the change. test_prepare_messages_keeps_completed_server_tool_call_paired_with_its_result pins the unchanged pairing once the search result arrives. The anthropic package unit tests pass (204), ruff check/format are clean, and mypy/pyright report no new errors in agent_framework_anthropic compared with main. I did not run it against the live Anthropic API.

Related Issue

Fixes #9478

The issue was reproduced by the repository's triage workflow (reproduced label, assigned to Eduard van Valkenburg (@eavanvalkenburg)). It has no maintainer comment on the direction yet, and no open PR references it. Happy to adjust or close if you'd rather handle it differently.

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: implementation, tests and this PR description were drafted with Claude Code and reviewed before submitting.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

🤖 Generated with Claude Code

When Claude calls a local tool and a server tool (such as web search) in
parallel, the response ends with a pending server_tool_use. The hosted call
was sent back as a plain tool_use, so Anthropic expected a local tool_result
for it and rejected the next request with HTTP 400. Hosted calls that have
no result in the conversation are now sent back as server_tool_use, so the
API runs the server tool on the next request.

Fixes microsoft#9478

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Oct 18, 2026

This branch was successfully deployed

1 active deployment
github-app-auth — 50353398 Deployed Oct 18, 2026 by ShivamSharma43 via team_check #7033
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Anthropic parallel hosted web search and local tool calls lose server_tool_use identity

2 participants