This page define the format of the JSON file used to describe a workflow in MetroFlow. The file describes a set of nodes (steps), the edges (connections between steps), and optional subworkflows (groups of steps).
The JSON file must be a dictionnary with the following top-level keys:
| Key | Type | Required | Description |
|---|---|---|---|
nodes | Array | Required | List of all steps in the workflow. |
edges | Array | Required | List of connections between steps. |
subworkflows | Dictionnary | Optional | Named groups of nodes for visual organisation. |
Each entry in the nodes array represents a single step in the workflow.
| Field | Type | Required | Description |
|---|---|---|---|
id | String | Required | Unique identifier for the node. Used to reference it in edges and subworkflows. |
name | String | Required | Display name of the step. |
position | Dictionnary | Required | Visual position on the canvas. Must contain x and y as string numbers. |
code | String | Optional | The process code associated with this step. |
file_ref | String | Optional | Path to the source file for this step, e.g. (modules/step1.nf). |
Node IDs follow a hierarchical naming convention using . as a separator between the subworkflow it is conatined in and the node name:
SUBWORKFLOW.nodeName
If the node belongs to multiple subworkflows, the subworkflow names are included:
SUBWORKFLOW1.SUBWORKFLOW2.nodeName
Each entry in the edges array defines a directed connection from one node to another.
| Field | Type | Required | Description |
|---|---|---|---|
id | String | Required | Unique identifier for the edge, typically A -> B. |
A | String | Required | ID of the source node. |
B | String | Required | ID of the destination node. |
color | String | Optional | Hex color code for the edge line, e.g. #4E79A7. |
condition | String | Optional | Condition under which the source node is executed and the path is taken, e.g. params.runStep1 == true. |
Subworkflows are optional and allow you to visually group nodes together. The subworkflows key is an dictionnary where each key is a subworkflow ID.
| Field | Type | Required | Description |
|---|---|---|---|
nodes | Array of strings | Required | List of node IDs that belong to this group. |
label | String | Required | Display name for the group. |
color | String | Optional | Background color of the group on the canvas, e.g. #eefde6. |
The following is a simple 3-step workflow: load data → process data → export results.
{
"nodes": [
{
"id": "MY_SUBWORKFLOW.loadData",
"name": "loadData",
"position": { "x": "100", "y": "150" },
"code": "process loadData {\n output:\n path \"data.csv\"\n script:\n \"\"\"\n cp /source/data.csv data.csv\n \"\"\"\n}",
"file_ref": "(modules/loadData.nf)"
},
{
"id": "MY_SUBWORKFLOW.processData",
"name": "processData",
"position": { "x": "300", "y": "150" },
"code": "process processData {\n input:\n path data\n output:\n path \"processed.csv\"\n script:\n \"\"\"\n python process.py ${data}\n \"\"\"\n}",
"file_ref": "(modules/processData.nf)"
},
{
"id": "MY_SUBWORKFLOW.exportResults",
"name": "exportResults",
"position": { "x": "500", "y": "150" },
"code": "process exportResults {\n input:\n path processed\n output:\n path \"results.zip\"\n script:\n \"\"\"\n zip results.zip ${processed}\n \"\"\"\n}",
"file_ref": "(modules/exportResults.nf)"
}
],
"edges": [
{
"id": "MY_SUBWORKFLOW.loadData -> MY_SUBWORKFLOW.processData",
"A": "MY_SUBWORKFLOW.loadData",
"B": "MY_SUBWORKFLOW.processData",
"color": "#4E79A7",
"condition": "params.loadData == true"
},
{
"id": "MY_SUBWORKFLOW.processData -> MY_SUBWORKFLOW.exportResults",
"A": "MY_SUBWORKFLOW.processData",
"B": "MY_SUBWORKFLOW.exportResults",
"color": "#76B7B2",
"condition": "params.processData == true"
}
],
"subworkflows": {
"MY_SUBWORKFLOW": {
"nodes": [
"MY_SUBWORKFLOW.loadData",
"MY_SUBWORKFLOW.processData",
"MY_SUBWORKFLOW.exportResults"
],
"label": "MY_SUBWORKFLOW",
"color": "#fefefa"
}
}
}