Skip to main content

Workflows

Table of Contents

  1. Overview
  2. Key Concepts
  3. Workflow Lifecycle
  4. Node Types
  1. Edge Types
  2. Context & Variable System
  3. Error Handling
  4. Execution Modes
  5. Real-Time Monitoring
  6. Workflow Triggers
  7. Best Practices

Overview

The Jet Admin Workflow Engine is a visual, DAG-based (Directed Acyclic Graph) automation platform that allows you to build, test, and deploy multi-step business processes without writing backend infrastructure code.

image-20260619-065118.png

Workflows are built by connecting nodes on a canvas. Each node represents a discrete unit of work — querying a database, running a script, branching on a condition, collecting input from a user, or pausing for a set duration. Nodes pass data to one another through a shared execution context, which acts as the workflow's live memory throughout a run.

Workflows can be triggered manually, via API, or linked directly to UI widgets inside Jet Admin apps.


Key Concepts

Nodes

Nodes are the building blocks of a workflow. Each node has a specific type that determines what it does. Nodes are visually represented as cards on the workflow canvas and are connected by edges.

Edges

Edges are the directional connections between nodes. They represent the flow of execution from one node to the next. Edges connect to specific handles on each node (for example, success, error, loop, completed), allowing you to route execution along different paths depending on the outcome of a node.

Execution Context (ctx)

The execution context is a shared key-value store that persists for the lifetime of a single workflow run. Every node reads from and writes to this context. When a node completes, its output is stored in the context under a name you define (the Output Variable). Subsequent nodes can reference that data using template expressions like {{ctx.outputVariableName}}.

The context always includes ctx.input, which holds the input parameters passed when the workflow was triggered.

Template Expressions

Data is referenced between nodes using double-curly-brace ({{ }}) template syntax. These expressions are resolved at runtime against the current execution context.

ExpressionDescription
{{ctx.input.userId}}A workflow input parameter named userId
{{ctx.queryResult}}The output of a node whose Output Variable is queryResult
{{ctx.queryResult[0].name}}The name field of the first row returned by a query node
{{ctx.item}}The current item in a Loop node's iteration
{{ctx.item.email}}A field on the current loop item

You can also use template expressions for string interpolation: "Order ID: {{ctx.input.orderId}}" will produce a string like "Order ID: 4821".

Output Variables

Every node that produces data has an Output Variable field. This is the key under which the node's result will be stored in the execution context. Output variable names must be unique across all nodes in a workflow and must start with a letter or underscore (e.g., queryResult, userData, isApproved).

Workflow Instances

Each time a workflow is executed, a new instance is created. Instances track the execution status (RUNNING, COMPLETED, FAILED), all node execution logs, and the full execution context. Instances are uniquely identified by an Instance ID.


Workflow Lifecycle

A workflow run follows this general sequence:

  1. Trigger — The workflow is initiated (manually, via API, or from a widget).
  2. Start Node Executes — The entry point node fires, placing input parameters into the context.
  3. DAG Traversal — The engine evaluates which nodes are ready to execute based on which upstream nodes have completed, then dispatches them to a processing queue.
  4. Node Execution — Each node runs, reads from the context, performs its work, and writes its output back to the context.
  5. Edge Routing — Based on the node's outcome (e.g., success vs. error), the engine follows the appropriate outgoing edge to determine the next node(s).
  6. Termination — Execution ends when an End Node is reached, completing or failing the instance.

Parallel Execution & Join Behaviour

When a node has multiple outgoing edges (a fan-out), downstream nodes can execute in parallel. When a node has multiple incoming edges (a join), you can configure whether it waits for all upstream nodes to complete before running (Wait for All), or whether it fires as soon as any one upstream node completes (Trigger on Any). This is set per-node in the Advanced Settings panel.


Node Types

Start Node

Purpose: The mandatory entry point of every workflow. There can only be one Start Node per workflow.

The Start Node receives the workflow's input parameters and makes them available throughout the rest of the workflow via {{ctx.input.*}}. It does not execute any business logic itself — it simply marks the beginning of the run and passes control to the first connected node.

