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

  1. Parse the trailing cause after '执行失败:' — for LLM timeouts/failures, apply fixes from errors 133/134 (timeout, credentials).
  2. 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.
  3. 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

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


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/740b52db33da31d9. Report an issue: GitHub.