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

  1. Extract the cause after '执行失败:' and fix the failing tool code or its input contract.
  2. Validate tool_input against the tool's expected schema before invoking call_tool.
  3. 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

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


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