Configuration:

FieldDescription
TitleThe display name for the node on the canvas
DescriptionAn optional note documenting the workflow's purpose

Input Parameters are not configured on the Start Node itself — they are defined in the Input Parameters panel on the left sidebar of the Workflow Editor. Each parameter has a name (key), a data type, a required flag, and an optional default value.

Supported parameter types: string, number, boolean, object, array.

Output handle: output — connects to the first node in the workflow.

Accessing inputs in subsequent nodes:

{{ctx.input.parameterName}}
{{ctx.input.userId}}
{{ctx.input.email}}


Data Query Node

Purpose: Executes a saved Data Query against a configured datasource (e.g., PostgreSQL, REST API). The result is stored in the execution context for use by later nodes.

This node references an existing query that has been defined and saved elsewhere in Jet Admin. Input values for the query's parameters are provided at the node level, using template expressions to bind them to the live context.

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
Data QueryThe saved query to execute, selected from a searchable dropdown
InputsMapped values for each of the query's input parameters
Output VariableThe context key where the query result will be stored
Timeout (seconds)Maximum time the query is allowed to run (default: 300, max: 3600)
Retry AttemptsHow many times to retry on failure (0–10)
Retry Delay (seconds)Wait time between retries (1–300)
Error BehaviourWhat to do if the node fails (see Error Handling)
Skip this nodeIf enabled, the node is bypassed entirely during execution

Input binding examples:

ExpressionDescription
{{ctx.input.userId}}Pass a workflow input directly to the query
{{ctx.fetchUser.id}}Pass a field from a previous node's output
Order-{{ctx.input.id}}String interpolation

Output handles: success, error

Accessing results:

{{ctx.outputVariableName}} — the full result set
{{ctx.outputVariableName[0].name}} — first row, name column


JavaScript Node

Purpose: Executes custom JavaScript logic inside a secure sandbox. Use this node for data transformation, computation, validation, or any logic that cannot be expressed with the other node types.

The code runs in an isolated environment. It has access to the full execution context via the ctx variable and can use a safe subset of JavaScript globals (JSON, Math, Date, Array, Object, String, Number, Boolean, parseInt, parseFloat). Network access, filesystem access, and external libraries are not available.

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
JavaScript CodeThe code to execute. Must use return to produce an output value
Output VariableThe context key where the returned value will be stored
Timeout (seconds)Execution time limit (default: 30, max: 300)
Retry AttemptsRetries on failure (0–10)
Retry Delay (seconds)Wait between retries (1–300)
Error BehaviourBehaviour on failure (see Error Handling)
Skip this nodeBypass this node during execution

Accessing context in code:

// Workflow input parameters
ctx.input.paramName

// Output from a previous node
ctx.queryResult
ctx.queryResult[0].name

// Current loop item (when inside a Loop node)
ctx.item
ctx.item.email

Code must use return to produce a value:

// Transform data
const user = ctx.fetchUser[0];
return {
fullName: user.first_name + " " + user.last_name,
isVerified: user.status === "active"
};

// Conditional logic
const order = ctx.orderData[0];
if (order.total > 10000) {
return { requiresApproval: true, level: "director" };
}
return { requiresApproval: false };

// Data aggregation
const orders = ctx.allOrders;
const total = orders.reduce((sum, o) => sum + o.amount, 0);
return {
count: orders.length,
total: total,
average: total / orders.length
};

Output handles: success, error


Condition Node

Purpose: Branches the workflow along different paths based on evaluated conditions. It is the primary decision-making node in Jet Admin workflows.

The Condition Node evaluates one or more branches in order from top to bottom. The first branch whose conditions are satisfied determines the outgoing path. If no branch matches, execution follows the else path.

Each branch has a label (which becomes the name of the outgoing edge handle), a condition logic setting (AND or OR), and one or more individual conditions.

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
BranchesThe list of conditional branches, evaluated in order
On ErrorBehaviour if evaluation itself fails

