Skip to main content
Liorry Herisnor
Runtime state: Partially wiredPlatforms

Automation Workflow Execution

A visual canvas builder whose graphs are executed one node per tick by a separate runner, with wait states, branching and a human approval node.

Runtime state: The engine and the builder both work, and executions advance correctly. But three of the four declared trigger types have no event dispatcher, so in practice only manual runs and the RSS worker create executions — and the runner process is not under service management, so it survives neither a reboot nor a deploy.

Business objective
Let an operator express a multi-step recipient journey visually, and have it execute reliably without holding state in a long-running process.
Trigger
A manual run against a specific recipient, or an RSS feed item.
Inputs
  • A workflow graph of nodes and edges
  • A recipient
  • Template and list references the nodes point at
Outputs
  • A per-recipient execution row advancing through the graph
  • Sent messages, tag changes, list moves, webhook calls
  • A completed, failed or waiting execution state

The execution model

The interesting decision here is that state lives in the database, not in a process. A workflow execution is a row. The runner wakes on a fixed interval, claims runnable executions with FOR UPDATE SKIP LOCKED, advances each by exactly one node, and writes the result back.

That has three consequences worth stating:

  • A wait is free. A node that needs to pause for a day sets a future wake time and stops being runnable. No timer, no held connection, no memory.
  • The runner is disposable. Kill it mid-cycle and nothing is lost; the executions it had not yet claimed are still runnable, and the one it was holding is released by the lock.
  • Multiple runners are safe by construction. Skip-locked claiming means two runners never advance the same execution.

The cost is that a workflow advances at most one node per tick, so a ten-node journey takes ten ticks. For recipient journeys measured in hours and days, that is the right trade.

The workflow

Trigger to completed execution

One node per tick. The loop below is the whole engine.

  1. Human action

    Operator authors the graph

    Nodes and edges on a canvas. The trigger node's configuration is synced back onto the workflow row when the canvas is saved.

  2. Approval gate

    Status must be active

    Decision point: Draft and paused workflows refuse to run. Three states only, so there is nothing to interpret.

  3. Automated software

    An execution row is created

    Per recipient. Created by a manual run or by the RSS worker turning a feed item into a journey.

  4. Automated software

    Runner claims runnable executions

    Fixed interval, skip-locked claiming so parallel runners never contend.

  5. Automated software

    Advance exactly one node

    Decision point: Dispatch on node type: trigger, action, wait, condition, approval, end — or an unrecognized type, which advances without acting.

  6. Automated software

    Action node — dispatch on the action

    Five core actions: send the message, add or remove a tag, move the recipient to another list, post to a webhook.

  7. AI / LLM

    Creative actions — six, behind a flag

    Load offer data, normalize inputs, generate creative, score it for compliance and quality, build a template, publish the assets. Gated by a feature flag that defaults off, and generation additionally requires a provider key at runtime.

  8. Automated software

    Wait node

    Sets a future wake time and marks the execution waiting. Minimum one minute, so a misconfigured wait cannot become a busy loop.

  9. Automated software

    Condition node

    Decision point: Six operators — exists, not exists, equals, not equals, contains, not contains. True takes the first edge, false the second.

  10. Approval gate

    Approval node

    Decision point: Halts the execution pending a human. An optional timeout auto-rejects rather than auto-approving — the safe default when nobody responds.

  11. Automated software

    Iteration breaker

    A maximum node count per execution, so a graph with a cycle terminates instead of running forever.

  12. Data store

    Execution reaches a terminal state

    Completed, or failed with the node that failed recorded.

  • Human action
  • Automated software
  • AI / LLM
  • Data store
  • Approval gate

Decision points

  • Is the workflow active? Draft and paused refuse.
  • Which node type is next? A closed set, with an explicit fall-through for anything unrecognized.
  • Condition true or false? Selects the outgoing edge.
  • Approve, reject, or time out? The approval node's three outcomes, where timing out means rejection.
  • Has the iteration cap been hit? The cycle guard.

Responsibilities

AI / LLM

  • The six creative actions — generating copy, scoring it, assembling a template — all behind a feature flag.
  • Nothing in graph traversal, claiming, or state transitions.

Deterministic

  • Claiming, advancing and state transitions.
  • All five core actions.
  • Condition evaluation.
  • Wait scheduling and the minimum-wait floor.
  • The iteration breaker.
  • Approval-node gating and timeout handling.

Human approval points

  1. Authoring and activating the graph.
  2. Any approval node the author places in the journey.
  3. Enabling the creative actions, which are flagged off by default.

Failure handling

FailureResponse
Runner dies mid-cycleThe claimed execution's lock is released and it becomes runnable again. Nothing is lost because nothing was held in memory.
A node action failsThe execution is marked failed with the node recorded, rather than silently advancing.
Graph contains a cycleThe per-execution iteration cap terminates it.
Wait misconfigured to zeroFloored to one minute, so it cannot become a busy loop.
Approval never answeredThe optional timeout rejects. Defaulting to reject rather than approve is the whole point.
Node type unrecognizedAdvances along the outgoing edge without acting. This is a real weakness — see below.

Monitoring

Runnable execution depth, executions advanced per tick, terminal state distribution, approval nodes waiting, and iteration-cap hits. The counter I would add is unrecognized-node-type encounters, since that failure is currently invisible.

More workflow designs

Back to the library