GLIDE Runtime Technical Reference Manual

This document provides an extensive reference for how GLIDE workflows are executed at runtime. It covers execution flow, step-by-step processing, fork handling, input/output validation, durations and event timings, error handling, and more.


Table of Contents

  1. 1. Overview
  2. 2. Step Status & Execution Results
  3. 3. The WorkflowExecutor Flow
  4. 4. Linear Step Execution
  5. 5. Fork Step Execution
  6. 6. Input Processing & Validation
  7. 7. Output Validation & Known Fields
  8. 8. Error Handling
  9. 9. executeWorkflow API
  10. 10. Usage Examples
  11. 11. References

1. Overview

Once a GLIDE Workflow is parsed (see the GLIDE Parser Manual), the runtime uses a WorkflowExecutor to execute each step in the declared order:

The runtime is orchestrated by executeWorkflow(context). This function:

  1. Ensures there's a durableExecutor in the context for scheduling actions.
  2. Instantiates WorkflowExecutor and calls its execute() method.
  3. Returns a structured WorkflowExecutionResult.

2. Step Status & Execution Results

2.1 StepStatus

2.2 StepExecutionNode

Each executed step produces a node with:

2.3 BranchExecutionNode

2.4 WorkflowExecutionResult


3. The WorkflowExecutor Flow

The WorkflowExecutor orchestrates top-level step iteration:

  1. execute() records a workflowStartTime and sets status='running'.
  2. Iterate over workflow.steps in insertion order:
  3. executeStep branches depending on the step’s kind:
  4. After all top-level steps are processed, status is 'completed' if no error occurred, or 'error' otherwise.

Finally, the executor calculates wallClockTimeMs and totalIOTimeMs, returning the WorkflowExecutionResult.


4. Linear Step Execution

executeLinearStep handles a single linear step:

  1. Creates a StepExecutionNode with status='running' and records startTime.
  2. Looks up the action definition (getActionDefinition(step.uses)). If missing, STEP_DEFINITION_ERROR is thrown.
  3. Validates input and output definitions for compatibility with the action’s inputDefinition and outputDefinition (if any). If mismatched, a STEP_DEFINITION_ERROR occurs.
  4. If the step has a when expression, evaluate it (via context.gel.evaluate). If false, mark status='skipped' and finish early.
  5. Otherwise, processStepInput is called to expand input fields (render templates, enforce min/max, etc.). auth credentials might also contain references that are rendered.
  6. Call the action handler with the processed input, config, auth, and an abortSignal to allow cancellations.
  7. The handler returns an ActionResult, which may have results (output fields) and extra data. If required output fields are missing, HANDLER_ERROR is thrown. Otherwise, validateStepOutput ensures the output matches the step’s OutputSchema.
  8. Any returned fields are stored in context.state[stepId] and used to register new known references in context.gel (via contributeFields), enabling subsequent steps to do $myStep.output.someField references.
  9. Set status='completed', record endTime, durationMs. If an error is thrown at any point, status='error' is set, capturing the RuntimeError.

5. Fork Step Execution

executeForkStep handles a kind='fork' step:

  1. Build a StepExecutionNode with status='running', no uses, no startTime or endTime (since forks themselves don’t produce direct output/time). Instead, it has an array of BranchExecutionNode.
  2. For each branch:
  3. If no branch actually executes (all were when: false), the entire fork step is 'skipped'.
  4. If any branch fails, set status='error' for the fork step; otherwise 'completed'.

Branches run in parallel from a code perspective via Promise.all, but each branch’s steps are still linear in nature within that branch. Once the fork step is completed (or errored), no further steps appear at that same level (fork is terminal).


6. Input Processing & Validation

6.1 processStepInput

Each linear step defines input fields in the DSL. The runtime uses processStepInput to:

When done, processStepInput returns a fully typed object suitable for passing to the action handler. If a single field fails, the entire step is aborted with RuntimeError.


7. Output Validation & Known Fields

7.1 validateStepOutput

After an action completes, we may have results in the returned ActionResult. If the step defines an OutputSchema, the runtime checks:

If this validateStepOutput fails, a VALIDATION_ERROR arises. Otherwise, the parsed output is stored in context.state[stepId], and new references (like $stepId.output.myField) are added to the GelEngine for subsequent steps to use.

7.2 inferFieldType & generateKnownFields


8. Error Handling

The runtime uses RuntimeError for structured error reporting, which includes:

Steps that fail set their status to 'error' and store the RuntimeError. The top-level WorkflowExecutionResult will have success=false, and subsequent steps are either cancelled or not executed.


9. executeWorkflow API

executeWorkflow(context) is the primary entry point for running a fully parsed workflow:

function executeWorkflow(context: WorkflowContext): Promise<WorkflowExecutionResult>;
  1. Checks context.durableExecutor is present, else CONFIGURATION_ERROR is thrown.
  2. Ensures workflow.steps is defined. If not, throws STEP_DEFINITION_ERROR.
  3. Constructs a WorkflowExecutor with the context and calls execute().
  4. Returns the resulting WorkflowExecutionResult, containing hierarchical step data.

9.1 WorkflowContext


10. Usage Examples

10.1 Simple Workflow Execution

import { parseWorkflow } from "./parser";
import { executeWorkflow } from "./runtime";
import { createWorkflowEvent } from "./schemas/events";

// 1) Build a minimal workflow DSL
const rawWorkflow = {
  name: "GreetingsFlow",
  id: "0b84288d-a7b8-4dc6-bb67-d1154b9847c0",
  compatibility: "2025-01-30T00:00:00.000Z",
  trigger: { on: "manual" },
  steps: {
    greet: {
      kind: "linear",
      uses: "myOrg/greet@v1",
      label: "Greeting Step",
      input: {
        extendable: false,
        fields: {
          name: {
            label: "Name",
            help: "Who to greet",
            type: "string",
            required: true,
            value: "GLIDE"
          }
        }
      }
    }
  }
};

// 2) Create a 'manual' event
const event = createWorkflowEvent("manual", { data: { userId: 123 } });

// 3) Parse the workflow => get a WorkflowContext
const context = parseWorkflow(rawWorkflow, event);

// 4) Execute the workflow
executeWorkflow(context)
  .then((result) => {
    console.log("Success:", result.success);
    console.log("Execution Steps:", result.steps);
  })
  .catch((err) => {
    console.error("Runtime error:", err);
  });

10.2 Forked Steps Example

// Assume parseWorkflow gave us 'context' with a top-level fork step
executeWorkflow(context).then(result => {
  if (!result.success) {
    console.error("Workflow failed. Error:", result.error);
  } else {
    console.log("All branches completed. Steps detail:", result.steps);
  }
});

11. References

Reference Description Link
GLIDE Parser Manual Explains how workflow JSON is validated and references are extracted. Open
actions.ts Implementation details for action handlers and the actionBuilder approach. View Code
runtime.ts Source code for WorkflowExecutor, executeWorkflow, and related logic. View Code
End of GLIDE Runtime Technical Reference Manual
For additional questions, consult other GLIDE manuals or repository documentation.