{"record":{"id":"c6aeeba10bb30da8","repo":"huggingface/smolagents","slug":"agent-interrupted","errorCode":null,"errorMessage":"Agent interrupted.","messagePattern":"Agent interrupted\\.","errorType":"exception","errorClass":"AgentError","httpStatus":null,"severity":"warning","filePath":"src/smolagents/agents.py","lineNumber":547,"sourceCode":"\n            return RunResult(\n                output=output,\n                token_usage=token_usage,\n                steps=step_dicts,\n                timing=Timing(start_time=run_start_time, end_time=time.time()),\n                state=state,\n            )\n\n        return output\n\n    def _run_stream(\n        self, task: str, max_steps: int, images: list[\"PIL.Image.Image\"] | None = None\n    ) -> Generator[ActionStep | PlanningStep | FinalAnswerStep | ChatMessageStreamDelta]:\n        self.step_number = 1\n        returned_final_answer = False\n        while not returned_final_answer and self.step_number <= max_steps:\n            if self.interrupt_switch:\n                raise AgentError(\"Agent interrupted.\", self.logger)\n\n            # Run a planning step if scheduled\n            if self.planning_interval is not None and (\n                self.step_number == 1 or (self.step_number - 1) % self.planning_interval == 0\n            ):\n                planning_start_time = time.time()\n                planning_step = None\n                for element in self._generate_planning_step(\n                    task, is_first_step=len(self.memory.steps) == 1, step=self.step_number\n                ):  # Don't use the attribute step_number here, because there can be steps from previous runs\n                    yield element\n                    planning_step = element\n                assert isinstance(planning_step, PlanningStep)  # Last yielded element should be a PlanningStep\n                planning_end_time = time.time()\n                planning_step.timing = Timing(\n                    start_time=planning_start_time,\n                    end_time=planning_end_time,\n                )","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/agents.py#L529-L565","documentation":"Agents support graceful interruption via an interrupt_switch; when it is set (e.g. by agent.interrupt()), the ReAct loop in _run_stream raises AgentError('Agent interrupted.') at the top of the next step instead of continuing.","triggerScenarios":"Calling agent.interrupt() (or setting agent.interrupt_switch = True) from another thread/callback while agent.run(...) is executing; the loop checks the switch before each step, so a long LLM call finishes before the error surfaces.","commonSituations":"Cancelling a runaway agent from a UI, timeout watchdog thread, or gradio button; interrupting during a long tool execution (the current step completes first).","solutions":["Catch AgentError in the run loop and check whether it's an interruption if you need to distinguish it from failures","Call interrupt() only from a different thread than the one running agent.run()","If run() keeps going, note the switch is checked between steps: wait for the current step to finish"],"exampleFix":"# before\nthreading.Thread(target=agent.run, args=(task,)).start()\nagent.interrupt()  # raises AgentError('Agent interrupted.') inside run\n\n# after\ntry:\n    agent.run(task)\nexcept AgentError as e:\n    if \"interrupted\" in str(e):\n        logger.info(\"Run cancelled by user\")\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from smolagents import AgentError\ntry:\n    result = agent.run(task)\nexcept AgentError as e:\n    if \"interrupted\" in str(e):\n        handle_cancelled()\n    else:\n        raise","preventionTips":["Call agent.interrupt() from a watchdog thread only, never the run thread","Treat AgentError with 'interrupted' as a normal cancellation, not a failure"],"tags":["smolagents","interruption","cancellation","agenterror"],"backgroundTag":"task-cancellation-interrupted","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}