{"record":{"id":"8f996407de9fb4e5","repo":"datawhalechina/hello-agents","slug":"tool-name-str-e-8f9964","errorCode":null,"errorMessage":"工具 '{tool_name}' 执行失败: {str(e)}","messagePattern":"工具 '(.+?)' 执行失败: (.+?)","errorType":"exception","errorClass":"AgentException","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py","lineNumber":191,"sourceCode":"                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\n            \n        except asyncio.TimeoutError:\n            raise TimeoutException(f\"工具 '{tool_name}' 执行超时\")\n        except Exception as e:\n            raise AgentException(f\"工具 '{tool_name}' 执行失败: {str(e)}\")\n    # ========== 状态 & 历史 ==========\n    def _add_to_history(self, message: str):\n        \"\"\"添加到历史记录\"\"\"\n        timestamp = datetime.now().isoformat()\n        self.history.append(f\"[{timestamp}] {message}\")\n        \n        # 限制历史记录长度\n        if len(self.history) > 100:\n            self.history = self.history[-50:]\n    \n    def get_history(self, limit: int = 10) -> List[str]:\n        \"\"\"获取历史记录\"\"\"\n        return self.history[-limit:]\n    \n    def clear_history(self):\n        \"\"\"清空历史记录\"\"\"\n        self.history = []\n    ","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py#L173-L209","documentation":"The generic except in call_tool: any exception raised by the tool function other than asyncio.TimeoutError is wrapped as AgentException('工具 ... 执行失败: <original message>'). Like error 134, the root cause survives only inside the message text, so diagnosis means parsing that string.","triggerScenarios":"Tool raising KeyError on unexpected input shape, network errors from its HTTP client, JSON decode failures on provider responses, None propagating into attribute access — any tool-internal exception.","commonSituations":"LLM producing tool_input that misses keys the tool expects; external APIs changing response schemas; unhandled None/empty results in glue code.","solutions":["Extract the cause after '执行失败:' and fix the failing tool code or its input contract.","Validate tool_input against the tool's expected schema before invoking call_tool.","In the agent loop, catch this AgentException and feed the error message back to the LLM so it can self-correct the arguments."],"exampleFix":"# before\ntry:\n    r = await agent.call_tool(name, tool_input)\nexcept AgentException:\n    pass  # cause lost\n\n# after\ntry:\n    r = await agent.call_tool(name, tool_input)\nexcept AgentException as e:\n    tool_errors.append(str(e))  # feed back to the LLM for argument self-correction\n    r = 'tool_error: ' + str(e)","handlingStrategy":"try-catch","validationCode":"def tool_input_ok(tool_func, tool_input, required_keys):\n    return isinstance(tool_input, dict) and all(k in tool_input for k in required_keys)","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 error: {e}'  # return to the LLM so it can fix the arguments and retry","preventionTips":["Validate tool_input against the tool's expected keys before invoking call_tool.","Return tool errors to the LLM as observations instead of aborting the agent loop.","Log the cause substring — the wrapper drops the exception chain."],"tags":["agent","tools","wrapper-exception","diagnostics"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}