{"record":{"id":"934ef38188f79b03","repo":"datawhalechina/hello-agents","slug":"tool-name-934ef3","errorCode":null,"errorMessage":"工具 '{tool_name}' 不存在","messagePattern":"工具 '(.+?)' 不存在","errorType":"exception","errorClass":"AgentException","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py","lineNumber":168,"sourceCode":"            \"function\": tool_func,\n            \"description\": description\n        }\n    \n    def get_tools_description(self) -> str:\n        \"\"\"获取工具描述\"\"\"\n        if not self.tools:\n            return \"暂无可用工具\"\n        \n        descriptions = []\n        for name, tool_info in self.tools.items():\n            descriptions.append(f\"- {name}: {tool_info['description']}\")\n        \n        return \"\\n\".join(descriptions)\n    \n    async def call_tool(self, tool_name: str, tool_input: Any) -> Any:\n        \"\"\"调用工具\"\"\"\n        if tool_name not in self.tools:\n            raise AgentException(f\"工具 '{tool_name}' 不存在\")\n        \n        try:\n            tool_func = self.tools[tool_name][\"function\"]\n            if asyncio.iscoroutinefunction(tool_func):\n                result = await asyncio.wait_for(\n                    tool_func(tool_input), \n                    timeout=self.timeout\n                )\n            else:\n                result = await asyncio.wait_for(\n                    asyncio.to_thread(tool_func, tool_input),\n                    timeout=self.timeout\n                )\n            \n            self._add_to_history(f\"Tool {tool_name} called with input: {tool_input}\")\n            self._add_to_history(f\"Tool {tool_name} result: {result}\")\n            \n            return result","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py#L150-L186","documentation":"BaseAgent.call_tool looks up tool_name in self.tools (populated via add_tool); an unknown name raises AgentException('工具 ... 不存在'). It is a registry lookup failure — the agent attempted to invoke a tool that was never registered on this instance.","triggerScenarios":"LLM emitting a tool name that is not in get_tools_description(); calling agent.call_tool('search_drug', ...) when only 'drug_search' was registered via add_tool; instantiating a fresh agent and calling a tool its subclass never registers.","commonSituations":"Hallucinated or renamed tool names from the model; tools registered conditionally (only if an API key exists) so the name disappears in some environments; prompt tool lists drifting out of sync with registrations.","solutions":["Register the tool before use: agent.add_tool('name', func, description).","Constrain the model to the registered list — feed it get_tools_description() output verbatim.","On AgentException with '不存在', re-prompt the model with the available tool list instead of crashing."],"exampleFix":"# before\nresult = await agent.call_tool('search_drugs', q)  # never registered\n\n# after\nagent.add_tool('search_drugs', search_drugs, '查询药品信息')\nresult = await agent.call_tool('search_drugs', q)\n\n# defensive: allowed = set(agent.tools)","handlingStrategy":"validation","validationCode":"def tool_exists(agent, name):\n    return name in agent.tools\n\nif not tool_exists(agent, tool_name):\n    raise KeyError(f'{tool_name} not registered; have: {sorted(agent.tools)}')","typeGuard":null,"tryCatchPattern":"try:\n    r = await agent.call_tool(name, tool_input)\nexcept AgentException as e:\n    if '不存在' in str(e):\n        r = f'tool {name} not available; valid: {sorted(agent.tools)}'  # feed back to LLM","preventionTips":["Register all tools in the agent's __init__ so the registry is complete before any LLM turn.","Give the model get_tools_description() output verbatim in the system prompt.","On lookup failure, reply to the LLM with the valid tool list so it self-corrects."],"tags":["agent","tools","registry","validation"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}