Branch structure:

Each branch contains:

  • Label — The name for this path (e.g., "VIP Customer", "Approved", "High Risk"). This becomes the handle name on the canvas.
  • Condition LogicAND (all conditions must be true) or OR (any condition must be true).
  • Conditions — One or more condition rows.

Condition operators:

OperatorDescriptionExample
EqualsLeft value equals right value{{ctx.status}} equals active
Not EqualsLeft value does not equal right value{{ctx.role}} not equals guest
ContainsLeft value contains the right value as a substring{{ctx.email}} contains @company.com
Doesn't ContainLeft value does not contain the right value{{ctx.tags}} doesn't contain blocked
Starts WithLeft value begins with the right value{{ctx.code}} starts with ORD-
Ends WithLeft value ends with the right value{{ctx.filename}} ends with .pdf
Greater ThanLeft numeric value is greater than right{{ctx.amount}} greater than 1000
Less ThanLeft numeric value is less than right{{ctx.score}} less than 50
≥ Or EqualGreater than or equal to{{ctx.age}}18
≤ Or EqualLess than or equal to{{ctx.retries}}3
Is EmptyValue is null, undefined, or empty string/array{{ctx.approvalComment}} is empty
Is Not EmptyValue has a non-empty value{{ctx.attachments}} is not empty
Matches RegexLeft value matches a regular expression pattern{{ctx.email}} matches ^[^\s@]+@[^\s@]+\.[^\s@]+$
JS ExpressionA raw JavaScript expression (returns true or false)ctx.score > 80 && ctx.tier === 'gold'

Note on JS Expression: Unlike other operators, JS Expression uses ctx.variable syntax directly (without {{ }}), as it runs as raw JavaScript code.

Output handles: One handle per branch (named after the branch label) + else (default path) + error.

Evaluation order: Branches are evaluated top to bottom. The first matching branch is taken. Remaining branches are not evaluated.


Loop Node

Purpose: Iterates over an array, executing the downstream nodes once for each item. Use this when you need to perform the same operation on multiple records — for example, sending a notification to each user in a list, or processing each row returned by a query.

The Loop Node emits one item at a time. For each item, it follows the loop handle to the body of the loop. After all items have been processed, it follows the completed handle to continue the rest of the workflow.

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
Source ArrayTemplate expression resolving to the array to iterate over (e.g., {{ctx.userList}})
Item Variable NameThe context key for the current item (default: item, accessible as ctx.item)
Index Variable NameThe context key for the current index (default: index, accessible as ctx.index)
Max IterationsSafety cap on iterations to prevent runaway loops (default: 1000, max: 100,000)
Delay Between Items (ms)Optional pause between each iteration (0–60,000 ms)
Error BehaviourWhat to do if a node in the loop body fails
Skip this nodeBypass the loop entirely

Accessing loop variables inside the loop body:

{{ctx.item}} — the current array element
{{ctx.item.email}} — a field on the current element
{{ctx.index}} — the current 0-based iteration index (0, 1, 2, …)

Output handles: loop (executes for each item), completed (executes after all items are done), error.

Loop body design pattern:

Loop Node ──(loop)──→ [Node A] ──→ [Node B] ──→ (back to Loop Node)
└─(completed)──→ [Next Step]

Important: The last node in the loop body must connect back to the Loop Node to allow it to advance to the next item. When the Loop Node detects all items have been processed, it automatically exits via the completed handle.


Delay Node

Purpose: Pauses workflow execution for a specified duration before continuing. Use this for rate limiting, scheduled follow-ups, polling patterns, or simply adding a gap between steps.

The Delay Node is non-blocking — it does not hold a process thread open. Instead, it schedules the next step to be queued after the delay period, which means large delays (even hours) are handled efficiently.

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
Delay TypeFixed Duration, From Variable, or Until Time
Skip this nodeBypass the delay

Delay type options:

Fixed Duration — Specify an exact wait period using minutes, seconds, and milliseconds. These values are additive.

