Create and use params in Airflow

Params are arguments which you can pass to an Airflow DAG or task at runtime and are stored in the Airflow context dictionary for each DAG run. You can pass DAG and task-level params by using the params parameter.

Params are ideal to store information that is specific to individual DAG runs like changing dates, file paths or ML model configurations. Params are not encrypted and therefore not suitable to pass secrets. See also Best practices for storing information in Airflow.

This guide covers:

  • How to pass params to a DAG at runtime.
  • How to define DAG-level param defaults which are rendered in the Trigger DAG UI.
  • How to access params in an Airflow task.
  • The hierarchy of params in Airflow.

Assumed knowledge

To get the most out of this guide, you should have an understanding of:

Pass params to a DAG run at runtime

Params can be passed to a DAG at runtime in four different ways:

  • In the Airflow UI by using the Trigger DAG form. This form appears when you click on the Trigger DAG (Play) button in the Airflow UI.
  • Running a DAG with the --conf flag using the Airflow CLI (airflow dags trigger).
  • Using the TriggerDagRunOperator with the conf parameter.
  • Making a POST request to the Airflow REST APIs Trigger Dag Run endpoint and using the conf parameter.

Param values passed to a DAG by any of these methods will override existing default values for the same key as long as the Airflow core config dag_run_conf_overrides_params is set to True (which is the default setting).

Info

You can only pass params to a DAG that are JSON-serializeable. Any params that are not JSON-serializeable will cause a DAG Import Error (ParamValidationError) upon DAG parsing.

Trigger DAG form

You can pass params to DAGs from the Airflow UI by clicking on the Play button in the DAGs overview or on the blue Trigger button on an individual DAG page.

Play button

This button opens a form in which you can specify details for the DAG run. If the DAG has any params with defaults values defined, the form will render a field for each those params under Run Parameters. Additional params can be added under Advanced Options -> Configuration JSON.

Trigger DAG form

Under Advanced Options, you can also set the Logical Date, define a Run ID, and add a Dag Run Note for the manual DAG run. Note that any params already defined under Run Parameters will be included in the Configuration JSON by default.

Advanced options trigger form

In the Trigger DAG form:

  • You can change any default values for params that have been defined in the DAG file under Run Parameters or in the Configuration JSON.
  • You can add new params under Advanced Options -> Configuration JSON.
  • You can set the Logical Date of the DAG run to any date. Note that you can also provide no logical date, by clearning it in the calendar picker.
  • You can set the Run ID to any string. If no Run ID is specified, Airflow generates one based on the run after date.
  • You can add a Dag Run Note to the DAG run.

After setting the configuration, you can start the DAG run with the Trigger button.

CLI

When you run an Airflow DAG from the CLI, you can pass params to the DAG run by providing a JSON string to the --conf flag. For example, to trigger the params_default_example DAG with the value of Hello from the CLI for param1, run:

Astro

Run Airflow commands from the Astro CLI using astro dev run:

1astro dev run dags trigger params_defaults_example --conf '{"param1" : "Hello from the CLI"}'
Airflow
1airflow dags trigger params_defaults_example --conf '{"param1" : "Hello from the CLI"}'

The CLI prints the configuration for the triggered run to the command line:

CLI output

You can use a --conf flag with the following Airflow CLI sub-commands:

  • airflow dags backfill
  • airflow dags test
  • airflow dags trigger

TriggerDagRunOperator

The TriggerDagRunOperator is a core Airflow operator that allows you to start a DAG run from within another DAG. You can use the TriggerDAGRunOperator conf param to trigger the dependent DAG with a specific configuration.

The DAG below uses the TriggerDagRunOperator to trigger the tdro_example_downstream DAG while passing a dynamic value for the upstream_color param via the conf parameter. The value for upstream_color is passed via a Jinja template pulling the return value of an upstream task via XCom.

