{"record":{"id":"fb3ff67831e2d1d3","repo":"datawhalechina/hello-agents","slug":"llm-str-e-fb3ff6","errorCode":null,"errorMessage":"LLM思考失败: {str(e)}","messagePattern":"LLM思考失败: (.+?)","errorType":"exception","errorClass":"AgentException","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py","lineNumber":145,"sourceCode":"                {\n                    \"duration_sec\": duration,\n                    \"prompt_tokens\": len(full_prompt),\n                }\n            )\n            \n            response_text = response.content if hasattr(response, 'content') else str(response)\n            \n            self.trace(\"LLM RESPONSE\", response_text)\n\n            self._add_to_history(f\"LLM prompt: {prompt}\")\n            self._add_to_history(f\"LLM response: {response_text}\")\n            \n            return response_text\n            \n        except asyncio.TimeoutError:\n            raise TimeoutException(f\"LLM思考超时\")\n        except Exception as e:\n            raise AgentException(f\"LLM思考失败: {str(e)}\")\n    # ========== Tool 机制 ==========\n    def add_tool(self, tool_name: str, tool_func: Callable, description: str = \"\"):\n        \"\"\"添加工具\"\"\"\n        self.tools[tool_name] = {\n            \"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)","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py#L127-L163","documentation":"The generic except in BaseAgent.think: any exception from the LLM call that is not asyncio.TimeoutError is re-wrapped as AgentException('LLM思考失败: <original message>'). The original cause is only in the string, so the real failure (auth error, connection refused, malformed response, missing attribute on the response object) must be read out of the message.","triggerScenarios":"Invalid/expired API key (401), unreachable base URL, model name not found, the LLM client returning an object without .content (falls into str() then downstream errors), or serialization issues in the prompt — anything except a wait_for timeout.","commonSituations":"Rotated API keys after the agent was deployed; pointing the client at a wrong/self-hosted endpoint; swapping LLM libraries whose response objects differ; empty responses from rate limiting.","solutions":["Read the embedded original message after 'LLM思考失败:' — it usually names the HTTP status or library error.","Fix the root cause: verify API key, base URL, and model id by making one direct client call outside the agent.","If the message mentions response shape issues, normalize the response before think() processes it.","Distinguish from error 133: no '超时' in the message means it is this generic path, not a timeout."],"exampleFix":"# before\ntry:\n    out = await agent.think(prompt)\nexcept AgentException as e:\n    abort()  # loses cause\n\n# after\ntry:\n    out = await agent.think(prompt)\nexcept AgentException as e:\n    cause = str(e).removeprefix('LLM思考失败: ')\n    if '401' in cause or 'api key' in cause.lower():\n        refresh_credentials()\n    raise","handlingStrategy":"try-catch","validationCode":"async def llm_reachable(llm):\n    try:\n        await asyncio.wait_for(llm.ainvoke('ping'), timeout=10)\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    out = await agent.think(prompt)\nexcept AgentException as e:\n    msg = str(e)\n    if '401' in msg or 'Unauthorized' in msg:\n        rotate_api_key()\n    elif 'Connection' in msg:\n        check_base_url_and_network()\n    else:\n        raise","preventionTips":["Verify credentials and endpoint with a direct minimal LLM call during agent startup.","Log the embedded cause string — the wrapper preserves no exception chain for programmatic use.","Keep the LLM client's response shape stable (wrap clients so .content always exists)."],"tags":["llm","agent","wrapper-exception","diagnostics"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}