microsoft/autogen · error · ValueError

tool_choice must be a Tool object, 'auto', 'required', or 'n

Error message

tool_choice must be a Tool object, 'auto', 'required', or 'none', got {type(tool_choice)}

What it means

AnthropicChatCompletionClient.create accepts tool_choice as either the strings 'auto', 'required', 'none' or a Tool object (to force a specific tool). The conversion helper maps these to Anthropic's format and raises ValueError with the actual received type for anything else — e.g. a raw dict {'type': 'tool', ...} or an OpenAI-style ToolChoiceOption.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/models/anthropic/_anthropic_client.py:175

        tool_choice: A single Tool object to force the model to use, "auto" to let the model choose any available tool, "required" to force tool usage, or "none" to disable tool usage.

    Returns:
        Anthropic API compatible tool_choice value.
    """
    if tool_choice == "none":
        return {"type": "none"}

    if tool_choice == "auto":
        return {"type": "auto"}

    if tool_choice == "required":
        return {"type": "any"}  # Anthropic uses "any" for required

    # Must be a Tool object
    if isinstance(tool_choice, Tool):
        return {"type": "tool", "name": tool_choice.schema["name"]}
    else:
        raise ValueError(f"tool_choice must be a Tool object, 'auto', 'required', or 'none', got {type(tool_choice)}")


@overload
def __empty_content_to_whitespace(content: str) -> str: ...


@overload
def __empty_content_to_whitespace(content: List[Any]) -> Iterable[Any]: ...


def __empty_content_to_whitespace(
    content: Union[str, List[Union[str, Image]]],
) -> Union[str, Iterable[Any]]:
    if isinstance(content, str) and not content.strip():
        return " "
    elif isinstance(content, list) and not any(isinstance(x, str) and not x.strip() for x in content):
        for idx, message in enumerate(content):
            if isinstance(message, str) and not message.strip():

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Pass a Tool object built by the same tools list you give create(): tool_choice=next(t for t in tools if t.schema['name'] == wanted).
  2. Use the string literals 'auto' | 'required' | 'none' for the corresponding behaviors.
  3. If tool_choice comes from config, validate/normalize it to Tool or one of the three strings before calling create.

Example fix

# before
result = await client.create(messages, tools=tools, tool_choice={'type': 'tool', 'name': 'get_weather'})  # ValueError

# after
forced = next(t for t in tools if t.schema['name'] == 'get_weather')
result = await client.create(messages, tools=tools, tool_choice=forced)
Defensive patterns

Strategy: type-guard

Validate before calling

from autogen_core.models import Tool

def coerce_tool_choice(choice, tools):
    if choice in ('auto', 'required', 'none'):
        return choice
    if isinstance(choice, Tool):
        return choice
    if isinstance(choice, str):
        return next(t for t in tools if t.schema['name'] == choice)
    raise TypeError(f'bad tool_choice: {choice!r}')

Type guard

def is_valid_tool_choice(choice) -> bool:
    return choice in ('auto', 'required', 'none') or isinstance(choice, Tool)

Try / catch

try:
    res = await client.create(messages, tools=tools, tool_choice=tc)
except ValueError as e:
    if 'tool_choice' in str(e):
        res = await client.create(messages, tools=tools)  # default 'auto'
    else:
        raise

Prevention

When it happens

Trigger: create(..., tool_choice={'type': 'function', 'function': {'name': 'x'}}) (OpenAI format); passing the tool's name string instead of the Tool object; passing None when you meant 'auto'; passing a pydantic schema instead of a Tool instance.

Common situations: Porting code from OpenAIChatCompletionClient where dict tool_choice is idiomatic; LLM-generated or config-driven tool_choice values arriving as dicts; assuming string tool names force tools.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/adb34753879b35f0. Report an issue: GitHub.