Taskflow
1from pendulum import datetime
2from airflow.decorators import dag, task
3from airflow.operators.trigger_dagrun import TriggerDagRunOperator
4import random
5
6
7@dag(
8 start_date=datetime(2023, 6, 1),
9 schedule="@daily",
10 catchup=False,
11)
12def tdro_example_upstream():
13 @task
14 def choose_color():
15 color = random.choice(["blue", "red", "green", "yellow"])
16 return color
17
18 tdro = TriggerDagRunOperator(
19 task_id="tdro",
20 trigger_dag_id="tdro_example_downstream",
21 conf={"upstream_color": "{{ ti.xcom_pull(task_ids='choose_color')}}"},
22 )
23
24 choose_color() >> tdro
25
26
27tdro_example_upstream()
Traditional
1from pendulum import datetime
2from airflow.decorators import dag, task
3from airflow.operators.trigger_dagrun import TriggerDagRunOperator
4from airflow.operators.python import PythonOperator
5import random
6
7
8def choose_color_func():
9 color = random.choice(["blue", "red", "green", "yellow"])
10 return color
11
12
13@dag(
14 start_date=datetime(2023, 6, 1),
15 schedule="@daily",
16 catchup=False,
17)
18def tdro_example_upstream_traditional():
19 choose_color = PythonOperator(
20 task_id="choose_color",
21 python_callable=choose_color_func,
22 )
23
24 tdro = TriggerDagRunOperator(
25 task_id="tdro",
26 trigger_dag_id="tdro_example_downstream",
27 conf={"upstream_color": "{{ ti.xcom_pull(task_ids='choose_color')}}"},
28 )
29
30 choose_color >> tdro
31
32
33tdro_example_upstream_traditional()

Runs of the tdro_example_downstream DAG that are triggered by this upstream DAG will override the default value of the upstream_color param with the value passed via the conf parameter, which leads to the print_color task to print either red, green, blue or yellow.

Taskflow
1from pendulum import datetime
2from airflow.decorators import dag, task
3
4
5@dag(
6 start_date=datetime(2023, 6, 1),
7 schedule=None,
8 catchup=False,
9 params={"upstream_color": "Manual run, no upstream color available."},
10)
11def tdro_example_downstream():
12 @task
13 def print_color(**context):
14 print(context["params"]["upstream_color"])
15
16 print_color()
17
18
19tdro_example_downstream()
Traditional
1from pendulum import datetime
2from airflow.decorators import dag
3from airflow.operators.python import PythonOperator
4
5
6def print_color_func(**context):
7 print(context["params"]["upstream_color"])
8
9
10@dag(
11 start_date=datetime(2023, 6, 1),
12 schedule=None,
13 catchup=False,
14 params={"upstream_color": "Manual run, no upstream color available."},
15)
16def tdro_example_downstream_traditional():
17 PythonOperator(
18 task_id="print_color",
19 python_callable=print_color_func,
20 )
21
22
23tdro_example_downstream_traditional()

Define DAG-level param defaults

To specify params for all runs of a given DAG, pass default values to the param parameter of the @dag decorator or the DAG class in your DAG file. You can directly specify a default value or use the Param class to define a default value with additional attributes.

The DAG below has two DAG-level params with defaults: param1 and param2, the latter only accepting integers.

Taskflow
1from pendulum import datetime
2from airflow.decorators import dag, task
3from airflow.models.param import Param
4
5
6@dag(
7 start_date=datetime(2023, 6, 1),
8 schedule=None,
9 catchup=False,
10 params={
11 "param1": "Hello!",
12 "param2": Param(
13 23,
14 type="integer",
15 ),
16 },
17)
18def simple_param_dag():
19 @task
20 def print_all_params(**context):
21 print(context["params"]["param1"] * 3)
22 print(context["params"]["param2"])
23
24 print_all_params()
25
26
27simple_param_dag()
Traditional
1from pendulum import datetime
2from airflow import DAG
3from airflow.operators.python import PythonOperator
4from airflow.models.param import Param
5
6
7def print_all_params_func(**context):
8 print(context["params"]["param1"] * 3)
9 print(context["params"]["param2"])
10
11
12with DAG(
13 dag_id="simple_param_dag",
14 start_date=datetime(2023, 6, 1),
15 schedule=None,
16 catchup=False,
17 params={
18 "param1": "Hello!",
19 "param2": Param(
20 23,
21 type="integer",
22 ),
23 },
24):
25 PythonOperator(
26 task_id="print_all_params",
27 python_callable=print_all_params_func,
28 )

If you define DAG-level param defaults, the Trigger DAG form renders a field for each param. From this UI, you can then override your defaults for individual DAG runs. A param with a red asterisk is a required param.

Trigger DAG with simple defaults

Info

