{"record":{"id":"d19b1711fa35d1d8","repo":"datawhalechina/hello-agents","slug":"stage-name","errorCode":null,"errorMessage":"{stage}失败：工具 {name} 未注册","messagePattern":"(.+?)失败：工具 (.+?) 未注册","errorType":"exception","errorClass":"WorkflowExecutionError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py","lineNumber":145,"sourceCode":"\n    @staticmethod\n    def _run_agent(stage: str, agent: AgentLike, prompt: str) -> str:\n        try:\n            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        \"\"\"避免多次运行时把上一条需求带入下一条需求。\"\"\"","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/zenith191-RequirementClarifierAgent/src/workflow.py#L127-L163","documentation":"Raised by _run_tool (src/workflow.py:145) when tool_registry.get_tool(name) returns None for the tool an agent tried to invoke. The registry is the official ToolRegistry, and only tools registered at workflow construction are resolvable — the error names the missing tool so you can see exactly which one the model asked for.","triggerScenarios":"The LLM emits a tool call with a name that was never registered (hallucinated or renamed tool); the tool set was trimmed between versions; a tool registered under a different key than the schema the model was told about.","commonSituations":"Prompt/schema drift: the tool description sent to the model lists an old tool name; a tool class renamed without updating prompts; selectively disabling tools for cost while the prompt still advertises them.","solutions":["Compare the name in the error against the names passed to ToolRegistry at setup; register the missing tool or fix the name mismatch.","Regenerate/refresh tool descriptions given to the model so the advertised list matches the registry.","If the tool was intentionally removed, also remove it from the agent's tool schema/prompt to stop the model from calling it."],"exampleFix":"# before\nregistry = ToolRegistry()\nregistry.register(SearchTool(name=\"web_lookup\"))\n\n# after (match what the model calls)\nregistry = ToolRegistry()\nregistry.register(SearchTool(name=\"search\"))","handlingStrategy":"validation","validationCode":"# keep the advertised tool list and the registry in lockstep\nregistered = set(tool_registry.list_tools()) if hasattr(tool_registry, \"list_tools\") else set()\nadvertised = {t.name for t in tool_schemas_given_to_model}\nassert advertised <= registered, f\"prompt advertises unregistered tools: {advertised - registered}\"","typeGuard":"def tool_is_registered(registry, name: str) -> bool:\n    return registry.get_tool(name) is not None\n\nassert tool_is_registered(tool_registry, \"search\")","tryCatchPattern":"try:\n    result = workflow.run(requirement)\nexcept WorkflowExecutionError as e:\n    if \"未注册\" in str(e):\n        # register the missing tool and retry, or drop it from the prompt\n        fix_tool_registry()\n        result = workflow.run(requirement)\n    else:\n        raise","preventionTips":["Generate tool descriptions for prompts from the live registry, never by hand.","Add a startup assertion that every advertised tool resolves via get_tool().\nWhen renaming a tool, update prompt templates and schemas in the same commit.","Run an integration smoke test that exercises every registered tool once."],"tags":["python","tool-registry","llm","workflow"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}