Step KV (:kv)
Quick Answer
Use :kv for workspace-scoped key/value state that must survive across steps and runs.
{:type :kv :operation :get|:set|:delete|:exists|:increment|:append|:list-keys ...}
Canonical Shape
| Field | Type | Required | Notes |
|---|---|---|---|
:type | keyword | Yes | Must be :kv |
:operation | keyword/string | Yes | One of :get, :set, :delete, :exists, :increment, :append, :list-keys |
:key | string | Depends | Required for all key-based operations |
:default | any | No | :get fallback when key missing/expired |
:value | any | No | :set payload |
:ttl | int | No | TTL in seconds (1 to 31536000) |
:metadata | map | No | Optional metadata with :set |
:if-not-exists | bool | No | Conditional create on :set |
:delta | int/double | No | Increment amount (:increment) |
:item, :items | any/vector | No | Items to append (:append) |
:max-length | int | No | Max list size for :append (default 1000) |
:prefix | string | No | Prefix filter for :list-keys |
:limit | int | No | Max keys for :list-keys |
Limits And Behavior
- Key length: max
256chars. - Key charset:
a-z,A-Z,0-9,_,-,:. - Value size: max
1 MBserialized. :ttlmax:31536000seconds (1 year).:list-keyslimit max:1000.- Expired keys are treated as missing during reads/exists/list.
Result Shapes
Representative results:
;; :get
{:success true :value {:foo "bar"} :exists? true}
;; :set
{:success true :key "session:123" :created? true}
;; :increment
{:success true :key "quota:user-42" :value 11 :previous 10}
;; :list-keys
{:success true :keys ["session:1" "session:2"] :count 2}
Canonical Example
{:functions [{:id :session-key
:language :clojure
:code "(fn [input]\n {:key (str \"session:\" (:session-id input) \":history\")})"}]
:flow
'(let [k (flow/step :function :build-session-key
{:ref :session-key
:input (flow/input)})
history (flow/step :kv :load-history
{:operation :get
:key (:key k)
:default []})
updated (conj history {:at (flow/now-ms)
:message \"hello\"})]
(flow/step :kv :save-history
{:operation :set
:key (:key k)
:value updated
:ttl 86400}))}