diff --git a/src/crewai/flow/flow.py b/src/crewai/flow/flow.py index 99ae82c96c..99985d648d 100644 --- a/src/crewai/flow/flow.py +++ b/src/crewai/flow/flow.py @@ -719,7 +719,10 @@ def kickoff(self, inputs: Optional[Dict[str, Any]] = None) -> Any: async def run_flow(): return await self.kickoff_async(inputs) - return asyncio.run(run_flow()) + try: + return asyncio.run(run_flow()) + except KeyboardInterrupt: + raise async def kickoff_async(self, inputs: Optional[Dict[str, Any]] = None) -> Any: """ diff --git a/tests/flow_test.py b/tests/flow_test.py index c2640fffbc..c7edbb2a9b 100644 --- a/tests/flow_test.py +++ b/tests/flow_test.py @@ -755,3 +755,29 @@ def anemia_analysis(self): assert execution_order.index("anemia_analysis") > execution_order.index( "anemia_router" ) + + +def test_flow_keyboard_interrupt_handling(): + """Test that a flow properly terminates when a keyboard interrupt is received.""" + execution_order = [] + + class KeyboardInterruptFlow(Flow): + @start() + def step_1(self): + execution_order.append("step_1") + + @listen(step_1) + def step_2(self): + execution_order.append("step_2") + raise KeyboardInterrupt() + + @listen(step_2) + def step_3(self): + execution_order.append("step_3") + + flow = KeyboardInterruptFlow() + + with pytest.raises(KeyboardInterrupt): + flow.kickoff() + + assert execution_order == ["step_1", "step_2"]