All workflows

Engine capabilities

Subworkflow Reuse

A Horus showcase of the subworkflow construct. A sub block carries a complete child workflow, and a YAML anchor instantiates the same two-stage body twice under different prefixes.

horus-runtimeYAMLuv

What this workflow does

This workflow demonstrates the subworkflow construct of horus-runtime. A sub: block carries a complete child workflow. Horus inlines the child into the parent graph when the workflow runs.

There is no binding table to keep in sync. Horus derives the ports from the child itself. The in-port is the root artifact that the child reads. The out-port is the task output that nothing inside the child consumes.

The showcase uses that to demonstrate reuse. A two-stage trim -> shout cleaning pipeline is written once, as a YAML anchor. The workflow instantiates it twice, as clean_a and clean_b, through a YAML alias. Each instance runs against a different input.

The problem it solves

A real pipeline repeats the same sequence of stages on different data. A cleaning sequence, a prep sequence, or a scoring sequence appears several times.

If you copy the stages, you own several copies. A fix to one copy misses the others. If you factor the sequence into a helper script, you lose the per-stage graph. The engine sees one opaque stage, so it cannot show you where a run failed.

The subworkflow construct keeps both properties. The body is written once, and the engine still sees every inner stage. Horus inlines the inner stages at <subworkflow id>/<inner id>, so clean_a/trim and clean_b/trim never collide. The same body is reused verbatim, with no id or path conflict.

Reuse happens at the YAML parsing level. The sub: value of clean_a is tagged &clean_pipeline. The sub: value of clean_b is *clean_pipeline, a plain YAML alias. The loader sees two independent but identical sub: blocks. This needs no custom tooling.

Pipeline

split (local)              examples/quotes.txt (2 lines) ──► quote_a.txt, quote_b.txt

clean_a (subworkflow)      clean_b (subworkflow)
   │  trim -> shout            │  trim -> shout
   │  (same body, inlined      │  (same body, inlined
   │   as clean_a/trim,        │   as clean_b/trim,
   │   clean_a/shout)          │   clean_b/shout)
   ──► clean.txt               ──► clean.txt

combine (local)             clean_a/clean.txt + clean_b/clean.txt ──► results/report.txt
   │  concatenates both cleaned quotes

Inputs and outputs

Input

  • examples/quotes.txt: two lines of text.

Outputs land in horus_workflow_results/:

  • quote_a.txt and quote_b.txt: the two split lines.
  • clean_a/clean.txt and clean_b/clean.txt: each input line, trimmed and then uppercased. The folder is the inner working directory of the inlined subworkflow.
  • results/report.txt: both cleaned lines, one per line.

Run the workflow

Install uv if you do not have it:

curl -LsSf https://astral.sh/uv/install.sh | sh

Then install the horus-runtime and run the workflow:

cd workflows/engine-showcases/w04-subworkflow-reuse
uv sync
horus run workflow.yaml

You can also install the runtime with pip:

pip install horus-runtime

To use your own text, replace the two lines in examples/quotes.txt. To change the behavior of both instances at once, edit the clean_pipeline body in workflow.yaml. Both clean_a and clean_b pick up the change, because they share the one anchored body.

References

Run this workflow

The workflow is open source. Clone the pantheon repository and run it with the horus-runtime engine. To run it on managed compute without a cluster of your own, join the Temple Compute OS waitlist.