diff --git a/create_account.py b/create_account.py
index b316cd0bca978d77f27a51ea067a3634c675049b..ef77d78b9eed202c406e127fd9b816dbf18dfd10 100755
--- a/create_account.py
+++ b/create_account.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 import sys
 import rc_util
 
diff --git a/dir_verify.py b/dir_verify.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f0127e50b50ebea248a89df0ad1f9a19eb2c545
--- /dev/null
+++ b/dir_verify.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+import sys
+import json
+import shutil
+import rc_util
+from pathlib import Path
+from rc_rmq import RCRMQ
+
+task = 'dir_verify'
+dirs = ['/home', '/data/user', '/data/scratch']
+
+args = rc_util.get_args()
+logger = rc_util.get_logger(args)
+
+# Instantiate rabbitmq object
+rc_rmq = RCRMQ({'exchange': 'RegUsr', 'exchange_type': 'topic'})
+
+def dir_verify(ch, method, properties, body):
+    msg = json.loads(body)
+    username = msg['username']
+    msg['task'] = task
+    msg['success'] = False
+
+    try:
+        for d in dirs:
+            path = Path(d) / msg['username']
+
+            if args.dry_run:
+                logger.info(f'Checking dirs: {path}')
+
+            else:
+                if not path.exists():
+                    # Make sure folder exists and with right permission
+                    path.mkdir(mode=0o700)
+
+                    # Make sure ownership is correct
+                    shutil.chown(path, int(msg['uid']), int(msg['gid']))
+
+                    logger.debug(f'{path} created')
+
+        msg['success'] = True
+
+    except Exception as exception:
+        logger.error('', exc_info=True)
+
+    # send confirm message
+    rc_rmq.publish_msg({
+        'routing_key': 'confirm.' + username,
+        'msg': msg
+    })
+
+    logger.debug(f'User {username} confirmation sent')
+
+    ch.basic_ack(delivery_tag=method.delivery_tag)
+
+
+logger.info(f'Start listening to queue: {task}')
+rc_rmq.start_consume({
+    'queue': task,
+    'routing_key': "verify.*",
+    'cb': dir_verify
+})
+
+logger.info('Disconnected')
+rc_rmq.disconnect()
diff --git a/git_commit.py b/git_commit.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ea965d288dd5c240e0c72d58b00921c91344777
--- /dev/null
+++ b/git_commit.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+import os
+import sh
+import sys
+import json
+import rc_util
+from rc_rmq import RCRMQ
+
+task = 'git_commit'
+
+# Instantiate rabbitmq object
+rc_rmq = RCRMQ({'exchange': 'RegUsr', 'exchange_type': 'topic'})
+
+# Define some location
+repo_location = os.path.expanduser('~/git/rc-users')
+users_dir = repo_location + '/users'
+groups_dir = repo_location + '/groups'
+
+args = rc_util.get_args()
+logger = rc_util.get_logger(args)
+
+if not args.dry_run:
+    git = sh.git.bake('-C', repo_location)
+    ldapsearch = sh.Command('ldapsearch')
+else:
+    git = sh.echo.bake('git', '-C', repo_location)
+    ldapsearch = sh.echo.bake('ldapsearch')
+
+def git_commit(ch, method, properties, body):
+    msg = json.loads(body)
+    username = msg['username']
+    ticketnum = msg.get('ticketnum', 'add-users-' + username.lower())
+    msg['task'] = task
+    msg['success'] = False
+    branch_name = 'issue-' + ticketnum
+    user_ldif = users_dir + f'/{username}.ldif'
+    group_ldif = groups_dir + f'/{username}.ldif'
+
+    logger.info("Received: %s", msg)
+    logger.debug("ticketnum: %s", ticketnum)
+    logger.debug("branch_name: %s", branch_name)
+
+    try:
+
+        logger.debug('git checkout master')
+        git.checkout('master')
+        logger.debug('git pull')
+        git.pull()
+        logger.debug('git checkout -b %s', branch_name)
+        git.checkout('-b', branch_name)
+
+        logger.debug("open(%s, 'w'), open(%s, 'w')", user_ldif, group_ldif)
+        with open(user_ldif, 'w') as ldif_u,\
+            open(group_ldif, 'w') as ldif_g:
+            logger.debug(f"ldapsearch -LLL -x -h ldapserver -b 'dc=cm,dc=cluster' uid={username} > {user_ldif}")
+            ldapsearch('-LLL', '-x', '-h', 'ldapserver', '-b', "dc=cm,dc=cluster", f"uid={username}", _out=ldif_u)
+            logger.debug(f"ldapsearch -LLL -x -h ldapserver -b 'ou=Group,dc=cm,dc=cluster' cn={username} > {group_ldif}")
+            ldapsearch('-LLL', '-x', '-h', 'ldapserver', '-b', "ou=Group,dc=cm,dc=cluster", f"cn={username}", _out=ldif_g)
+        logger.info('user ldif files generated.')
+
+        logger.debug('git add %s', user_ldif)
+        git.add(user_ldif)
+        logger.debug('git add %s', group_ldif)
+        git.add(group_ldif)
+        logger.debug("git commit -m 'Added new cheaha user: %s'", username)
+        git.commit(m="Added new cheaha user: " + username)
+        logger.debug('git checkout master')
+        git.checkout('master')
+
+        logger.debug('git merge %s --no-ff --no-edit', branch_name)
+        git.merge(branch_name, '--no-ff', '--no-edit')
+        logger.debug('git push origin master')
+        git.push('origin', 'master')
+        # merge with gitlab api
+
+        logger.info('Added ldif files and committed to git repo')
+
+        msg['success'] = True
+    except Exception as exception:
+        logger.error('', exc_info=True)
+
+    # Send confirm message
+    logger.debug('rc_rmq.publish_msge()')
+    rc_rmq.publish_msg({
+        'routing_key': 'confirm.' + username,
+        'msg': msg
+    })
+    logger.info('confirmation sent')
+
+    # Acknowledge message
+    logger.debug('ch.basic_ack()')
+    ch.basic_ack(delivery_tag=method.delivery_tag)
+
+
+logger.info("Start listening to queue: %s", task)
+rc_rmq.start_consume({
+    'queue': task,
+    'routing_key': "verify.*",
+    'cb': git_commit
+})
+
+logger.info("Disconnected")
+rc_rmq.disconnect()
diff --git a/mail_config.py b/mail_config.py
new file mode 100644
index 0000000000000000000000000000000000000000..1146e3848f5e3a0bdcc3fc24a6fdcb711d475b0a
--- /dev/null
+++ b/mail_config.py
@@ -0,0 +1,30 @@
+# Some variable for email
+Server = 'localhost'
+My_email = 'root@localhost'
+Sender = 'ROOT@LOCALHOST'
+Sender_alias = 'Services'
+Subject = 'New User Account'
+Info_url = 'https://www.google.com'
+
+Head = f"""From: {Sender_alias} <{Sender}>
+To: <{{{{ to }}}}>
+Subject: {Subject}
+"""
+
+Body = f"""
+Hi {{{{ username }}}}
+Your account has been set up with:
+
+============================
+User ID:  {{{{ username }}}}
+============================
+
+If you have any questions, please visit:
+{Info_url}
+
+or email at {My_email}
+
+Cheers,
+"""
+
+Whole_mail = Head + Body
diff --git a/notify_user.py b/notify_user.py
new file mode 100644
index 0000000000000000000000000000000000000000..753d14d790c4c1d5fea98ed3709dfaa1739f5cff
--- /dev/null
+++ b/notify_user.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+import sys
+import json
+import rc_util
+import smtplib
+import dataset
+from rc_rmq import RCRMQ
+from jinja2 import Template
+from datetime import datetime
+import mail_config as mail_cfg
+
+task = 'notify_user'
+
+args = rc_util.get_args()
+logger = rc_util.get_logger(args)
+
+db = dataset.connect(f'sqlite:///.agent_db/{task}.db')
+table = db['notified_user']
+
+# Instantiate rabbitmq object
+rc_rmq = RCRMQ({'exchange': 'RegUsr', 'exchange_type': 'topic'})
+
+# Email instruction to user
+def notify_user(ch, method, properties, body):
+    msg = json.loads(body)
+    username = msg['username']
+    user_email = msg['email']
+    msg['task'] = task
+    msg['success'] = False
+
+    try:
+
+        # Search username in database
+        record = table.find_one(username=username)
+
+        if record:
+            # Update counter
+            count = record['count']
+            table.update({'username': username, 'count': count + 1}, ['username'])
+
+            logger.debug(f'User {username} counter updated to {count + 1}')
+
+        else:
+            # Send email to user
+            receivers = [user_email, mail_cfg.My_email]
+            message = Template(mail_cfg.Whole_mail).render(username=username, to=user_email)
+
+            if args.dry_run:
+                logger.info(f'smtp = smtplib.SMTP({mail_cfg.Server})')
+                logger.info(f'smtp.sendmail({mail_cfg.Sender}, {receivers}, message)')
+                logger.info(f"table.insert({{'username': {username}, 'count': 1, 'sent_at': datetime.now()}})")
+
+            else:
+                smtp = smtplib.SMTP(mail_cfg.Server)
+                smtp.sendmail(mail_cfg.Sender, receivers, message)
+
+                logger.debug(f'Email sent to: {user_email}')
+
+                table.insert({
+                    'username': username,
+                    'count': 1,
+                    'sent_at': datetime.now()
+                })
+
+                logger.debug(f'User {username} inserted into database')
+
+        msg['success'] = True
+    except Exception as exception:
+        logger.error('', exc_info=True)
+
+    # Send confirm message
+    rc_rmq.publish_msg({
+        'routing_key': 'confirm.' + username,
+        'msg': msg
+    })
+
+    logger.debug(f'User {username} confirmation sent')
+
+    # Acknowledge the message
+    ch.basic_ack(delivery_tag=method.delivery_tag)
+
+
+if __name__ == "__main__":
+    logger.info(f'Start listening to queue: {task}')
+    rc_rmq.start_consume({
+        'queue': task,
+        'routing_key': "notify.*",
+        'cb': notify_user
+    })
+
+    logger.info('Disconnected')
+    rc_rmq.disconnect()
diff --git a/requirements.txt b/requirements.txt
index 4fd3ec63932e6b593735241cb97e87ca05ac34dd..562cb606a776a6080f5acab0f53490d766dd2a2b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,5 @@
 pika==1.1.0
 pyldap==3.0.0.post1
+dataset==1.3.1
+Jinja2==2.11.2
+sh==1.12.14
\ No newline at end of file
diff --git a/task_manager.py b/task_manager.py
new file mode 100644
index 0000000000000000000000000000000000000000..604c1ec283135ded7661e2e2f08e71e2f50a44f6
--- /dev/null
+++ b/task_manager.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+import sys
+import json
+import rc_util
+from rc_rmq import RCRMQ
+from datetime import datetime
+
+task = 'task_manager'
+
+args = rc_util.get_args()
+logger = rc_util.get_logger(args)
+
+record = {
+    'uid': -1,
+    'gid': -1,
+    'email': '',
+    'fullname': '',
+    'last_update': datetime.now(),
+    'request': {
+        'get_next_uid_gid': None
+    },
+    'create': {
+        'subscribe_mail_list': None,
+        'bright_account': None
+    },
+    'verify': {
+        'git_commit': None,
+        'dir_verify': None
+    },
+    'notify': {
+        'notify_user': None
+    },
+    'delivery_tags': None
+}
+
+# Currently tracking users
+tracking = {}
+
+# Instantiate rabbitmq object
+rc_rmq = RCRMQ({'exchange': 'RegUsr', 'exchange_type': 'topic'})
+
+def task_manager(ch, method, properties, body):
+    msg = json.loads(body)
+    username = method.routing_key.split('.')[1]
+    task_name = msg['task']
+    done = success = msg['success']
+    routing_key = ""
+
+    if username not in tracking:
+        current = tracking[username] = record.copy()
+        current['delivery_tags'] = []
+        current['uid'] = msg.get('uid', -1)
+        current['gid'] = msg.get('gid', -1)
+        current['email'] = msg.get('email', '')
+        current['fullname'] = msg.get('fullname', '')
+
+        logger.debug(f'Tracking user {username}')
+    else:
+        current = tracking[username]
+
+    # Save the delivery tags for future use
+    current['delivery_tags'].append(method.delivery_tag)
+
+    try:
+        if task_name in current['request']:
+            current['request'][task_name] = success
+            routing_key = 'create.' + username
+            done = success
+
+            logger.debug(f'Request level task(s) done?{done}')
+
+        elif task_name in current['create']:
+            current['create'][task_name] = success
+            routing_key = 'verify.' + username
+            done = True
+            for status in current['create'].values():
+                if status is not True:
+                    done = False
+
+            logger.debug(f'Create level task(s) done?{done}')
+
+        elif task_name in current['verify']:
+            current['verify'][task_name] = success
+            routing_key = 'notify.' + username
+            done = True
+            for status in current['verify'].values():
+                if status is not True:
+                    done = False
+
+            logger.debug(f'Verify level task(s) done?{done}')
+
+        elif task_name in current['notify']:
+            current['verify'][task_name] = success
+            routing_key = 'complete.' + username
+            done = success
+
+            logger.debug(f'Notify level task(s) done?{done}')
+
+    except Exception as exception:
+        logger.error('', exc_info=True)
+
+    if done:
+        # Send trigger message
+        rc_rmq.publish_msg({
+            'routing_key': routing_key,
+            'msg': {
+                'username': username,
+                'fullname': current['fullname'],
+                'email': current['email'],
+                'uid': current['uid'],
+                'gid': current['gid']
+            }
+        })
+
+        logger.debug(f"Trigger message '{routing_key}' sent")
+
+        # Acknowledge all message from last level
+        for tag in current['delivery_tags']:
+            ch.basic_ack(tag)
+        current['delivery_tags'] = []
+
+        logger.debug('Previous level messages acknowledged')
+
+
+logger.info(f'Start listening to queue: {task}')
+rc_rmq.start_consume({
+    'queue': task,
+    'routing_key': "confirm.*",
+    'cb': task_manager
+})
+
+logger.info('Disconnected')
+rc_rmq.disconnect()