Skip to content

Workflow runner

The workflow runner executes a declarative defineWorkflow (from @cosmicdrift/kumiko-framework/engine) with an explicit run lifecycle exposed through the outer Run-Envelope events, so a workflow run is a first-class, observable aggregate, distinct from fire-and-forget background jobs.

import { defineWorkflow } from "@cosmicdrift/kumiko-framework/engine";

Every run emits a deterministic sequence on the workflow’s own aggregate:

EventMeaning
workflow.run-starteda run began (with its workflowRunAggregateId)
workflow.run-completedthe run finished successfully
workflow.run-failedthe run failed (with error payload)

Each run lives under

import { workflowRunAggregateId } from "@cosmicdrift/kumiko-bundled-features/workflow-runner";
workflowRunAggregateId(workflowName, key); // → "<workflowName>:<key>"

so a run is addressable, re-runnable, and its events are replayable : unlike jobs, which are best-effort background work with no run lifecycle.

Wire a workflow to fire on events via registerEventTrigger:

import { registerEventTrigger } from "@cosmicdrift/kumiko-bundled-features/workflow-runner";
registerEventTrigger(r, workflow);

You can also start a run imperatively with startAndRunWorkflow({ runId, ... }).

  • Run-envelope vs jobs: use the runner when you need an observable, aggregate-addressed run (audit, retry, follow-up events). Use jobs for best-effort background tasks with no run lifecycle.
  • Workflows are built with r.step.* steps inside defineWorkflow; the runner executes those steps within the run aggregate.