diff --git a/beat/backend/python/algorithm.py b/beat/backend/python/algorithm.py
index 2cb4a95edc06315c0f318458d883a4ccdfa2be47..4d8c1679cf51cc6e20d8d21388b1ccb1107d9745 100644
--- a/beat/backend/python/algorithm.py
+++ b/beat/backend/python/algorithm.py
@@ -214,7 +214,10 @@ class Runner(object):
 
         # The method is optional
         if hasattr(self.obj, "prepare"):
-            if self.algorithm.type in [Algorithm.AUTONOMOUS, Algorithm.LOOP_USER]:
+            if self.algorithm.type in [
+                Algorithm.AUTONOMOUS,
+                Algorithm.AUTONOMOUS_LOOP_USER,
+            ]:
                 self.prepared = loader.run(
                     self.obj, "prepare", self.exc, data_loaders.secondaries()
                 )
@@ -264,35 +267,40 @@ class Runner(object):
         else:
             _check_argument(data_loaders, "data_loaders")
 
-            if self.algorithm.type == Algorithm.SEQUENTIAL:
+            if self.algorithm.is_sequential:
                 _check_argument(inputs, "inputs")
 
-                return loader.run(
-                    self.obj, "process", self.exc, inputs, data_loaders, outputs_to_use
-                )
+                run_args = [
+                    self.obj,
+                    "process",
+                    self.exc,
+                    inputs,
+                    data_loaders,
+                    outputs_to_use,
+                ]
 
             elif self.algorithm.is_autonomous:
                 run_args = [self.obj, "process", self.exc, data_loaders, outputs_to_use]
 
-                has_loop_arg = utils.has_argument(self.obj.process, "loop_channel")
-                if loop_channel is not None:
-                    if has_loop_arg:
-                        run_args.append(loop_channel)
-                    else:
-                        raise exc(
-                            "Algorithm '%s' is not a valid loop enabled algorithm"
-                            % self.name
-                        )
-                elif has_loop_arg:
+            else:
+                raise exc("Unknown algorithm type: %s" % self.algorithm.type)
+
+            has_loop_arg = utils.has_argument(self.obj.process, "loop_channel")
+            if loop_channel is not None:
+                if has_loop_arg:
+                    run_args.append(loop_channel)
+                else:
                     raise exc(
-                        "Algorithm '%s' is a loop enabled algorithm but no loop_channel given"
+                        "Algorithm '%s' is not a valid loop enabled algorithm"
                         % self.name
                     )
+            elif has_loop_arg:
+                raise exc(
+                    "Algorithm '%s' is a loop enabled algorithm but no loop_channel given"
+                    % self.name
+                )
 
-                return loader.run(*run_args)
-
-            else:
-                raise exc("Unknown algorithm type: %s" % self.algorithm.type)
+            return loader.run(*run_args)
 
     def validate(self, result):
         """Validates the given results"""
@@ -404,7 +412,8 @@ class Algorithm(object):
     SEQUENTIAL = "sequential"
     AUTONOMOUS = "autonomous"
     LOOP = "loop"
-    LOOP_USER = "loop_user"
+    SEQUENTIAL_LOOP_USER = "sequential_loop_user"
+    AUTONOMOUS_LOOP_USER = "autonomous_loop_user"
 
     def __init__(self, prefix, name, dataformat_cache=None, library_cache=None):
 
@@ -672,7 +681,16 @@ class Algorithm(object):
     @property
     def is_autonomous(self):
         """ Returns whether the algorithm is in the autonomous category"""
-        return self.type in [Algorithm.AUTONOMOUS, Algorithm.LOOP_USER, Algorithm.LOOP]
+        return self.type in [
+            Algorithm.AUTONOMOUS,
+            Algorithm.AUTONOMOUS_LOOP_USER,
+            Algorithm.LOOP,
+        ]
+
+    @property
+    def is_sequential(self):
+        """ Returns whether the algorithm is in the sequential category"""
+        return self.type in [Algorithm.SEQUENTIAL, Algorithm.SEQUENTIAL_LOOP_USER]
 
     @language.setter
     def language(self, value):
diff --git a/beat/backend/python/test/prefix/algorithms/autonomous/loop_user/1.json b/beat/backend/python/test/prefix/algorithms/autonomous/loop_user/1.json
index ebd5c1252886fafa75b07570535a0d0980f52bf6..1cd6567396066fc77746db386afeb962abf3ba00 100644
--- a/beat/backend/python/test/prefix/algorithms/autonomous/loop_user/1.json
+++ b/beat/backend/python/test/prefix/algorithms/autonomous/loop_user/1.json
@@ -2,7 +2,7 @@
     "schema_version": 3,
     "language": "python",
     "api_version": 2,
