datawhalechina/hello-agents · error · AgentException
工具 '{tool_name}' 执行失败: {str(e)}
Error message
工具 '{tool_name}' 执行失败: {str(e)} What it means
The generic except in call_tool: any exception raised by the tool function other than asyncio.TimeoutError is wrapped as AgentException('工具 ... 执行失败: <original message>'). Like error 134, the root cause survives only inside the message text, so diagnosis means parsing that string.
Source
Thrown at Co-creation-projects/Shawnxyxy-HealthRecordAgent/backend/agents/base.py:191
result = await asyncio.wait_for(
tool_func(tool_input),
timeout=self.timeout
)
else:
result = await asyncio.wait_for(
asyncio.to_thread(tool_func, tool_input),
timeout=self.timeout
)
self._add_to_history(f"Tool {tool_name} called with input: {tool_input}")
self._add_to_history(f"Tool {tool_name} result: {result}")
return result
except asyncio.TimeoutError:
raise TimeoutException(f"工具 '{tool_name}' 执行超时")
except Exception as e:
raise AgentException(f"工具 '{tool_name}' 执行失败: {str(e)}")
# ========== 状态 & 历史 ==========
def _add_to_history(self, message: str):
"""添加到历史记录"""
timestamp = datetime.now().isoformat()
self.history.append(f"[{timestamp}] {message}")
# 限制历史记录长度
if len(self.history) > 100:
self.history = self.history[-50:]
def get_history(self, limit: int = 10) -> List[str]:
"""获取历史记录"""
return self.history[-limit:]
def clear_history(self):
"""清空历史记录"""
self.history = []
View on GitHub (pinned to 606a07d341)
Solutions
- Extract the cause after '执行失败:' and fix the failing tool code or its input contract.
- Validate tool_input against the tool's expected schema before invoking call_tool.
- In the agent loop, catch this AgentException and feed the error message back to the LLM so it can self-correct the arguments.
Example fix
# before
try:
r = await agent.call_tool(name, tool_input)
except AgentException:
pass # cause lost
# after
try:
r = await agent.call_tool(name, tool_input)
except AgentException as e:
tool_errors.append(str(e)) # feed back to the LLM for argument self-correction
r = 'tool_error: ' + str(e) Defensive patterns
Strategy: try-catch
Validate before calling
def tool_input_ok(tool_func, tool_input, required_keys):
return isinstance(tool_input, dict) and all(k in tool_input for k in required_keys) Try / catch
try:
r = await agent.call_tool(name, tool_input)
except AgentException as e:
if '执行失败' in str(e):
r = f'tool error: {e}' # return to the LLM so it can fix the arguments and retry Prevention
- Validate tool_input against the tool's expected keys before invoking call_tool.
- Return tool errors to the LLM as observations instead of aborting the agent loop.
- Log the cause substring — the wrapper drops the exception chain.
When it happens
Trigger: Tool raising KeyError on unexpected input shape, network errors from its HTTP client, JSON decode failures on provider responses, None propagating into attribute access — any tool-internal exception.
Common situations: LLM producing tool_input that misses keys the tool expects; external APIs changing response schemas; unhandled None/empty results in glue code.
Related errors
- LLM思考失败: {str(e)}
- 工具 '{tool_name}' 不存在
- 工具 '{tool_name}' 执行超时
- PlannerAgent 执行失败: {str(e)}
- {stage}失败:工具执行异常:{exc}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/8f996407de9fb4e5.
Report an issue: GitHub.