Skip to content

Workflow Engine

EcoCtrl ships with a built-in workflow engine that lets you automate business logic through a visual node graph. Workflows are defined in a JSON DSL, edited in the admin dashboard, and executed by a runtime interpreter in packages/server/src/engine/.

Overview

A workflow consists of three parts:

  1. Trigger — decides when the workflow runs.
  2. Nodes — the steps to execute, arranged as a directed graph.
  3. Edges — connections between nodes that define execution order.

The engine executes nodes sequentially while maintaining an ExecutionContext that holds variables, node outputs and environment values.

Trigger types

TypeDescriptionConfig
state_changeFires when watched data changeswatch: string[], optional condition expression
scheduleCron-based recurring executioncron: string, timezone: string
manualTriggered by POST /api/workflows/:id/trigger
webhookTriggered by POST /api/webhook with the workflow's webhook IDsecret, allowedIps
eventFires on a named internal eventevent: string, optional condition

Schedule triggers are backed by the pg-boss queue system. When a workflow is created or updated with a schedule trigger, a corresponding cron job is registered (or unregistered) automatically.

Node types

Control nodes

NodePurpose
startEntry point. Every workflow has exactly one.
endTerminal node. Stops execution.
conditionEvaluates a boolean expression (expr.ts). Follows the "true" edge if the condition is met, otherwise the "false" edge.
switchLike condition but with multiple output branches.
loopIterates over a collection, executing the connected subgraph for each item.
parallelExecutes multiple downstream branches concurrently.
delayPauses execution for a configured duration.

Action nodes

NodePurposeConfig highlights
http_requestMakes an outbound HTTP call.method, url, headers, body (supports template interpolation).
databaseRuns a SQL query against the EcoCtrl database.query, params.
emailSends an email via the configured SMTP relay.to, subject, body.
variableSets or mutates a workflow variable.name, value (supports expressions).

Error handling

Every node can declare an onError handler:

ActionBehavior
retryRe-runs the node up to retryCount times with retryDelayMs between attempts.
skipMarks the node as skipped and continues to the next connected node.
abortFails the entire workflow execution.
gotoJumps to the node identified by gotoNodeId. Useful for fallback paths.

Execution model

Trigger fires


Executor creates ExecutionContext


For each node in topological order:
    - Resolve inputs (template interpolation, variable substitution)
    - Run the node handler
    - Store output in nodeOutputs map
    - Follow the matching edge to the next node


Execution ends → persist result to workflow_executions table

The ExecutionContext contains:

  • triggerData — payload that fired the trigger
  • variables — mutable Map of user-defined variables
  • nodeOutputs — Map of each node's output record
  • env — process environment variables

Admin UI

The admin dashboard provides a visual workflow editor at WorkflowCanvas.tsx (powered by @xyflow/react). Users can:

  • Drag nodes from a palette onto the canvas.
  • Connect nodes with edges.
  • Configure each node's properties in a side panel.
  • Test-run workflows directly from the editor.

Workflow definitions are auto-saved to the workflows table as the JSON DSL.

API

MethodPathDescription
GET/api/workflowsList workflows
POST/api/workflowsCreate workflow
GET/api/workflows/:idGet workflow DSL
PUT/api/workflows/:idUpdate workflow
DELETE/api/workflows/:idDelete workflow
POST/api/workflows/:id/triggerManual execution
GET/api/workflows/:id/executionsExecution history
POST/api/webhook/:slugWebhook trigger (public)

Adding a custom node

  1. Add the node type to NodeType in engine/types.ts.
  2. Implement the handler in executor.ts.
  3. Add the UI component in the admin workflow editor palette.
  4. Update the validator to accept the new node's config schema.

Released under the MIT License.