datawhalechina/hello-agents · error · AgentException
PlannerAgent 执行失败: {str(e)}
Error message
PlannerAgent 执行失败: {str(e)} What it means
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.
Source
Thrown at Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/planner.py:51
plan = self._parse_plan(response)
self.set_state("completed")
self._add_to_history(f"生成计划,包含 {len(plan)} 个步骤")
result = {
"status": "success",
"goal": goal,
"plan": plan,
"created_at": datetime.now().isoformat()
}
self.set_state("completed")
return result
except Exception as e:
self.set_state("error")
raise AgentException(f"PlannerAgent 执行失败: {str(e)}")
def get_required_fields(self) -> List[str]:
"""
Planner 只关心 goal
"""
return ["goal"]
# ======================
# 内部方法
# ======================
def _build_planner_prompt(self, goal: str, context: Dict[str, Any]) -> str:
"""
构造 Planner Prompt (Plan-And-Solve)
"""
return f"""
你是一个 Planner Agent,擅长将复杂目标拆解为可执行的子任务。
【总目标】View on GitHub (pinned to 606a07d341)
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.
Example fix
# before
plan = await planner.run({'goal': g}) # crashes through on malformed LLM JSON
# after
try:
plan = await planner.run({'goal': g})
except AgentException as e:
msg = str(e)
if 'LLM思考超时' in msg:
await asyncio.sleep(2); plan = await planner.run({'goal': g})
else:
raise Defensive patterns
Strategy: try-catch
Validate before calling
ok, missing = has_required_fields(planner, {'goal': goal})
if not ok:
raise ValueError(f'missing: {missing}') # fail before run() wraps everything Try / catch
try:
result = await planner.run({'goal': g, 'context': ctx})
except AgentException as e:
msg = str(e)
if 'LLM思考超时' in msg:
result = await planner.run({'goal': g, 'context': trimmed(ctx)})
else:
raise
finally:
assert planner.state != 'error' or handled, 'planner left in error state' Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- LLM思考失败: {str(e)}
- 工具 '{tool_name}' 执行失败: {str(e)}
- 工具 '{tool_name}' 不存在
- 工具 '{tool_name}' 执行超时
- 工具 '{tool_name}' 执行失败: {str(e)}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/740b52db33da31d9.
Report an issue: GitHub.