    :kick"
   [chat-source user event-type body]
   ; only :message has a body
-  (when body
-    ; see if it looks like a command
-    (when-let [[_ body] (re-find #"^\!(.+)" body)]
-      (with-fresh-db
-        (try
-          (chat-data-structure
-            (handle-unparsed-expr chat-source user body))
-          (catch Throwable ex
-            (error
-              "error handling expression:" body
-              (format-exception-log ex))
-            (chat-data-structure (format exception-format ex))))))))
-
+  (go (when body
+        ; see if it looks like a command
+        (when-let [[_ body] (re-find #"^\!(.+)" body)]
+          (with-fresh-db
+            (try
+              (chat-data-structure
+                (handle-unparsed-expr chat-source user body))
+              (catch Throwable ex
+                (error
+                  "error handling expression:" body
+                  (format-exception-log ex))
+                (chat-data-structure (format exception-format ex)))))))))
 
 (defn cmd-reader [& args] (handle-unparsed-expr (join " " args)))

    [yetibot.core.util.format :refer [to-coll-if-contains-newlines format-exception-log]]
    [yetibot.core.parser :refer [parse-and-eval]]
    [clojure.core.match :refer [match]]
    [yetibot.core.chat :refer [chat-data-structure]]
    [clojure.string :refer [join]]
    [clojure.stacktrace :as st]))

     (handle-unparsed-expr body)))
  ([body] (parse-and-eval body)))

(def ^:private exception-format "👮 %s 👮")

(defn handle-raw
  "No-op handler for optional hooks.
   Expected event-types are:
