Skip to content

Python: [Bug]: AnthropicClient ignores allow_multiple_tool_calls=False when tool_choice is unset (incl. every loop iteration after tool_choice="required") #8979

Closed

Description

Description

Anthropic only lets you turn off parallel tool use through tool_choice.disable_parallel_tool_use. RawAnthropicClient maps allow_multiple_tool_calls onto that field only inside the tool_choice branch. When tool_choice is None, _prepare_tools_for_anthropic returns early and the setting is dropped (it was already popped from the request in _prepare_options). There is no warning or error.

tool_choice is None in two common cases:

  1. Calling the client directly with tools and allow_multiple_tool_calls=False without setting tool_choice.
  2. Every model call after the first one in the function-invocation loop when tool_choice="required", because _reset_required_tool_choice sets options["tool_choice"] = None after the first iteration. The first request has {"type": "any", "disable_parallel_tool_use": true}. Later requests have no tool_choice at all, so Claude can emit parallel tool_use blocks again.
  • Expected: every request that sends tools also sends disable_parallel_tool_use: true when allow_multiple_tool_calls=False (Anthropic's default mode is auto, so {"type": "auto", "disable_parallel_tool_use": true}).
  • Actual: tool_choice is omitted and parallel tool use stays enabled.

The OpenAI clients map allow_multiple_tool_calls to parallel_tool_calls whenever tools are present, regardless of tool_choice.

Code Sample

from unittest.mock import MagicMock
from agent_framework import Message, tool
from agent_framework_anthropic import AnthropicClient

@tool(approval_mode="never_require")
def get_weather(city: str) -> str:
    """Get the weather."""
    return f"sunny in {city}"

client = AnthropicClient(api_key="x", model="claude-sonnet-4-5", anthropic_client=MagicMock())
run_options = client._prepare_options(
    [Message(role="user", contents=["Weather in Paris and Rome?"])],
    {"tools": [get_weather], "allow_multiple_tool_calls": False},
)
print(run_options.get("tool_choice"))  # None -> parallel tool use not disabled

For the loop case, run get_response(..., options={"tools": [get_weather], "tool_choice": "required", "allow_multiple_tool_calls": False}) against a mocked beta.messages.create that returns tool_use twice. Request 1 has tool_choice={"type": "any", "disable_parallel_tool_use": True}. Requests 2 and 3 have no tool_choice.

Root cause

python/packages/anthropic/agent_framework_anthropic/_chat_client.py:1146-1148:

# Process tool choice
if options.get("tool_choice") is None:
    return result or None

allow_multiple_tool_calls is only read after this early return. It is also removed from the request at :701, so nothing else forwards it. The loop reset happens in python/packages/core/agent_framework/_tools.py:4380 (_reset_required_tool_choice).

Proposed fix

When tool_choice is unset, allow_multiple_tool_calls is set and tools are present, send {"type": "auto", "disable_parallel_tool_use": not allow_multiple_tool_calls}. This is Anthropic's default mode, so nothing else changes. Requests without tools or without allow_multiple_tool_calls are unchanged. The fix stays in the Anthropic option mapping; the function-invocation loop is not touched. PR with regression tests is ready.

Code Sample

Error Messages / Stack Traces

Package Versions

agent-framework-anthropic: 1.0.0b261002, agent-framework-core: 1.20.0 (main @ e9857bd)

Python Version

Python 3.12

Additional Context

No response

Activity

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

    @github-actions
    Contributor

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

    Agent analysis

    python/packages/anthropic/agent_framework_anthropic/_chat_client.py::_prepare_tools_for_anthropic omits tool_choice when tools and allow_multiple_tool_calls=False are supplied without an explicit tool choice; required-tool loops trigger this after _reset_required_tool_choice clears the option. Minimal repro: call _prepare_options with one tool and allow_multiple_tool_calls=False, then assert the result contains tool_choice.type="auto" and disable_parallel_tool_use=True.

    • Failing test: python/packages/anthropic/tests/test_anthropic_client.py::test_unset_tool_choice_disables_parallel_use
    • Files examined: python/packages/anthropic/agent_framework_anthropic/_chat_client.py, python/packages/core/agent_framework/_tools.py, python/packages/anthropic/tests/test_anthropic_client.py, python/packages/anthropic/pyproject.toml
    • Tests run: test_prepare_options_with_tool_choice_auto, test_tool_choice_auto_with_allow_multiple, test_unset_tool_choice_disables_parallel_use
    • Reported version: agent-framework-anthropic 1.0b261002
    • Current version: agent-framework-anthropic 1.0.0b261002
  4. added
    agentsUsage: [Issues, PRs], Target: Single agent
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 2, 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