Skip to main content
Workflows link multiple tasks together. They are written as Python functions decorated with @workflow, but it is important to understand how they differ from tasks.

Tasks

Execute at run time — on a Kubernetes pod, in a query engine, or on a hosted service.

Workflows

Execute at registration time — the workflow body builds the DAG. No computation happens inside a workflow.
Registration involves uploading the serialized code to the Flyte backend so the workflow can be triggered.

Define a workflow

Import task and workflow from flytekit, define your tasks, then compose them in a workflow function:
workflow.py
from flytekit import task, workflow


@task
def slope(x: list[int], y: list[int]) -> float:
    n = len(x)
    sum_xy = sum(xi * yi for xi, yi in zip(x, y))
    sum_x = sum(x)
    sum_y = sum(y)
    sum_x2 = sum(xi ** 2 for xi in x)
    return (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)


@task
def intercept(x: list[int], y: list[int], slope: float) -> float:
    mean_x = sum(x) / len(x)
    mean_y = sum(y) / len(y)
    return mean_y - slope * mean_x


@workflow
def simple_wf(x: list[int], y: list[int]) -> float:
    slope_val = slope(x=x, y=y)
    intercept_val = intercept(x=x, y=y, slope=slope_val)
    return intercept_val
The output of slope is passed directly as an input to intercept, establishing a dependency between the two tasks.

How workflows work

The @workflow decorator wraps task calls in lazily evaluated promises. When the workflow body runs at registration time:
  • Each task call returns a Promise object — not the actual output value.
  • Promises can be passed to downstream tasks as inputs.
  • Promises cannot be inspected or manipulated inside the workflow body.
  • Actual values are only available when the workflow executes.
Because workflow inputs are also promises, you can only pass them directly into tasks or other workflows — you cannot branch on them with if/else logic. Use dynamic workflows for conditional logic over materialized inputs.

Run a workflow

Call a workflow like a regular Python function for local execution:
if __name__ == "__main__":
    result = simple_wf(x=[-3, 0, 3], y=[7, 4, -2])
    print(result)  # 4.0
Or use pyflyte run:
pyflyte run workflow.py simple_wf --x '[-3,0,3]' --y '[7,4,-2]'

Workflow inputs and outputs

Workflows are strongly typed — inputs and outputs must be annotated. The type system flows through the entire DAG:
from flytekit import task, workflow
import typing


@task
def preprocess(raw: str) -> list[float]:
    return [float(x) for x in raw.split(",")]


@task
def compute_sum(values: list[float]) -> float:
    return sum(values)


@workflow
def data_pipeline(raw_data: str) -> float:
    values = preprocess(raw=raw_data)
    total = compute_sum(values=values)
    return total

Use partial for default arguments

Use functools.partial to assign default or constant values to task parameters:
workflow.py
import functools
from flytekit import task, workflow


@task
def slope(x: list[int], y: list[int]) -> float:
    n = len(x)
    sum_xy = sum(xi * yi for xi, yi in zip(x, y))
    sum_x = sum(x)
    sum_y = sum(y)
    sum_x2 = sum(xi ** 2 for xi in x)
    return (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)


@workflow
def simple_wf_with_partial(x: list[int]) -> float:
    partial_task = functools.partial(slope, y=[7, 4, -2])
    return partial_task(x=x)

Documenting workflows

Flyte stores docstrings in FlyteAdmin and displays them in the UI. You can use any Python docstring style.
documenting_workflows.py
from flytekit import workflow

@workflow
def sphinx_docstring_wf(x: list[int] = [-3, 0, 3], y: list[int] = [7, 4, -2]) -> float:
    """
    Slope and intercept of a regression line.

    This workflow computes the slope and intercept of a regression line
    using the provided x and y data points.

    :param x: List of x-values.
    :param y: List of y-values.
    :return: The intercept of the regression line.
    """
    ...
documenting_workflows.py
from flytekit import workflow

@workflow
def numpy_docstring_wf(x: list[int] = [-3, 0, 3], y: list[int] = [7, 4, -2]) -> float:
    """
    Slope and intercept of a regression line.

    This workflow computes the slope and intercept of a regression line
    using the provided x and y data points.

    Parameters
    ----------
    x : list[int]
        List of x-values.
    y : list[int]
        List of y-values.

    Returns
    -------
    float
        The intercept of the regression line.
    """
    ...
documenting_workflows.py
from flytekit import workflow

@workflow
def google_docstring_wf(x: list[int] = [-3, 0, 3], y: list[int] = [7, 4, -2]) -> float:
    """
    Slope and intercept of a regression line.

    This workflow computes the slope and intercept of a regression line
    using the provided x and y data points.

    Args:
        x (list[int]): List of x-values.
        y (list[int]): List of y-values.

    Returns:
        float: The intercept of the regression line.
    """
    ...
The short description (first line of the docstring) appears on the workflow list page in the UI. The full description is visible when you open the workflow.

Next steps

Launch plans

Schedule workflows and share them with predefined inputs.

Named outputs

Return multiple named outputs from tasks and workflows.

Build docs developers (and LLMs) love