{"record":{"id":"efd18ddae1dd462c","repo":"FoundationAgents/OpenManus","slug":"tool-calls-required-but-none-provided","errorCode":null,"errorMessage":"Tool calls required but none provided","messagePattern":"Tool calls required but none provided","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"app/agent/toolcall.py","lineNumber":135,"sourceCode":"            # For 'auto' mode, continue with content if no commands but content exists\n            if self.tool_choices == ToolChoice.AUTO and not self.tool_calls:\n                return bool(content)\n\n            return bool(self.tool_calls)\n        except Exception as e:\n            logger.error(f\"🚨 Oops! The {self.name}'s thinking process hit a snag: {e}\")\n            self.memory.add_message(\n                Message.assistant_message(\n                    f\"Error encountered while processing: {str(e)}\"\n                )\n            )\n            return False\n\n    async def act(self) -> str:\n        \"\"\"Execute tool calls and handle their results\"\"\"\n        if not self.tool_calls:\n            if self.tool_choices == ToolChoice.REQUIRED:\n                raise ValueError(TOOL_CALL_REQUIRED)\n\n            # Return last message content if no tool calls\n            return self.messages[-1].content or \"No content or commands to execute\"\n\n        results = []\n        for command in self.tool_calls:\n            # Reset base64_image for each tool call\n            self._current_base64_image = None\n\n            result = await self.execute_tool(command)\n\n            if self.max_observe:\n                result = result[: self.max_observe]\n\n            logger.info(\n                f\"🎯 Tool '{command.function.name}' completed its mission! Result: {result}\"\n            )\n","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/FoundationAgents/OpenManus/blob/52a13f2a57d8c7f6737eefb02ccf569594d44273/app/agent/toolcall.py#L117-L153","documentation":"Raised in ToolCallAgent.act() when the agent produced no tool calls while tool_choices is ToolChoice.REQUIRED. In REQUIRED mode the LLM must invoke at least one tool; an empty tool_calls list means the model answered in plain text instead. This is a hard contract violation for pipelines that depend on structured tool output.","triggerScenarios":"Agent configured with tool_choices=ToolChoice.REQUIRED (\"required\") but the model replies with text only; weaker models ignoring the tool_choice constraint; tool schemas not registered so the model has nothing valid to call.","commonSituations":"Using a model that does not support tool_choice=\"required\" (some open-weight/local models); tools list empty at request time; temperature too high causing the model to skip tools.","solutions":["Re-run think() before act() so the model gets another chance (loop think/act as the framework intends) instead of calling act() directly","Use a model that honors tool_choice=\"required\" (gpt-4o class models)","If plain-text answers are acceptable, set tool_choices=ToolChoice.AUTO so act() falls back to the last message content"],"exampleFix":"# before\nresult = await agent.act()  # raises if think() produced no tool calls\n\n# after\nawait agent.think()\nresult = await agent.act()","handlingStrategy":"validation","validationCode":"from app.agent.toolcall import ToolChoice\n\ndef can_act(agent) -> bool:\n    if agent.tool_choices == ToolChoice.REQUIRED:\n        return bool(agent.tool_calls)\n    return True","typeGuard":null,"tryCatchPattern":"try:\n    out = await agent.act()\nexcept ValueError as e:\n    if \"Tool calls required\" in str(e):\n        # give the model another chance to produce tool calls\n        await agent.think()\n        out = await agent.act()\n    else:\n        raise","preventionTips":["Always drive the think()/act() loop rather than calling act() standalone","Prefer ToolChoice.AUTO unless structured tool output is mandatory","Use models that reliably honor tool_choice='required' for REQUIRED-mode pipelines"],"tags":["agent","tool-calling","validation"],"backgroundTag":null,"analyzedSha":"52a13f2a57d8c7f6737eefb02ccf569594d44273","analyzedAt":"2026-08-15T02:33:49.993Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}