Thinking about a modern agent orchestration / busi...
# thinking-together
n
Thinking about a modern agent orchestration / business process modeling / workflow language. Here is how the standard BPMN example might look like:
Copy code
# Tasks are enqueued jobs to specific queues. They emit events like started, success, failure, cancelled as well as custom intermediate events.
# Tasks cannot consume events. Task invoker can cancel those tasks.
# Tasks are triggerred by specific events indicated by their corresponding "when" clause.
# Process is a stateful workflow which orchestrates tasks based on events.

process pizza() do
    x = @customer.select_pizza when $start
    y = @customer.order_pizza(kind: x.kind) when x
    z = @chef.make_pizza(order: y.order) when y
    
    p = y.order.line_items.map do |item| # array processing
        subprocess procure(item: item) #invoke a subprocess
    end when z
    q = @clerk.pack when p.all?
    
    w = @delivery_boy.deliver_pizza(to: y.address) when z
    u = @customer.pay_for_pizza when w
    v = @customer.eat_pizza when u
    success $hunger_satisfied when v

    r = @customer.ask_for_pizza when (y or r[-1] + 60.minutes) and w.pending?
    s = @clerk.calm_the_customer when r
end
a
Is the text the language, the chart, or both?
n
Text is the proposed language. The chart is that of the classic example used in BPMN docs.
a
It’s nice that the “when” syntax reads left-to-right. It necessitates naming every single task, though, and those names are the hardest part to follow for me (x, y, z, p, etc).
n
Yeah. Naming of tasks is needed because they are used to specify event conditions to trigger followup tasks. I couldn't think of a way out of this.
Similar approach in Spotify's Prefect framework: https://docs.prefect.io/latest/concepts/tasks/#wait-for
a
I don’t see any of the task initializers being reused except procure, so I wonder if you could use those to identify and give the tasks names only when necessary? Along the lines of “@chef.make_pizza(…) when @customer.order_pizza”?
n
No, the same task could be used at multiple times with say, different arguments.
a
I’ve seen serial syntax like >> used too, but that doesn’t help with so much fanout.
Oh yeah, I’m just saying that I don’t actually see that happening almost at all in this workflow, so maybe the cases that need disambiguation can use the “x, y, z” names if they’re more exceptional? Just a thought.
n
Yeah, good point.
j
"do" is a bit awkward, because it's not imperative code. It's declarative, describing a process that may never be initiated. When $start also feels like it should be implicit for anything that doesn't have a different trigger. The names could be more descriptive than lowercase letters. I might be inclined to use "when {name} happens" , and "step: {name} is" to make it clearer, too. But all that should be taken with a grain of salt, because I have never been able to understand why I would want to use BPMN. All my use cases seem deeply ill-suited to it.
n
@Jason Morris All good points.
do ... end
is just a construct I copied from Ruby's block syntax. BPMN has around 120 types of elements including exclusive gateways, parallel gateways which seems highly unnecessary. I'm trying to avoid all those elements with some kind of composable event algebra. I think workflow engines (where some tasks could be done by humans) have been underutilized by developers precisely because of BPMN's complexity.
j
I think BPMN not having a semantics has been the biggest issue in people not using BPMN for workflow. But there are other ways to do workflow, and the ones that get used the most don't require BPMN.