Sub-fieldRangeDescription
Minutes0–1440Number of full minutes to wait
Seconds0–59Additional seconds
Milliseconds0–999Additional milliseconds

From Variable — The delay duration (in milliseconds) is resolved from the execution context at runtime. The referenced variable must resolve to a numeric millisecond value.

{{ctx.calculatedDelay}}
{{ctx.input.waitMs}}

Until Time — Waits until a specific ISO 8601 datetime string. If the time is already in the past when the node executes, it proceeds immediately.

2025-01-31T09:00:00Z
{{ctx.scheduledTime}}

Maximum delay: 24 hours.

Output handles: output (after the delay completes), error.


Data Collection Node

Purpose: Suspends the workflow and waits for a human to provide data through a form before the workflow can continue. This enables human-in-the-loop automation patterns — for example, requiring a manager to approve an order, asking an analyst to fill in a missing value, or prompting a user to confirm an action.

When this node executes, the workflow pauses. A form modal appears in the Jet Admin interface for the relevant user. The workflow only resumes once the user submits the form.

If the collection request is not fulfilled within the configured expiry period, the request expires and the workflow remains suspended until addressed or administratively resolved.

Configuration:

FieldDescription
Modal TitleThe heading shown on the form modal (e.g., "Approval Required")
InstructionsExplanatory text shown to the user inside the modal
Collection MethodCurrently UI Form — the form is rendered inside Jet Admin
Form FieldsThe list of fields the user must fill in
Output VariableThe context key where the submitted data will be stored (default: collectedData)
Expiry (minutes)How long before the request expires (0 = never expires)

Form field configuration:

Each field in the form has the following properties:

PropertyDescription
KeyThe field's identifier in the submitted data (e.g., approvalComment)
LabelThe display label shown to the user (e.g., "Approval Comment")
TypeThe field type: Text, Long text, Number, Checkbox, or Dropdown
PlaceholderOptional hint text shown inside the field
RequiredWhether the user must fill in this field before submitting
OptionsFor Dropdown type: comma-separated list of options

Accessing submitted data in subsequent nodes:

{{ctx.collectedData}} — the full submitted object
{{ctx.collectedData.approvalComment}} — a specific field
{{ctx.collectedData.approved}} — a boolean checkbox field

Output handles: output (after successful submission), error.

Workflow behaviour during suspension:

  • The workflow instance remains in RUNNING status while waiting.
  • The user sees an "Input Required" indicator in the workflow execution panel.
  • Submitting the form resumes the workflow automatically.
  • If the user closes the modal without submitting, they can reopen it from the "Input Required" button that appears in the execution panel.
  • The Data Collection Node supports idempotent re-delivery — if the system sends the form prompt more than once (e.g., due to a page refresh), the same request is reused rather than creating a duplicate.

End Node

Purpose: Terminates the workflow run and optionally maps node outputs to named workflow-level outputs. Every workflow must have at least one End Node. You can have multiple End Nodes for different completion paths (e.g., one for success, one for a failure branch).

Configuration:

FieldDescription
TitleDisplay name for the node
DescriptionOptional documentation
Completion StatusSuccess, Failure, or Cancelled — records the intended outcome
Output ParametersNamed outputs that will be returned by the workflow when it completes

Output Parameters:

Each output parameter maps a name to a source value from the execution context:

PropertyDescription
NameThe key for this output (e.g., createdUserId, totalRevenue)
Source VariableA template expression resolving to the value (e.g., {{ctx.createUser[0].id}})
DescriptionOptional note on what this output represents

No output handles — the End Node is terminal.


Edge Types

Edges connect nodes and define the flow of execution. Each edge connects from a source handle on one node to the target handle on the next. The handle determines which execution outcome triggers that path.

Visual Edge Styles

The edge style is a cosmetic preference and does not affect execution. Available styles:

StyleDescription
Bezier (Curved)Smooth curved lines (default)
StraightDirect straight lines between nodes
Step (Sharp)Right-angled lines with sharp corners
Smooth StepRight-angled lines with rounded corners
Simple BezierA simpler curved variant