-    "type": "loop_user",
+    "type": "autonomous_loop_user",
     "splittable": false,
     "groups": [
         {
diff --git a/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.json b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.json
new file mode 100644
index 0000000000000000000000000000000000000000..4fc4a7846508e233687362c3d81428e8bfc6fca8
--- /dev/null
+++ b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.json
@@ -0,0 +1,29 @@
+{
+    "schema_version": 3,
+    "language": "python",
+    "api_version": 2,
+    "type": "sequential_loop_user",
+    "splittable": false,
+    "groups": [
+        {
+            "inputs": {
+                "in": {
+                    "type": "user/single_integer/1"
+                }
+            },
+            "outputs": {
+                "out": {
+                    "type": "user/single_integer/1"
+                }
+            },
+            "loop": {
+                "request": {
+                    "type": "user/single_integer/1"
+                },
+                "answer": {
+                    "type": "user/single_integer/1"
+                }
+            }
+        }
+    ]
+}
diff --git a/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.py b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0ee50d0ce75ceff0aa4830635275da81d1bd171
--- /dev/null
+++ b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+###################################################################################
+#                                                                                 #
+# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/               #
+# Contact: beat.support@idiap.ch                                                  #
+#                                                                                 #
+# Redistribution and use in source and binary forms, with or without              #
+# modification, are permitted provided that the following conditions are met:     #
+#                                                                                 #
+# 1. Redistributions of source code must retain the above copyright notice, this  #
+# list of conditions and the following disclaimer.                                #
+#                                                                                 #
+# 2. Redistributions in binary form must reproduce the above copyright notice,    #
+# this list of conditions and the following disclaimer in the documentation       #
+# and/or other materials provided with the distribution.                          #
+#                                                                                 #
+# 3. Neither the name of the copyright holder nor the names of its contributors   #
+# may be used to endorse or promote products derived from this software without   #
+# specific prior written permission.                                              #
+#                                                                                 #
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED   #
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          #
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE    #
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL      #
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR      #
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER      #
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,   #
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   #
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.            #
+#                                                                                 #
+###################################################################################
+
+
+import numpy as np
+
+
+class Algorithm:
+    def process(self, inputs, data_loaders, outputs, loop_channel):
+        cnt = 10
+        is_valid, _ = loop_channel.validate({"value": np.int32(cnt)})
+        while not is_valid:
+            cnt = cnt - 1
+            is_valid, _ = loop_channel.validate({"value": np.int32(cnt)})
+
+        value = inputs["in"].data.value
+        new_value = value + cnt
+        outputs["out"].write({"value": np.int32(new_value)})
+
+        return True
diff --git a/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.rst b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e62c1c42520de03eed49b89f3ed95fce122745de
--- /dev/null
+++ b/beat/backend/python/test/prefix/algorithms/sequential/loop_user/1.rst
@@ -0,0 +1 @@
+Test documentation
diff --git a/beat/backend/python/test/test_algorithm.py b/beat/backend/python/test/test_algorithm.py
index 0e75b54f478e66c2af71d0e9466254f1898586bb..31c1197121ce457afe947af8317a77907c172673 100644
--- a/beat/backend/python/test/test_algorithm.py
+++ b/beat/backend/python/test/test_algorithm.py
@@ -234,6 +234,24 @@ class TestSequentialAPI_Loading(unittest.TestCase):
         self.assertFalse(runnable.ready)
         self.assertFalse(runnable.prepared)
 
+    def test_load_valid_loop_user(self):
+        algorithm = Algorithm(prefix, "sequential/loop_user/1")
+        self.assertEqual(algorithm.name, "sequential/loop_user/1")
+        self.assertTrue(algorithm.valid)
+
+        self.assertFalse(algorithm.errors)
+        self.assertFalse(algorithm.results)  # it is not an analyzer
+        self.assertFalse(algorithm.parameters)  # does not contain parameters
+        self.assertTrue(algorithm.input_map)
+        self.assertTrue(algorithm.output_map)
+        self.assertEqual(algorithm.schema_version, 3)
+        self.assertEqual(algorithm.api_version, 2)
+        self.assertEqual(algorithm.type, Algorithm.SEQUENTIAL_LOOP_USER)
+
+        runnable = algorithm.runner()
+        self.assertTrue(runnable.ready)
+        self.assertTrue(runnable.prepared)
+
 
 # ----------------------------------------------------------
 
@@ -285,6 +303,24 @@ class TestAutonomousAPI_Loading(unittest.TestCase):
         self.assertFalse(runnable.ready)
         self.assertFalse(runnable.prepared)
 
+    def test_load_valid_loop_user(self):
+        algorithm = Algorithm(prefix, "autonomous/loop_user/1")
+        self.assertEqual(algorithm.name, "autonomous/loop_user/1")
+        self.assertTrue(algorithm.valid)
+
+        self.assertFalse(algorithm.errors)
+        self.assertFalse(algorithm.results)  # it is not an analyzer
+        self.assertFalse(algorithm.parameters)  # does not contain parameters
+        self.assertTrue(algorithm.input_map)
+        self.assertTrue(algorithm.output_map)
+        self.assertEqual(algorithm.schema_version, 3)
+        self.assertEqual(algorithm.api_version, 2)
+        self.assertEqual(algorithm.type, Algorithm.AUTONOMOUS_LOOP_USER)
+
+        runnable = algorithm.runner()
+        self.assertTrue(runnable.ready)
+        self.assertTrue(runnable.prepared)
+
 
 # ----------------------------------------------------------