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
- 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).
- Use the string literals 'auto' | 'required' | 'none' for the corresponding behaviors.
- 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
- Always resolve forced tools to the Tool object from your tools list
- Never port OpenAI-style dict tool_choice directly
- Normalize config-driven tool_choice through one coercion helper
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
- Unknown content type: {part}
- Required create args are missing: {required_create_args - cr
- Disallowed create args are present: {disallowed_create_args.
- model is required for AnthropicChatCompletionClient
- Invalid name: {name}. Only letters, numbers, '_' and '-' are
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/adb34753879b35f0.
Report an issue: GitHub.