Reference

Orchestration Constructs

Canonical reference for non-step flow forms and metadata labels used for readable orchestration timelines.

Quick Answer

Use standard flow forms (if, for, loop, cond, case, etc.) inside :flow, and annotate control nodes with metadata labels (^{:label ...}) so runs render human-readable branch and loop names.

Supported Non-Step Forms

  • sequencing: let, do
  • branching: if, if-not, when, when-not, cond, case
  • iteration: for, doseq, loop, recur
  • child orchestration: flow/call-flow

Label Metadata

Attach metadata directly to a control form:

  • shorthand: ^"My Label" (if ...)
  • explicit: ^{:label "My Label"} (if ...)

Branch-specific labels on if / if-not:

^{:label "Risk gate"
  :yes "Requires approval"
  :no "Auto-approve"}
(if (:needs-approval summary)
  (flow/step :wait :approval {...})
  {:action :approve})

Loop metadata:

^{:label "Retry status poll" :max-iterations 6}
(loop [attempt 0]
  (let [status (flow/step :http :get-status
                 {:connection :orders-api
                  :method :get
                  :path "/orders/status"})]
    (if (or (= :done (:state status))
            (>= attempt 5))
      status
      (recur (inc attempt)))))

for / doseq label example:

^{:label "Enrich each order"}
(for [order orders]
  (flow/step :http :enrich-order
    {:connection :orders-api
     :method :get
     :path (str "/orders/" (:id order))}))

Branching Guidance

  • use if / if-not for binary business gates and set :yes / :no
  • use when / when-not for one-sided conditionals
  • use cond / case for multi-branch routing; add ^{:label ...} on the whole form
  • keep transformation logic in top-level :functions, not inside branch bodies

Design Rules

  • label major decisions and loops; skip labels only for trivial one-liners
  • keep labels business-facing ("Approve order?", "Retry payment status")
  • keep :flow focused on orchestration, and call steps/functions/templates for heavy logic/data
  • combine labels with :persist and templates to keep large flows readable and size-safe
  • use flow/poll for bounded external status polling instead of custom unbounded loops

Related

As of Feb 13, 2026