Error Edges

Any connection from an error handle is displayed in red regardless of the visual style setting, to visually distinguish error paths from normal execution paths.

Edge Labels

Edges can be given labels by clicking on the edge label area on the canvas. Labels are cosmetic — they document the intent of a connection but do not affect routing.

Standard Source Handles by Node Type

NodeHandleDescription
StartoutputConnects to the first step in the workflow
Data QuerysuccessQuery executed successfully
Data QueryerrorQuery failed
JavaScriptsuccessScript executed and returned a value
JavaScripterrorScript threw an error
Condition(branch label)One handle per defined branch (named by label)
ConditionelseNo branch conditions were matched
ConditionerrorCondition evaluation itself failed
LooploopFires for each item in the array
LoopcompletedFires after all items have been processed
LooperrorLoop encountered an error
DelayoutputFires after the delay period has elapsed
DelayerrorDelay configuration was invalid
Data CollectionoutputUser submitted the form
Data CollectionerrorAn error occurred creating or managing the request
End(none)Terminal node — no outgoing handles

Context & Variable System

How Context Works

The execution context (ctx) is a flat key-value store that accumulates data as the workflow runs. Each time a node completes successfully, its output is merged into the context under its configured Output Variable name. Later nodes can reference any previously stored value.

The context is assembled from the workflow's full execution log in chronological order. If two nodes write to the same key, the later write wins.

Reserved Context Keys

KeyDescription
ctx.inputThe workflow's input parameters, provided at trigger time
ctx.itemThe current loop item (set by a Loop Node during iteration)
ctx.indexThe current loop index (set by a Loop Node during iteration)

Naming Rules for Output Variables

  • Must start with a letter or underscore: a–z, A–Z, _
  • May contain letters, digits, and underscores: a–z, A–Z, 0–9, _
  • Must be unique across all nodes in the workflow
  • Examples of valid names: queryResult, userData, isApproved, _tempValue, step2Output
  • Examples of invalid names: query result (spaces), 2ndResult (starts with digit), query-result (hyphen)

Template Expression Reference

SyntaxResult
{{ctx.variableName}}The full value of variableName in the context
{{ctx.variableName[0]}}The first element of an array result
{{ctx.variableName[0].fieldName}}A specific field from the first row
{{ctx.input.paramName}}An input parameter provided at trigger time
prefix-{{ctx.input.id}}String interpolation — combines literal text with a context value

Error Handling

Each node (except Start and End) can be configured with an Error Behaviour setting that determines what happens if that node fails.

OptionDescriptionWhen to Use
Fail WorkflowStop execution immediately and mark the workflow as FAILEDCritical operations where failure means the whole process must stop
ContinueIgnore the error and proceed via the error handle; the node's output will be nullNon-critical steps where failure is expected and can be handled downstream
Retry, then ContinueRetry the node up to the configured number of times, then continue via the error handle if still failingFlaky external services or network calls
Retry, then FailRetry the node, then fail the whole workflow if it still failsImportant but potentially transient failures

Retry Behaviour

When retries are configured, the engine applies exponential backoff between attempts:

AttemptWait Before Retrying
1st retryConfigured Retry Delay (e.g., 5 seconds)
2nd retry2× Retry Delay (e.g., 10 seconds)
3rd retry4× Retry Delay (e.g., 20 seconds)

Error Edges

To handle errors gracefully rather than failing silently, connect a node's error handle to a downstream node (such as a notification step, a logging query, or another End Node with a Failure status). This lets you build explicit error recovery paths directly in the workflow graph.


Execution Modes

Test Run

A Test Run executes the workflow in-memory using the nodes and edges as currently drawn on the canvas, without saving the workflow first. This is ideal for iterative development and debugging.

During a Test Run:

  • You can provide custom input parameter values before the run starts.
  • The Console panel shows a real-time log of every node as it starts and completes.
  • The Context panel shows the live execution context, updating as each node completes.
  • Node cards on the canvas update visually to reflect their current status (running, completed, failed).
  • The test instance is automatically cleaned up from the system when you click Stop or Clear.