When you specify a required type for a param, the field will be a required input by default because of JSON validation. To make a field optional but still require a specific input type, allow NULL values by setting the type to ["null", "<my_type>"].

Info

If you do not specify a type for your param, Airflow will infer it based on the default value you provide.

Param types

The following param types are supported:

  • string: A string. This is the default type.
  • null: Allows the param to be None by being left empty.
  • integer: An integer.
  • number: A float (or integer).
  • boolean: True or False.
  • array: An HTML multi line text field, every line edited will be made into a string array as the value.
  • object: A JSON entry field.

Param attributes

Aside from the type attribute, the Param class has several other attributes that you can use to define how users interact with the param:

  • title: The title of the param that appears in the Trigger DAG UI.
  • description: A description of the param.
  • section: Creates a section under which the param will appear in the Trigger DAG UI. All params with no specified section will appear under the default section DAG conf Parameters.
  • format: A JSON format that Airflow will validate a user’s input against.
  • enum: A list of valid values for a param. Setting this attribute creates a dropdown menu in the UI.
  • const: Defines a permanent default value and hides the param from the Trigger DAG UI. Note that you still need to provide a default value for the param.

All Param attributes are optional to set. For string type params, you can additionally set minLength and maxLength to define the minimum and maximum length of the input. Similarly, integer and number type params can have a minimum and maximum value.

Param examples in the Airflow UI

This section presents a few examples of params and how they are rendered in the Trigger DAG UI.

The code snippet below defines a mandatory string param with a few UI elements to help users input a value.

1from airflow.sdk import Param
2
3"my_string_param": Param(
4 "Airflow is awesome!",
5 type="string",
6 title="Favorite orchestrator:",
7 description="Enter your favorite data orchestration tool.",
8 section="Important params",
9 minLength=1,
10 maxLength=200,
11)

String param example

When you define date, datetime, or time param, a calendar picker appears in the Trigger DAG UI.

1from airflow.sdk import Param
2
3"my_datetime_param": Param(
4 "2016-10-18T14:00:00+00:00",
5 type="string",
6 format="date-time",
7),

Datetime param example

Providing a list of values to the enum attribute will create a dropdown menu in the Trigger DAG UI. Note that the default value must also be in the list of valid values provided to enum. Due to JSON validation rules, a value has to be selected.

1from airflow.sdk import Param
2
3"my_enum_param": Param(
4 "Hi :)", type="string", enum=["Hola :)", "Hei :)", "Bonjour :)", "Hi :)"]
5),

Enum param example

A boolean type param will create a toggle in the Trigger DAG UI.

1from airflow.sdk import Param
2
3"my_bool_param": Param(True, type="boolean"),

Bool param example

An array type param will create a multi-line text field in the Trigger DAG UI. Each line will be converted to an item in the array.

1from airflow.sdk import Param
2
3"my_array_param": Param(["Hello Airflow", ":)"], type="array"),

Array param example

An object type param will create a JSON entry field in the Trigger DAG UI. The value of the param must be a valid JSON object.

1from airflow.sdk import Param
2
3"my_object_param": Param({"a": 1, "b": 2}, type="object"),

Object param example

Define task-level param defaults

You can set task-level param defaults in the same way as for DAG-level params. If a param of the same key is specified at both the DAG and task level, the DAG-level param will take precedence.

Taskflow
1@task(params={"param1": "Hello World!"})
2def t1(**context):
3 print(context["params"]["param1"])
Traditional
1t1 = BashOperator(
2 task_id="t1",
3 bash_command="echo {{ params.param1 }}",
4 params={"param1": "Hello World!"},
5)

Access params in a task

You can access params in an Airflow task like you can with other elements in the Airflow context.

Taskflow
1from airflow.sdk import task
2
3@task
4def t1(**context):
5 print(context["params"]["my_param"])
Traditional
1from airflow.providers.standard.operators.python import PythonOperator
2
3def t1_func(**context):
4 print(context["params"]["my_param"])
5
6t1 = PythonOperator(
7 task_id="t1",
8 python_callable=t1_func,
9)

Params are also accessible as a Jinja template using the {{ params.my_param }} syntax.

If you try to access a param that has not been specified for a specific DAG run, the task will fail with an exception.

Param precedence

The order of precedence for params, with the first item taking most precedence, is as follows: