diff --git a/slapos/recipe/pbs.py b/slapos/recipe/pbs.py
index 173e0d27373b2f9ddd8c3c9a945c63bd7172c1fc..a1fb9e40038950bebf0070486c3ba0e94d3eeff6 100644
--- a/slapos/recipe/pbs.py
+++ b/slapos/recipe/pbs.py
@@ -26,20 +26,30 @@
 ##############################################################################
 from json import loads as unjson
 from hashlib import sha512
-from urlparse import urlparse
+import urlparse
 import os
 import subprocess
 import sys
 import signal
 import inspect
+import uuid
+import base64
+import urllib
 
 from slapos.recipe.librecipe import GenericSlapRecipe
 from slapos.recipe.dropbear import KnownHostsFile
-from slapos.recipe.notifier import Notify
-from slapos.recipe.notifier import Callback
 from slapos import slap as slapmodule
 
 
+def process_backup(config):
+  from glob import glob
+
+  runafter = config['run_after']
+  pull_script = config['pull']
+  push_scripts = glob(config['push'])
+  os.execv(runafter, [runafter] + ['--first-one', pull_script] + push_scripts)
+
+
 def promise(args):
 
   def failed_ssh(partition, ssh):
@@ -97,23 +107,17 @@ def promise(args):
   return ssh.returncode
 
 
+class Recipe(GenericSlapRecipe):
 
-class Recipe(GenericSlapRecipe, Notify, Callback):
-
-  def add_slave(self, entry, known_hosts_file):
-    path_list = []
-
-    url = entry.get('url')
-    if url is None:
-      url = ''
-
-    # We assume that thanks to sha512 there's no collisions
-    url_hash = sha512(url).hexdigest()
-    name_hash = sha512(entry['name']).hexdigest()
+  def _options(self, options):
+    if self.optionIsTrue('client', True):
+      slaves = unjson(options['slave-instance-list'])
+      options['peers'] = '\n'.join([str(entry['request-agent-url'])
+                                    for entry in slaves])
 
+  def add_slave_promise(self, parsed_url, instance_id):
     promise_path = os.path.join(self.options['promises-directory'],
-                                url_hash)
-    parsed_url = urlparse(url)
+                                instance_id)
     promise_dict = self.promise_base_dict.copy()
     promise_dict.update(user=parsed_url.username,
                         host=parsed_url.hostname,
@@ -121,27 +125,57 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
     promise = self.createPythonScript(promise_path,
                                       __name__ + '.promise',
                                       promise_dict)
-    path_list.append(promise)
+    self.path_list.append(promise)
 
+  def add_slave(self, entry, known_hosts_file):
+    url = entry.get('url')
+    if url is None:
+      url = ''
+
+    # Base32 is filename safe
+    backup_id = base64.b32encode(uuid.UUID(entry['id']).bytes)
+    instance_id = '%(uuid)s%(type)s%(id)s' % {
+      'uuid': backup_id,
+      'type': entry['type'],
+      'id': entry['slave_reference']
+    }
+    parsed_url = urlparse.urlparse(url)
+
+    self.add_slave_promise(parsed_url, instance_id)
 
     host = parsed_url.hostname
-    known_hosts_file[host] = entry['server-key']
+    known_hosts_file[host] = entry['authorized-key']
 
-    remote_schema = '%(ssh)s -p %%s %(user)s@%(host)s' % \
-      {
+    remote_schema = '%(ssh)s -p %%s %(user)s@%(host)s' % {
         'ssh': self.options['sshclient-binary'],
         'user': parsed_url.username,
         'host': parsed_url.hostname,
-      }
+    }
+
+    agent_url = self.options['agent-url']
+    feed_url = urlparse.urljoin(self.options['agent-url'],
+                                'log/%s' % urllib.quote(instance_id))
+    notify_url = urlparse.urljoin(self.options['agent-url'],
+                                  'notify')
+
+    command = [self.options['notifier-binary'],
+               '--write', feed_url,
+               '--title', entry.get('name', 'Untitled'),
+              ]
 
-    command = [self.options['rdiffbackup-binary']]
-    command.extend(['--remote-schema', remote_schema])
+    for notify in entry.get('notify', '').split():
+      if notify: # Ignore empty values
+        import pdb; pdb.set_trace()
+        command.extend(['--notify', notify])
+    command.append('--')
+
+    command.extend([self.options['rdiffbackup-binary'], '--remote-schema', remote_schema])
 
     remote_directory = '%(port)s::%(path)s' % {'port': parsed_url.port,
                                                'path': parsed_url.path}
 
     local_directory = self.createDirectory(self.options['directory'],
-                                           name_hash)
+                                           backup_id)
 
     if entry['type'] == 'push':
       command.extend(['--restore-as-of', 'now'])
