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.