0
0
AirflowHow-ToBeginner · 3 min read

How to Use Taskflow with XCom in Airflow: Simple Guide

Use the @task decorator from Airflow's Taskflow API to define tasks that automatically push return values to XCom. Retrieve these values in downstream tasks by calling the upstream task function with .output inside the DAG context.
📐

Syntax

The Taskflow API uses the @task decorator to define tasks as Python functions. When a task function returns a value, Airflow automatically pushes it to XCom. To use this value in another task, call the upstream task function with .output as an argument.

Key parts:

  • @task: marks a Python function as an Airflow task.
  • Return value: automatically pushed to XCom.
  • .output: used to pull the XCom value from an upstream task.
  • with DAG(...): context defines the workflow.
python
from airflow.decorators import dag, task
from airflow.utils.dates import days_ago

@dag(start_date=days_ago(1), schedule_interval='@daily', catchup=False)
def example_dag():

    @task
def push_task():
        return 'data from push_task'

    @task
def pull_task(data):
        print(f'Received: {data}')

    data = push_task()
    pull_task(data)

example_dag_instance = example_dag()
💻

Example

This example shows two tasks: push_task returns a string that is automatically pushed to XCom. The pull_task receives this data as an argument and prints it. The DAG runs daily without catching up on past runs.

python
from airflow.decorators import dag, task
from airflow.utils.dates import days_ago

@dag(start_date=days_ago(1), schedule_interval='@daily', catchup=False)
def taskflow_xcom_example():

    @task
def push_task():
        return 'Hello from XCom'

    @task
def pull_task(message):
        print(f'Received message: {message}')

    msg = push_task()
    pull_task(msg)

dag = taskflow_xcom_example()
Output
Received message: Hello from XCom
⚠️

Common Pitfalls

  • Not using @task decorator: Without it, return values won't be pushed to XCom automatically.
  • Trying to access XCom outside the DAG context: You must use the task function's .output inside the DAG definition.
  • Passing task instances instead of their outputs: Always pass task_instance.output, not the task function itself.
  • Forgetting to set catchup=False if you don't want backfill runs.
python
from airflow.decorators import dag, task
from airflow.utils.dates import days_ago

@dag(start_date=days_ago(1), schedule_interval='@daily', catchup=False)
def wrong_xcom_usage():

    def push_task():  # Missing @task decorator
        return 'data'

    @task
def pull_task(data):
        print(f'Received: {data}')

    data = push_task()  # This returns a string, but no XCom pushed
    pull_task(data)  # pull_task receives the string directly

# Correct way:
@dag(start_date=days_ago(1), schedule_interval='@daily', catchup=False)
def correct_xcom_usage():

    @task
def push_task():
        return 'data'

    @task
def pull_task(data):
        print(f'Received: {data}')

    data = push_task()
    pull_task(data)
📊

Quick Reference

ConceptDescription
@task decoratorDefines a Python function as an Airflow task that supports XCom automatically.
Return valueAutomatically pushed to XCom for downstream tasks.
.outputUsed to access the XCom value from an upstream task.
DAG contextTasks and their dependencies must be defined inside the DAG function.
catchup=FalsePrevents running past scheduled DAG runs when starting fresh.

Key Takeaways

Use @task decorator to enable automatic XCom push of return values.
Access upstream task data by passing task_function.output inside the DAG.
Always define tasks and dependencies inside the DAG context.
Avoid missing @task decorator to prevent silent XCom failures.
Set catchup=False to control backfill behavior when needed.