Back to examples
Basics

Return Values

Rich return types (lists, dicts) passed through a pipeline chain.

When to use

Use this when tasks need to pass structured data to each other. DAGY serialises return values automatically.

basics/return-values.py
"""
04_return_values.py: Rich return types passed through a chain.

Demonstrates:
- Tasks returning dicts and lists
- Downstream tasks consuming structured data
- Composing a pipeline where each stage refines the data
"""

from dagy import flow, task


@task
def fetch_users() -> list:
    return [
        {"id": 1, "name": "Alice", "active": True},
        {"id": 2, "name": "Bob", "active": False},
        {"id": 3, "name": "Charlie", "active": True},
    ]


@task
def filter_active(users: list) -> list:
    return [u for u in users if u["active"]]


@task
def extract_names(users: list) -> list:
    return [u["name"] for u in users]


@task
def build_report(names: list) -> dict:
    return {
        "total_active": len(names),
        "names": names,
        "summary": f"Active users: {', '.join(names)}",
    }


@flow(name="return_values_flow")
def return_values_flow() -> None:
    users = fetch_users()
    active = filter_active(users)
    names = extract_names(active)
    build_report(names)


if __name__ == "__main__":
    result = return_values_flow.deploy(name="return-values-flow")
    print(f"Deployed : {result.flow_name}:{result.flow_version}")
    print(f"Deployment: {result.deployment_name}")

How it works

  1. `fetch_users` returns a list of user dicts.
  2. `filter_active` keeps only users where `active` is `True`.
  3. `extract_names` pulls just the name strings from the filtered list.
  4. `build_report` assembles a summary dict with count and names.
  5. Each task receives exactly what the previous task returned.

Inputs

  • None; all data is generated internally.

Outputs

  • A report dict with `total_active`, `names`, and a `summary` string.

Dependencies

  • `dagy`