Constructing a packet header
Looks pretty good to me.  There are a few shortcuts you could add if you don't mind using the Tupelo Clojure library.  One of them is vals->map
and with-map-vals.  

Called with a list of symbols like (vals-&gt;map a b c) returns a map like {:a a :b b :c c}:

(let [a 1
      b 2
      c 3]
  (vals-&gt;map a b c))  ;=&gt;  {:a 1 :b 2 :c 3} }


Given a map like {:a 1 :b 2 :c 3} (such as generated by (vals-&gt;map a b c)), performs safe let destructuring using grab like:

   (let [some-map  {:a 1 :b 2 :c 3} } ]
     (with-map-vals some-map [a b c]
        (+ a b c)))  ;=&gt;  6


with-map-vals is safe for typos since grab will throw if the requested key is not present. See vals->map for simple creation of labeled data maps.

For default values, I think the simplest way is like this:

  (let [defaults {:a 1 :dir :up :name "joe"}
        v1       {:a 2}
        v2       {:a 9 :dir :left :name "sally"}]
    (spyx (into defaults v1))
    (spyx (glue defaults v2))


There is also the pure clojure way:

; Pure clojure way
(let [{:keys [a dir name ] } v1]
  (spyx :pure-1 (vals-&gt;map a dir name)) )

; can't use `defaults` here, need map with keyword =&gt; symbol
(let [{:keys [a dir name] :or {a 1 dir :up name "joe"}} v1] 
  (spyx :pure-2 (vals-&gt;map a dir name)))

(let [{:keys [a dir name ] :or {a 1 dir :up name "joe"}} v2] 
  (spyx :pure-1 (vals-&gt;map a dir name)) )


See also Clojure Destructuring.



Lastly, instead of concat I like to use glue.

; Glue together like collections:
(is (= (glue [ 1 2] '(3 4) [ 5 6] )       [ 1 2 3 4 5 6 ]  ))   ; all sequential (vectors &amp; lists)
(is (= (glue {:a 1} {:b 2} {:c 3} )       {:a 1 :c 3 :b 2} ))   ; all maps
(is (= (glue #{1 2} #{3 4} #{6 5} )      #{ 1 2 6 5 3 4 }  ))   ; all sets
(is (= (glue "I" " like " \a " nap!" )   "I like a nap!"   ))   ; all text (strings &amp; chars)

; If you want to convert to a sorted set or map, just put an empty one first:
(is (= (glue (sorted-map) {:a 1} {:b 2} {:c 3})   {:a 1 :b 2 :c 3} ))
(is (= (glue (sorted-set) #{1 2} #{3 4} #{6 5})  #{ 1 2 3 4 5 6  } ))




Lastly, I wouldn't bother with defn-  It just makes testing harder and provides little value.  If you have non-public functions that you don't want in the documentation (via the lein-codox plugin), you can add metadata to the function like:

(defn ^:no-doc my-helper-fn
  ...)