diff --git a/lc-esp-sdk/build.gradle b/lc-esp-sdk/build.gradle
index 4e312cd3b79658126e0499168777ee6c18382a7f..c1d2fa58e9c484e859b00bf13c7ddc3f4a691e2f 100644
--- a/lc-esp-sdk/build.gradle
+++ b/lc-esp-sdk/build.gradle
@@ -4,7 +4,7 @@ plugins {
 }
 
 group 'leighco'
-version '18.0'
+version '18.1-SNAPSHOT'
 
 repositories {
     mavenCentral()
diff --git a/lc-esp-sdk/src/main/java/lc/esp/sdk/service/ESPService.java b/lc-esp-sdk/src/main/java/lc/esp/sdk/service/ESPService.java
new file mode 100644
index 0000000000000000000000000000000000000000..14a67972573ad52c7c77b5b81d8f8ec07a588fcf
--- /dev/null
+++ b/lc-esp-sdk/src/main/java/lc/esp/sdk/service/ESPService.java
@@ -0,0 +1,66 @@
+package lc.esp.sdk.service;
+
+import lc.esp.sdk.*;
+import lc.mecha.log.MechaLogger;
+import lc.mecha.log.MechaLoggerFactory;
+
+/**
+ * This class implements a basic ESP request/response server.
+ *
+ * @author Alex Leigh
+ * @since 18.1
+ */
+public abstract class ESPService implements Runnable {
+    private static final MechaLogger logger = MechaLoggerFactory.getLogger(ESPService.class);
+    private final ESPClient client;
+    private final ESPAddress address;
+
+    public ESPService(ESPClient client, ESPAddress address) {
+        this.client = client;
+        this.address = address;
+    }
+
+    public ESPService(ESPAddress address) throws Exception {
+        client = new ESPClient();
+        client.start();
+        this.address = address;
+    }
+
+    public ESPService(String address) throws Exception {
+        this(new ESPAddress(address));
+    }
+
+    @Override
+    public void run() {
+        try {
+            try (ESPSession session = client.createSession()) {
+                try (ESPConsumer consumer = session.createConsumer(address)) {
+                    //noinspection InfiniteLoopStatement
+                    while (true) {
+                        ESPMessage request = consumer.receive();
+                        ESPAddress replyAddress = request.getReplyTo();
+                        if (replyAddress != null) {
+                            try (ESPProducer producer = session.createProducer(replyAddress)) {
+                                ESPMessage reply = handle(request);
+                                if (reply != null) {
+                                    // We force the correlation ID to match the request.
+                                    String correlationId = request.getCorrelationId();
+                                    if (correlationId != null) {
+                                        reply.setCorrelationId(correlationId);
+                                    }
+                                    producer.send(reply);
+                                }
+                            }
+                        } else {
+                            logger.warn("Caller did not supply a return address: {}", request);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public abstract ESPMessage handle(ESPMessage msg);
+}
diff --git a/lc-hello-svc/src/main/java/lc/hello/service/HelloService.java b/lc-hello-svc/src/main/java/lc/hello/service/HelloService.java
index a262d21810dfb3d46e46531f0e4d4662e95e1c5d..57fa291f2e2cdf5796091d1c603c2f10a020c82b 100644
--- a/lc-hello-svc/src/main/java/lc/hello/service/HelloService.java
+++ b/lc-hello-svc/src/main/java/lc/hello/service/HelloService.java
@@ -1,10 +1,10 @@
 package lc.hello.service;
 
-import lc.esp.sdk.*;
+import lc.esp.sdk.ESPMessage;
+import lc.esp.sdk.service.ESPService;
 import lc.mecha.json.JSONObject;
 import lc.mecha.log.MechaLogger;
 import lc.mecha.log.MechaLoggerFactory;
-import lc.mecha.util.BasicallyDangerous;
 
 /**
  * The hello service greets a caller. This service is really only useful for dev/test and as an illustrative example
@@ -13,40 +13,22 @@ import lc.mecha.util.BasicallyDangerous;
  * @author Alex Leigh
  * @since mk18 (GIPSY DANGER)
  */
-public class HelloService extends BasicallyDangerous {
+public class HelloService extends ESPService {
     private static final MechaLogger logger = MechaLoggerFactory.getLogger(HelloService.class);
 
-    public static void main(String[] args) {
-        new HelloService().run();
+    public HelloService() throws Exception {
+        super("queue://lc.dev.example.hello.cmd");
     }
 
-    @Override
-    public void runDangerously() throws Exception {
-        try (ESPClient esp = new ESPClient().start()) {
-            try (ESPSession session = esp.createSession()) {
-                ESPAddress dst = new ESPAddress("queue://lc.dev.example.hello.cmd");
-                try (ESPConsumer consumer = session.createConsumer(dst)) {
-                    //noinspection InfiniteLoopStatement
-                    while (true) {
-                        ESPMessage request = consumer.receive();
-                        ESPAddress replyAddress = request.getReplyTo();
-                        if (replyAddress != null) {
-                            try (ESPProducer producer = session.createProducer(replyAddress)) {
-                                producer.send(buildReply(request));
-                            }
-                        } else {
-                            logger.warn("Requestor did not supply a return address: {}", request);
-                        }
-                    }
-                }
-            }
-        }
+    public static void main(String[] args) throws Exception {
+        new HelloService().run();
     }
 
-    private ESPMessage buildReply(ESPMessage request) {
+    @Override
+    public ESPMessage handle(ESPMessage request) {
         String theirName = request.getPayload().getString("name");
         JSONObject replyJson = new JSONObject();
         replyJson.put("msg", "Hello, " + theirName);
-        return new ESPMessage(replyJson, null, request.getCorrelationId());
+        return new ESPMessage(replyJson);
     }
 }
\ No newline at end of file