{"record":{"id":"ad07146bb88fdd8d","repo":"microsoft/autogen","slug":"unknown-tool-name-please-choose-from-tool","errorCode":null,"errorMessage":"Unknown tool '{name}'. Please choose from:\n\n{tool_names}","messagePattern":"Unknown tool '(.+?)'\\. Please choose from:\n\n(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py","lineNumber":768,"sourceCode":"            # Summarize the DOM. No need to take further action. Browser state does not change.\n            action_description = \"I summarized the current web page\"\n            return await self._summarize_page(cancellation_token=cancellation_token)\n\n        elif name == \"hover\":\n            target_id = str(args.get(\"target_id\"))\n            target_name = self._target_name(target_id, rects)\n            if target_name:\n                action_description = f\"I hovered over '{target_name}'.\"\n            else:\n                action_description = \"I hovered over the control.\"\n            await self._playwright_controller.hover_id(self._page, target_id)\n\n        elif name == \"sleep\":\n            action_description = \"I am waiting a short period of time before taking further action.\"\n            await self._playwright_controller.sleep(self._page, 3)\n\n        else:\n            raise ValueError(f\"Unknown tool '{name}'. Please choose from:\\n\\n{tool_names}\")\n\n        await self._page.wait_for_load_state()\n        await self._playwright_controller.sleep(self._page, 3)\n\n        # Handle downloads\n        if self._last_download is not None and self.downloads_folder is not None:\n            fname = os.path.join(self.downloads_folder, self._last_download.suggested_filename)\n            await self._last_download.save_as(fname)  # type: ignore\n            page_body = f\"<html><head><title>Download Successful</title></head><body style=\\\"margin: 20px;\\\"><h1>Successfully downloaded '{self._last_download.suggested_filename}' to local path:<br><br>{fname}</h1></body></html>\"\n            await self._page.goto(\n                \"data:text/html;base64,\" + base64.b64encode(page_body.encode(\"utf-8\")).decode(\"utf-8\")\n            )\n            await self._page.wait_for_load_state()\n\n        # Handle metadata\n        page_metadata = json.dumps(await self._playwright_controller.get_page_metadata(self._page), indent=4)\n        metadata_hash = hashlib.md5(page_metadata.encode(\"utf-8\")).hexdigest()\n        if metadata_hash != self._prior_metadata_hash:","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/_multimodal_web_surfer.py#L750-L786","documentation":"In MultimodalWebSurfer's action dispatch (visit_page, click, input_text, scroll_down/up, scroll_element_up/down, hover, sleep, ...), any tool name not matching a known branch falls through to ValueError listing the valid tool_names. In practice this error is produced by the LLM's own tool call, not the application: the model hallucinated a tool name or used one from a different agent/prompt version.","triggerScenarios":"The model emits a function call named e.g. 'navigate', 'type', or 'screenshot' that is not in the web surfer's tool list, or an application forwards a tool call intended for another agent into this agent's handler.","commonSituations":"Prompt changes where the advertised tool list drifted from the dispatcher, small models with weak tool-name adherence, team setups where tool calls get routed to the wrong agent's handle_request/on_messages.","solutions":["Update/repair the system prompt or tool schema so only supported tool names are advertised","Catch ValueError from the agent's message handling and feed the error text back to the model so it retries with a valid name","Use a stronger function-calling model for the web surfer","Ensure the tool call is routed to the agent whose schema produced it"],"exampleFix":"// before\nresult = await surfer.on_messages([TextMessage(content='go', source='user')], cts)\n\n// after\ntry:\n    result = await surfer.on_messages(msgs, cts)\nexcept ValueError as e:\n    # echo valid tool names back so the model self-corrects\n    msgs.append(TextMessage(content=f'Invalid action: {e}. Retry with a listed tool.', source='user'))","handlingStrategy":"retry","validationCode":"KNOWN_TOOLS = {'visit_page','click','input_text','scroll_down','scroll_up','scroll_element_up','scroll_element_down','hover','sleep','read_page','answer_question'}\ndef valid_tool_name(name: str) -> bool:\n    return name in KNOWN_TOOLS","typeGuard":null,"tryCatchPattern":"try:\n    result = await surfer.on_messages(messages, token)\nexcept ValueError as e:\n    if 'Unknown tool' in str(e):\n        messages = messages + [TextMessage(content=f'That tool does not exist. {e}. Pick again.', source='user')]\n        result = await surfer.on_messages(messages, token)  # model self-corrects\n    else:\n        raise","preventionTips":["Advertise only the agent's real tool schema in prompts","Feed the error text (which lists valid names) back to the model","Use function-calling-strong models for browser automation"],"tags":["web-surfer","llm","tool-calling","dispatch","retry"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}