Skip to content

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

Closed

Description

@coding-totoro

Observed Behavior

With the stock AnthropicClient, native get_web_search_tool(), and one local function tool, a parallel tool turn can fail with HTTP 400. A pending Anthropic server_tool_use is serialized back as a local tool_use, so the API incorrectly expects a local result for the server search.

Reproduced against the real API with and without adaptive thinking. Web search alone and sequential search followed by a local tool succeeded. No application history provider or custom agent loop was involved.

Expected Behavior

Preserve the pending server_tool_use when sending the local tool result. Anthropic documents this mixed-tool flow: the application returns the local result, then the API executes the pending server tool on the next request (server tools).

Steps to Reproduce

  1. Install the versions below and set ANTHROPIC_API_KEY.
  2. Run the minimal example.
  3. When Claude emits a local tool_use alongside a pending server_tool_use, the next API request fails. Tool scheduling is model-dependent; a sequential response will not trigger it.

Minimal Reproduction

import asyncio

import anthropic
from agent_framework import tool
from agent_framework.anthropic import AnthropicClient


@tool
def local_value() -> str:
    """Return a local test value."""
    return "local-ok"


async def main():
    async with anthropic.AsyncAnthropic() as raw:
        client = AnthropicClient(anthropic_client=raw, model="claude-opus-5-5")
        async with client.as_agent(
            tools=[client.get_web_search_tool(), local_value],
            default_options={"max_tokens": 4096},
        ) as agent:
            result = await agent.run(
                "Call local_value and search the web for the Microsoft Agent "
                "Framework Python 1.22 release page. These tasks are independent; "
                "use the tools in parallel where possible. Return the local "
                "value and the release URL.",
                stream=True,
            ).get_final_response()
            print(result.text)


asyncio.run(main())

Error Messages and Stack Traces

Relevant error excerpt (identifier abbreviated):

ChatClientInvalidRequestException: Error code: 400
messages.2: `tool_use` ids were found without `tool_result` blocks immediately after: srvtoolu_...
Each `tool_use` block must have a corresponding `tool_result` block in the next message.

Package Versions

agent-framework-core==1.22.0, agent-framework-anthropic==1.0.0b261015, anthropic==1.11.0, httpx2==2.13.1

Python Version / Operating System

Python 3.14.7 / macOS

Regression

Unknown.

Additional Context

The parser preserves hosted=True, informational_only=True, and the raw server_tool_use block, but the outgoing function_call conversion emits "type": "tool_use" unconditionally (source). This code is also present on current main; runtime reproduction was on the released versions above.

Simplified wire shape:

API response:       assistant [tool_use(local_id), server_tool_use(srv_id)]
Next request:       assistant [tool_use(local_id), tool_use(srv_id)]
                    user      [tool_result(local_id)]

Related: #6997 prevents local execution of hosted calls, but the outgoing Anthropic serialization still loses their server-tool type.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 17, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 17, 2026
  3. github-actions commented on Oct 17, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: python/packages/anthropic/agent_framework_anthropic/_chat_client.py::_prepare_message_for_anthropic at line 1003 loses server_tool_use identity when a hosted call appears alongside a local tool call. Parsing retains hosted=True and informational_only=True, but serialization emits both calls as tool_use. Minimal repro: parse parallel local tool_use and hosted server_tool_use blocks, append only the local result, then call _prepare_messages_for_anthropic and inspect the assistant block types.

    • Failing test: python/packages/anthropic/tests/test_anthropic_client.py::test_prepare_messages_preserves_parallel_server_tool_use
    • Files examined: python/packages/anthropic/agent_framework_anthropic/_chat_client.py, python/packages/anthropic/tests/test_anthropic_client.py, python/packages/anthropic/pyproject.toml
    • Tests run: test_prepare_message_for_anthropic_function_call, test_prepare_messages_preserves_parallel_server_tool_use
    • Reported version: 1.0.0b261015
    • Current version: 1.0.0b261015
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

agentsUsage: [Issues, PRs], Target: Single agentpythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions