{"record":{"id":"740b52db33da31d9","repo":"datawhalechina/hello-agents","slug":"planneragent-str-e","errorCode":null,"errorMessage":"PlannerAgent 执行失败: {str(e)}","messagePattern":"PlannerAgent 执行失败: (.+?)","errorType":"exception","errorClass":"AgentException","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/planner.py","lineNumber":51,"sourceCode":"            plan = self._parse_plan(response)\n\n            self.set_state(\"completed\")\n            self._add_to_history(f\"生成计划，包含 {len(plan)} 个步骤\")\n\n            result = {\n                \"status\": \"success\",\n                \"goal\": goal,\n                \"plan\": plan,\n                \"created_at\": datetime.now().isoformat()\n            }\n\n            self.set_state(\"completed\")\n\n            return result\n\n        except Exception as e:\n            self.set_state(\"error\")\n            raise AgentException(f\"PlannerAgent 执行失败: {str(e)}\")\n    \n    def get_required_fields(self) -> List[str]:\n        \"\"\"\n        Planner 只关心 goal\n        \"\"\"\n        return [\"goal\"]\n\n    # ======================\n    # 内部方法\n    # ======================\n    def _build_planner_prompt(self, goal: str, context: Dict[str, Any]) -> str:\n        \"\"\"\n        构造 Planner Prompt (Plan-And-Solve)\n        \"\"\"\n        return f\"\"\"\n你是一个 Planner Agent，擅长将复杂目标拆解为可执行的子任务。\n\n【总目标】","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/planner.py#L33-L69","documentation":"PlannerAgent.run wraps its whole execution (prompt build, LLM think, plan parsing) in try/except; on any exception it sets agent state to 'error' and re-raises as AgentException('PlannerAgent 执行失败: <original message>'). It is a boundary wrapper: the state transition to 'error' is a side effect that happens before the re-raise, and the original cause lives only in the message string.","triggerScenarios":"The inner LLM call failing (errors 133/134 propagate and get re-wrapped), JSON/structure parsing of the model's plan output failing, or missing context keys used while building _build_planner_prompt — anything inside the try block.","commonSituations":"Planner LLM returning malformed plan JSON; LLM credentials/endpoint issues surfacing here second-hand; context dict passed to run lacking keys the prompt builder indexes.","solutions":["Parse the trailing cause after '执行失败:' — for LLM timeouts/failures, apply fixes from errors 133/134 (timeout, credentials).","If it is a parse failure, make plan parsing tolerant (json.loads with fallback extraction of the JSON block) or instruct the model with a stricter output format.","After catching, check agent state ('error') before retrying so you reset or rebuild the agent."],"exampleFix":"# before\nplan = await planner.run({'goal': g})  # crashes through on malformed LLM JSON\n\n# after\ntry:\n    plan = await planner.run({'goal': g})\nexcept AgentException as e:\n    msg = str(e)\n    if 'LLM思考超时' in msg:\n        await asyncio.sleep(2); plan = await planner.run({'goal': g})\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"ok, missing = has_required_fields(planner, {'goal': goal})\nif not ok:\n    raise ValueError(f'missing: {missing}')  # fail before run() wraps everything","typeGuard":null,"tryCatchPattern":"try:\n    result = await planner.run({'goal': g, 'context': ctx})\nexcept AgentException as e:\n    msg = str(e)\n    if 'LLM思考超时' in msg:\n        result = await planner.run({'goal': g, 'context': trimmed(ctx)})\n    else:\n        raise\nfinally:\n    assert planner.state != 'error' or handled, 'planner left in error state'","preventionTips":["Validate inputs before run() so schema issues surface unwrapped.","Check planner.state after any exception — the wrapper sets 'error' as a side effect.","Make plan parsing tolerant of LLM formatting (extract JSON block, retry once)."],"tags":["agent","planner","wrapper-exception","state-machine"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}