Understanding Workflow Definitions Syntax

In Roboflow Workflows, the Workflow Definition is the internal "programming language". It provides a structured way to define how different blocks interact, specifying the necessary inputs, outputs, and configurations. By using this syntax, users can create workflows without UI.

Let's start from examining a Workflow Definition and analyse it step by step.

Version Marker

Every Workflow Definition begins with the version parameter, which specifies the compatible version of the Workflows Execution Engine. Roboflow utilizes Semantic Versioning to manage these versions and maintains one version from each major release to ensure backward compatibility. This means that a workflow defined for Execution Engine version 1.0.0 will function with version 1.3.4 and other newer versions, but workflows created for more recent versions may not be compatible with earlier ones.

List of Execution Engine versions loaded on the Roboflow Hosted platform is available here.

Inputs

A workflow specifies inputs as placeholders that can be filled with data while running the workflow.

[
    {
      "type": "WorkflowImage", "name": "image"
    },
    {
      "type": "WorkflowParameter", "name": "model", "default_value": "rfdetr-small"
    }
]

The first placeholder is named image and is of type WorkflowImage. This special input type is batch-oriented, meaning it can accept one or more images at runtime to be processed as a single batch. You can add multiple inputs of the type WorkflowImage, and it is expected that the data provided to these placeholders will contain the same number of elements. The only exception is when you submit a single image; it will be broadcast to fit the batch size requirements of other inputs.

The second placeholder is a straightforward WorkflowParameter called model. This type of input allows users to inject hyperparameters — such as model variants, confidence thresholds, and reference values — at runtime. The value is not expected to be a batch of elements, so when you provide a list, it will be interpreted as a list of elements, rather than a batch of elements each to be processed individually.

More details about the nature of batch-oriented data processing in workflows can be found in the workflow execution guide.

Generic Batch-Oriented Inputs

Since Execution Engine v1.3.0 (inference release v0.27.0), Workflows support batch-oriented inputs of any kind and dimensionality. These inputs are not enforced for now, but we expect that as the ecosystem grows, they will be more and more useful.

If you wanted to replace the WorkflowImage input with a generic batch-oriented input, use the following construction:

{
  "inputs": [
    {
      "type": "WorkflowBatchInput",
      "name": "image",
      "kind": ["image"]
    }
  ]
}

Additionally, if your image is supposed to sit at a higher dimensionality level, add the dimensionality property:

{
  "inputs": [
    {
      "type": "WorkflowBatchInput",
      "name": "image",
      "kind": ["image"],
      "dimensionality": 2
    }
  ]
}

This will alter the expected format of image data in the Workflow run — dimensionality=2 enforces image to be a nested batch of images (a list of lists of images).

Steps

Steps are instances of Workflow blocks connected with inputs and outputs of other steps to dictate how data flows through the workflow. Here is an example step definition:

{
  "type": "roboflow_core/roboflow_object_detection_model@v1",
  "name": "model",
  "images": "$inputs.image",
  "model_id": "$inputs.model"
}

Two common properties for each step are type and name. Type tells which block to load and name gives the step a unique identifier, based on which other steps may refer to its output.

Two remaining properties declare selectors (this is how we call references in Workflows) to inputs — image and model. While running the workflow, data passed into those placeholders will be provided for the block to process.

Input data bindings of blocks (like images property) can be filled with selectors to batch-oriented inputs and step outputs. Configuration properties of blocks (like model_id) usually can be filled with either values hardcoded in the workflow definition (they cannot be altered in runtime) or selectors to inputs of type WorkflowParameter.

Let's see how step outputs are referred as inputs of another step:

{
  "type": "roboflow_core/dynamic_crop@v1",
  "name": "dynamic_crop",
  "images": "$inputs.image",
  "predictions": "$steps.model.predictions"
}

In this case, predictions property defines output of step named model. Construction of the selector is: $steps.{step_name}.{step_output_name}. Thanks to this reference, the model step is connected with dynamic_crop and at runtime model predictions will be passed into dynamic crop as a reference for image cropping.

Outputs

This section of Workflow Definition specifies how the response from workflow execution looks. Definitions of each response field look like this:

{
  "type": "JsonField",
  "name": "detections",
  "selector": "$steps.detections_classes_replacement.predictions"
}

The selector can reference either an input or a step output. Additionally, you can specify the "coordinates_system" property, which accepts two values: "own" or "parent". This property is relevant for outputs that provide model detections and determines the coordinate system used for the detections. To ensure these coordinates are not translated back to the parent coordinate system, set "coordinates_system": "own" (parent is the default option).

Additionally, output selectors support wildcards ($steps.step_name.*) to grab all outputs of a specific step.

To fully understand how output structure is created, read about data processing in Workflows.