{"record":{"id":"b6c96dbfeeba74a5","repo":"datawhalechina/hello-agents","slug":"stage-exc-b6c96d","errorCode":null,"errorMessage":"{stage}失败：工具执行异常：{exc}","messagePattern":"(.+?)失败：工具执行异常：(.+?)","errorType":"exception","errorClass":"WorkflowExecutionError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py","lineNumber":149,"sourceCode":"            response = agent.run(prompt)\n        except Exception as exc:\n            raise WorkflowExecutionError(f\"{stage}阶段执行失败：{exc}\") from exc\n        if not isinstance(response, str) or not response.strip():\n            raise WorkflowExecutionError(f\"{stage}阶段返回了空结果\")\n        return response.strip()\n\n    def _run_tool(\n        self, name: str, parameters: dict[str, object], stage: str\n    ) -> dict[str, object]:\n        \"\"\"通过官方 ToolRegistry 获取工具并解析其字符串协议。\"\"\"\n\n        tool = self.tool_registry.get_tool(name)\n        if tool is None:\n            raise WorkflowExecutionError(f\"{stage}失败：工具 {name} 未注册\")\n        try:\n            raw_result = tool.run(parameters)\n        except Exception as exc:\n            raise WorkflowExecutionError(f\"{stage}失败：工具执行异常：{exc}\") from exc\n        try:\n            payload = json.loads(raw_result)\n        except (TypeError, ValueError) as exc:\n            raise WorkflowExecutionError(f\"{stage}失败：工具返回的不是有效 JSON\") from exc\n        if not isinstance(payload, dict):\n            raise WorkflowExecutionError(f\"{stage}失败：工具结果必须是 JSON 对象\")\n        if not payload.get(\"ok\"):\n            raise WorkflowExecutionError(\n                f\"{stage}失败：{payload.get('message', '未知工具错误')}\"\n            )\n        return payload\n\n    def _clear_agent_histories(self) -> None:\n        \"\"\"避免多次运行时把上一条需求带入下一条需求。\"\"\"\n\n        for agent in (\n            self.team.analyst,\n            self.team.architect,","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py#L131-L167","documentation":"Raised by _run_tool when tool.run(parameters) itself raises; the original exception is chained via 'from exc' and surfaced after '工具执行异常：'. The stage and tool name contextualize it. Root causes live inside the tool implementation — file I/O, network calls, bad parameter values, etc.","triggerScenarios":"Any exception thrown inside tool.run(parameters) during a workflow stage: a search tool hitting a dead URL, a file tool given a missing path, or invalid parameter types from the model.","commonSituations":"Tool hits a dead URL or DNS failure; tool reads a missing file path; the model passes parameters that violate the tool's expectations (string vs int); timeouts on external services.","solutions":["Read the exception text after '工具执行异常：' — it is the tool's own error message; fix that root cause first.","Harden the tool: validate parameters, add timeouts and retries around external calls.","If the model keeps sending malformed parameters, tighten the tool's JSON schema/description so the LLM produces valid arguments."],"exampleFix":"# before\ndef run(self, params):\n    return open(params[\"path\"]).read()\n\n# after\ndef run(self, params):\n    try:\n        return open(params[\"path\"]).read()\n    except OSError as e:\n        return json.dumps({\"ok\": False, \"message\": f\"read failed: {e}\"})","handlingStrategy":"try-catch","validationCode":"# dry-run each tool with sample params at startup so failures surface early\nsample = {\"q\": \"test\"}\nraw = tool_registry.get_tool(\"search\").run(sample)\nassert json.loads(raw).get(\"ok\") is True","typeGuard":null,"tryCatchPattern":"try:\n    result = workflow.run(requirement)\nexcept WorkflowExecutionError as e:\n    if \"工具执行异常\" in str(e) and e.__cause__ is not None:\n        cause = e.__cause__\n        if isinstance(cause, (ConnectionError, TimeoutError)):\n            import time; time.sleep(2)\n            result = workflow.run(requirement)  # one retry for transient tool I/O\n        else:\n            raise\n    else:\n        raise","preventionTips":["Design tools to fail soft: catch internal exceptions and return {\"ok\": false, \"message\": ...} instead of raising.","Add timeouts and bounded retries inside tools for network I/O.","Inspect e.__cause__ — the wrapper hides the tool's original traceback otherwise.","Validate tool parameters against a schema before calling run()."],"tags":["python","tools","workflow","wrapper-exception"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}