Skip to main content
Unlisted page
This page is unlisted. Search engines will not index it, and only users having a direct link can access it.

ADR-004: Workflow Engine Inline vs Dispatch Step Types

  • Status: Accepted
  • Date: 2026-02-01

Context​

The workflow engine supports multiple step types. Some are pure data operations (conditions, transforms, delays) while others require external execution (jobs, sub-workflows). Running all steps through the job dispatch pipeline adds unnecessary latency and complexity for steps that can be resolved locally.

Decision​

Split step types into two categories:

Inline Steps (executed synchronously in the engine)​

Step TypeBehavior
conditionEvaluate expression, choose branch
delaySchedule timer, mark pending
approvalCreate approval request, wait for human
notifyFire notification event
transformEvaluate template expressions against run context
storageRead/write workflow context paths
switchMulti-branch condition evaluation

These execute within the engine's scan loop — no job dispatch, no worker involvement. Results are written directly to the run's step state in Redis.

Dispatch Steps (require external execution)​

Generic step types have no dedicated engine handler — they are dispatched as jobs to worker pools:

Step TypeBehavior
workerSubmit to scheduler for worker dispatch (default job type)
llmDispatch to an LLM worker
httpDispatch an HTTP-call job
containerDispatch a containerized job
scriptDispatch a script-execution job
inputDispatch a job that collects input

These create jobs that execute outside the engine process.

parallel, loop, switch, and subworkflow have dedicated engine handlers (see the inline/handler list above and core/workflow/models.go): they are orchestrated by the engine, which in turn dispatches the underlying worker/generic jobs.

Expression Syntax​

Inline steps use ${ expression } template syntax (not {{ }}). The evalTemplates function recursively evaluates expressions against the run's context scope, resolving input.*, steps.<id>.output.*, and context.* references.

Key source files:

  • core/workflow/engine.go — step handler dispatch and inline execution
  • core/workflow/models.go — StepType constants
  • docs/workflow-step-types.md — user-facing step type reference

Consequences​

Positive:

  • Inline steps complete in microseconds (no network round-trip)
  • Simpler error handling — no job state machine for data transforms
  • Workflow engine can process data-only workflows without scheduler involvement
  • Reduces load on scheduler and NATS for internal operations

Tradeoffs:

  • Engine scan loop must handle inline step failures without blocking
  • Two execution models to understand and debug
  • Inline steps cannot leverage worker pool scaling