Aller au contenu

Workflows overview

A workflow is a directed acyclic graph of functions, each backed by a specific, pinned FunctionVersion. The output of one node feeds the input of another through typed ports. Runtime values the user supplies are materialised as input nodes — typed nodes that sit in the graph like any other.

Workflows solve a recurring engineering need: the result that matters rarely comes out of a single function. A typical sizing problem reads like “compute the wind load on a structure, feed it into a bolt sizing, then check the resulting shear stress” — three functions chained end-to-end.

Typed connections

Every edge is validated against the canonical type catalog at draw time. You cannot wire a Force output into a Length input — the editor refuses it live.

Computed visibility

A workflow’s visibility is not declared — it is derived from the visibility of every referenced package. Public everywhere ⇒ public. Any private node ⇒ private.

Pinned versions

Each function node freezes (package_slug, function_name, package_version) when added. Updating the underlying package does not change the workflow — reproducibility is first-class (FRO-pkg-05 applied to graphs).

Fail-fast

If a node fails, every downstream node is cancelled. Independent branches that were already running finish their current execution, but no new job is submitted on them.

╭──────────╮
│ I_bolt │ (input: {d, p, As, Re_min})
╰────┬─────╯ ┌──────────┐
│ ┌───┤ Bolt ├── margin ─┐
├──────────────────────┤ └──────────┘ │ ┌───────────┐
│ │ ├────┤ Validator │─ verdict
╭────┴─────╮ │ ┌──────────┐ │ └───────────┘
│ I_loads │ └───┤ Stress ├── stress ─┘
╰──────────┘ └──────────┘

Three building blocks:

  • Function nodes — one per function call. Carry a node_key (stable identifier) and a pinned function_version_id.
  • Input nodes — typed value sources. Declare a label, a type_expr (any canonical type, including structs like {d: Length, p: Length}), whether the value is required at submission. A single input node can feed many function ports — that’s how you share the same parameter across two branches of the graph.
  • Edges — directed, typed. Connect one output port to one input port. Every input port receives exactly one incoming edge.

Duplicating a compute node does not duplicate its inputs: the duplicate can either reuse the same input node (same value in both branches) or be wired to a new one (independent values). The graph itself is the source of truth for sharing — there is no hidden rule on top of the topology.

Input nodes can emit any type from the catalog:

  • a primitive or physical scalar (Force, Length, Moment…)
  • a homogeneous list (list[Force]) or dict (dict[str, Length])
  • a struct — typically the signature of a business object like a bolt {d: Length, p: Length, As: Area, Re_min: Stress, quality_class: String}

The run form generates one field group per input node and renders struct shapes recursively.

Featurev1v1.5v2
DAG (parallel branches)
Visual editor (React Flow)
Explicit typed input nodes
Typed connections with sous-typage
Fusion of same-package steps (one cold start per chain)✅ (plan)✅ (worker)
Warm pool✅ (FRO-wkf-12)
Import / export YAML✅ (FRO-wkf-13)
Logic nodes (if / loop)✅ (FRO-wkf-15)
Meta-workflows✅ (FRO-wkf-14)

Type system

Canonical catalog, sous-typage rules, composite types.

Visual editor

Palette, drag-and-drop, live edge validation, properties panel.

Running a workflow

Run submission, tick polling, terminal outputs, failure handling.

API reference

Endpoints for CRUD, versioning, runs, and live polling via /tick.