Macro module for defining workflows with callback-based pattern matching.
Add use Hephaestus.Workflow to a module to declare a workflow via
start/0 and transit/3. Static clauses ignore the context argument
with _ctx. Dynamic clauses use @targets before the clause to declare
possible destinations for DAG validation. The macro extracts the step DAG
at compile time, validates it with libgraph, cross-checks events/0
declarations, and generates helper functions for runtime coordination.
Options
:tags— a list of strings used as labels for observability and filtering (default:[]). Runner adapters can use these to tag jobs or events.:metadata— a map with string keys and JSON-safe values (strings, numbers, booleans, nil, or nested maps/lists) for custom observability data (default:%{}). Atom keys are rejected because they lose identity after JSON round-tripping in adapters like Oban.:unique— required keyword options used to build a%Hephaestus.Workflow.Unique{}for runtime uniqueness checks.:hephaestus— optional module reference for multi-instance setups that need to identify which Hephaestus facade module should coordinate the workflow.:version— a positive integer identifying this workflow definition version (default:1). Used by versioned workflow registries to route instances to the correct module.:versions— a map of%{version_integer => workflow_module}that turns the module into an umbrella dispatcher. Umbrella modules do not definestart/0ortransit/3and skip DAG validation entirely. Instead they generate dispatcher functions (__versions__/0,current_version/0,resolve_version/1, and overridableversion_for/2).:current— required when:versionsis set. The version integer thatresolve_version(nil)andcurrent_version/0resolve to.
Generated Functions
When you use Hephaestus.Workflow, the following functions are generated in your module:
__tags__/0— returns the list of tags declared via the:tagsoption (default:[]).__metadata__/0— returns the metadata map declared via the:metadataoption (default:%{}).__unique__/0— returns the validated%Hephaestus.Workflow.Unique{}declared via the required:uniqueoption.__hephaestus__/0— returns the optional module passed via the:hephaestusoption, ornilwhen not configured.__predecessors__/1— returns the set of immediate predecessor steps for a given step module as aMapSet. Used byHephaestus.Core.Engineto implement join semantics: a step is only activated when all of its predecessors have completed. Returns an emptyMapSetfor the start step or unknown modules.__graph__/0— returns the complete workflow DAG as aGraphstruct (from thelibgraphlibrary). Useful for introspection and tooling such asmix hephaestus.gen.docs.__edges__/0— returns the raw list of edge maps extracted at compile time. Each edge is a map with:from,:event,:targets, and:dynamic?keys. Used by tooling (e.g.,mix hephaestus.gen.docs) to render event-annotated workflow diagrams.__version__/0— returns the workflow version as a positive integer (default:1). Umbrella dispatcher modules instead returnnil.__versioned__?/0— returnsfalsefor standalone workflows. Version-dispatcher umbrella modules override this to returntrue.resolve_version/1— givennilor the matching version integer, returns{version, module}. RaisesArgumentErrorfor any other version.
Umbrella-only functions (when :versions is set)
__versions__/0— returns the version map passed via the:versionsoption.current_version/0— returns the version integer passed via the:currentoption.resolve_version/1— givennil, returns{current, module}. Given a version integer present in the map, returns{version, module}. RaisesArgumentErrorfor unknown versions.version_for/2— receives the version map and an opts keyword list. Returnsnilby default. The opts keyword list is forwarded fromstart_instance/3as-is, but the callback is only consulted when no explicitopts[:version]was passed. The core reserves:versionand:telemetry_metadata, so custom routing should avoid those keys. Can be overridden (defoverridable) to implement custom version selection logic.
Validation Rules
Standard workflows validate :version as a positive integer.
Umbrella workflows additionally validate that:
:versionand:versionsare not used together- every key in
:versionsis a positive integer :currentis present in:versions- every referenced version module implements
Hephaestus.Core.Workflow - every referenced version module reports the same
__version__/0as its map key - every referenced version module is nested under the umbrella module namespace
Umbrella modules are dispatchers, so they do not generate DAG helper functions like
__graph__/0, __edges__/0, or __predecessors__/1.