@@ -150,48 +184,50 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
     else:
       command.extend([remote_directory, local_directory])
 
-    wrapper_basepath = os.path.join(self.options['wrappers-directory'],
-                                    url_hash)
-
-    wrapper_path = wrapper_basepath
-    if 'notify' in entry:
-      wrapper_path = '%s_raw' % wrapper_basepath
+    wrapper_path = os.path.join(self.options['wrappers-directory'],
+                                instance_id)
 
-    wrapper = self.createPythonScript(
-       wrapper_path,
+    self.path_list.append(self.createPythonScript(
+      wrapper_path,
       'slapos.recipe.librecipe.execute.execute',
-      [str(i) for i in command]
-    )
-    path_list.append(wrapper)
-
-    if 'notify' in entry:
-      feed_url = '%s/get/%s' % (self.options['notifier-url'],
-                                entry['notification-id'])
-      wrapper = self.createNotifier(
-        self.options['notifier-binary'],
-        wrapper=wrapper_basepath,
-        executable=wrapper_path,
-        log=os.path.join(self.options['feeds'], entry['notification-id']),
-        title=entry.get('title', 'Untitled'),
-        notification_url=entry['notify'],
-        feed_url=feed_url,
-      )
-      path_list.append(wrapper)
-      #self.setConnectionDict(dict(feed_url=feed_url), entry['slave_reference'])
-
-    if 'on-notification' in entry:
-      path_list.append(self.createCallback(str(entry['on-notification']),
-                                           wrapper))
-    else:
-      cron_entry = os.path.join(self.options['cron-entries'], url_hash)
-      with open(cron_entry, 'w') as cron_entry_file:
-        cron_entry_file.write('%s %s' % (entry['frequency'], wrapper))
-      path_list.append(cron_entry)
-
-    return path_list
+      command,
+    ))
+
+    if entry['type'] == 'pull':
+      backup_wrapper = os.path.join(self.options['wrapper-directory'],
+                                    backup_id)
+      push_pattern = os.path.join(self.options['wrapper-directory'],
+                                  '%spush*' % backup_id)
+      self.path_list.append(self.createPythonScript(
+        backup_wrapper,
+        __name__ + '.process_backup',
+        {
+          'run_after': self.options['runafter-binary'],
+          'pull': wrapper_path,
+          'push': push_pattern,
+        }
+      ))
+
+      if 'frequency' in entry:
+        cron_entry_filename = os.path.join(self.options['cron-entries'],
+                                           '%s-%s' % (self.name, backup_id))
+        self.path_list.append(self.createFile(cron_entry_filename,
+          '%s %s' % (entry['frequency'], backup_wrapper)))
+      elif 'trigger-feed' in entry:
+        trigger_filename = os.path.join(self.options['agent-callbacks-directory'],
+                                        sha512(entry['trigger-feed']).hexdigest())
+        with open(trigger_filename, 'w') as trigger_file:
+          trigger_file.write(backup_wrapper)
+        self.path_list.append(trigger_filename)
+
+    self.setConnectionDict({
+      'agent-url': agent_url,
+      'feed-url': feed_url,
+      'notify-url': notify_url,
+    }, entry['slave_reference'])
 
   def _install(self):
-    path_list = []
+    self.path_list = []
 
 
     if self.optionIsTrue('client', True):
@@ -211,7 +247,7 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
       known_hosts = KnownHostsFile(self.options['known-hosts'])
       with known_hosts:
         for slave in slaves:
-          path_list.extend(self.add_slave(slave, known_hosts))
+          self.add_slave(slave, known_hosts)
 
     else:
       command = [self.options['rdiffbackup-binary']]
@@ -223,6 +259,6 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
         self.options['wrapper'],
         'slapos.recipe.librecipe.execute.execute',
         command)
-      path_list.append(wrapper)
+      self.path_list.append(wrapper)
 
-    return path_list
+    return self.path_list