Production Run

A Production Run executes a saved workflow. It is triggered via the workflow list, via API, or via a linked UI widget. Production runs are persisted in the database and their logs and context are retained for audit and debugging.


Real-Time Monitoring

The Workflow Editor provides two monitoring panels that are visible during and after execution:

Console Panel

The Console shows a timestamped log of all execution events in chronological order. Each entry includes the event type, the node name, and a brief message. For completed nodes, the output data is shown inline. For failed nodes, the error message is displayed.

Log entry types: Run Started, Node Started, Node Completed, Node Failed, Workflow Complete, Workflow Failed, Connected, Stopped, Timeout.

Context Panel

The Context Panel shows the full execution context as a live JSON view. It updates automatically as each node completes, so you can see exactly what data is available to downstream nodes at any point in the run.

The context display truncates very large arrays and strings by default (togglable) to prevent browser performance issues when working with large result sets.

Node Status Indicators

Each node card on the canvas shows a visual badge in its top-right corner during execution:

IndicatorMeaning
Spinning icon (blue, pulsing)Node is currently executing
Green checkmarkNode completed successfully
Red XNode failed
Amber pulsing borderNode is suspended, waiting for user input (Data Collection Node)

Workflow Triggers

A workflow can be initiated in the following ways:

Trigger MethodDescription
Manual (Test Run)Click "Test Run" in the Workflow Editor. Prompts for input parameters if any are defined.
Manual (Production)Click "Run" from the workflow list or detail view.
APIMake a POST request to the workflow's execution endpoint with input values in the request body.
WidgetLink the workflow to a Jet Admin widget (e.g., a button). The widget triggers the workflow when the user interacts with it.
Sub-workflowA workflow can be called from another workflow (composability).

Best Practices

Workflow Design

  • One responsibility per node. Nodes should do one thing clearly. Avoid combining multiple concerns into a single JavaScript node when separate Data Query and condition nodes would be clearer.
  • Name your output variables descriptively. Prefer customerData over result1, and isOrderApproved over flag.
  • Add titles and descriptions to every node. This makes the canvas readable and helps collaborators understand the intent without reading configuration details.
  • Use the Condition Node's else path. Always connect the else handle of a Condition Node to handle cases where no branch matches — even if it leads to an End Node with a Failure status.
  • Connect all error handles on critical paths. Don't leave error handles dangling. Route them to meaningful recovery logic or a dedicated failure End Node.

Performance

  • Paginate large result sets. If a Data Query might return thousands of rows, add pagination to the query rather than loading all rows and processing them in JavaScript.
  • Use Delay Between Items in Loop Nodes when iterating over external API calls to avoid hitting rate limits.
  • Set appropriate timeouts. The default timeout for Data Query nodes is 5 minutes and for JavaScript nodes is 30 seconds. Adjust these to match the expected runtime of your specific operations.

Testing

  • Test with representative data. When using Test Run, provide input values that reflect real-world scenarios, including edge cases.
  • Check the Context Panel after each node completes to verify the output shape matches what you expect before building downstream nodes.
  • Test error paths explicitly. Configure test inputs that will intentionally cause a node to fail, and verify that your error handling routes execution correctly.

Data Collection (Human-in-the-Loop)

  • Set a reasonable expiry. Requests without an expiry can leave a workflow suspended indefinitely. Choose an expiry that reflects your process SLAs.
  • Write clear instructions. The instructions field in the modal is the only guidance the user has. Be explicit about what is needed and why.
  • Handle the expiry case. If a Data Collection request expires, the workflow remains suspended. Consider building a separate monitoring process or alerting mechanism for overdue requests.

This document covers the Jet Admin Workflow Engine as of the current platform version. For API endpoint reference, datasource configuration, and RBAC permissions related to workflows, refer to the respective sections of the Jet Admin technical documentation.