{"record":{"id":"5c87675b13544b4d","repo":"microsoft/autogen","slug":"tool-choice-references-tool-name-but-it-s-not-5c8767","errorCode":null,"errorMessage":"tool_choice references '{tool_name}' but it's not in the provided tools","messagePattern":"tool_choice references '(.+?)' but it's not in the provided tools","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/models/openai/_openai_client.py","lineNumber":649,"sourceCode":"        converted_tools = convert_tools(tools)\n\n        # Process tool_choice parameter\n        if isinstance(tool_choice, Tool):\n            if len(tools) == 0:\n                raise ValueError(\"tool_choice specified but no tools provided\")\n\n            # Validate that the tool exists in the provided tools\n            tool_names_available: List[str] = []\n            for tool in tools:\n                if isinstance(tool, Tool):\n                    tool_names_available.append(tool.schema[\"name\"])\n                else:\n                    tool_names_available.append(tool[\"name\"])\n\n            # tool_choice is a single Tool object\n            tool_name = tool_choice.schema[\"name\"]\n            if tool_name not in tool_names_available:\n                raise ValueError(f\"tool_choice references '{tool_name}' but it's not in the provided tools\")\n\n        if len(converted_tools) > 0:\n            # Convert to OpenAI format and add to create_args\n            converted_tool_choice = convert_tool_choice(tool_choice)\n            create_args[\"tool_choice\"] = converted_tool_choice\n\n        return CreateParams(\n            messages=oai_messages,\n            tools=converted_tools,\n            response_format=response_format_value,\n            create_args=create_args,\n        )\n\n    async def create(\n        self,\n        messages: Sequence[LLMMessage],\n        *,\n        tools: Sequence[Tool | ToolSchema] = [],","sourceCodeStart":631,"sourceCodeEnd":667,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/models/openai/_openai_client.py#L631-L667","documentation":"Thrown by OpenAIChatCompletionClient when tool_choice is a Tool instance whose schema name does not appear in the provided tools list. The client validates that the forced tool is actually available to the model before building the request, preventing an API-side rejection.","triggerScenarios":"Calling create with tool_choice=Tool(name='X') while the tools list contains only tools named other than 'X' (or only ToolSchema dicts whose 'name' differs). The name comparison uses the schema's 'name' field for both Tool objects and raw dicts.","commonSituations":"Renaming a tool but not the tool_choice reference; constructing tool_choice from a different tool set than tools (e.g. copy-paste across agents); passing a workbench subset of tools while forcing a tool excluded by the filter.","solutions":["Make sure the tool referenced by tool_choice is included in the tools list by that exact name","Check for naming drift between the Tool object used for tool_choice and the registered tools","Use tool_choice='auto' or 'required' if you do not need to force one specific tool"],"exampleFix":"# before\ntool_a = Tool(get_weather, ...)  # name='get_weather'\nawait client.create([msg], tools=[tool_a], tool_choice=Tool(lookup_stock, ...))  # name='lookup_stock'\n\n# after\nawait client.create([msg], tools=[tool_a], tool_choice=tool_a)","handlingStrategy":"validation","validationCode":"def tool_names(tools):\n    return [t.schema[\"name\"] if hasattr(t, \"schema\") else t[\"name\"] for t in tools]\n\nif isinstance(tool_choice, Tool):\n    assert tool_choice.schema[\"name\"] in tool_names(tools), \"tool_choice name not in tools\"","typeGuard":"def tool_choice_resolves(tool_choice, tools) -> bool:\n    if not isinstance(tool_choice, Tool):\n        return True\n    return tool_choice.schema[\"name\"] in tool_names(tools)","tryCatchPattern":"try:\n    result = await client.create(messages, tools=tools, tool_choice=tool_choice)\nexcept ValueError as e:\n    if \"not in the provided tools\" in str(e):\n        result = await client.create(messages, tools=tools, tool_choice=\"required\")\n    else:\n        raise","preventionTips":["Single-source tool definitions: build tools once and reference elements of that list for tool_choice","Rename tools in one place (the Tool constructor), never by editing call sites","Add a unit test that every forced tool_choice name exists in the offered tools"],"tags":["openai","tool-choice","tools","validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}