Inputs is a list of dynamic values passed to the flow at runtime.

What are inputs

A flow can be parameterized using inputs to allow multiple executions of the same flow, each with different input values. Flow inputs are stored as variables within the flow execution context and can be accessed within the flow using the syntax {{ inputs.parameter_name }}.

You can use inputs to make your tasks more dynamic. For instance, you can use an input to dynamically define the path of a file that needs to be processed within a flow.

You can inspect the input values in the Overview tab of the Execution page.

You can set a custom displayName for each input to make the Execution interface more user-friendly.

Declaring inputs

You can declare as many inputs as necessary for any flow. Inputs can be required or optional.

If an input is required, we recommend using the defaults property to set default values. The flow cannot start if the input is not provided during the creation of the Execution.

Every input will be parsed during the creation of the execution, and any invalid inputs will deny the creation of the execution.

Below is an example flow using several inputs:

yaml
id: inputs
namespace: company.team

inputs:
  - id: string
    type: STRING
    defaults: "Hello World!"
    displayName: "A string input"

  - id: optional
    type: STRING
    required: false
    displayName: "An optional string"

  - id: int
    type: INT
    defaults: 100
    displayName: "An integer input"

  - id: list_of_int
    type: ARRAY
    itemType: INT
    defaults: [1, 2, 3]
    displayName: "A list of integers"

  - id: bool
    type: BOOLEAN
    defaults: true
    displayName: "A boolean input"

  - id: float
    type: FLOAT
    defaults: 100.12
    displayName: "A float input"

  - id: dropdown
    type: SELECT
    displayName: "A dropdown input"
    defaults: VALUE_1
    values:
      - VALUE_1
      - VALUE_2
      - VALUE_3

  - id: dropdown_multi
    type: MULTISELECT
    values:
      - VALUE_1
      - VALUE_2
      - VALUE_3

  - id: instant
    type: DATETIME
    defaults: "2013-08-09T14:19:00Z"
    displayName: "A datetime input"

  - id: date
    type: DATE
    defaults: "2013-10-25"
    displayName: "A date input"

  - id: time
    type: TIME
    displayName: "A time input"
    defaults: "14:19:00"

  - id: duration
    type: DURATION
    defaults: "PT5M6S"
    displayName: "A duration input"

  - id: file
    type: FILE
    displayName: "Upload a file"

  - id: json
    type: JSON
    displayName: "A JSON input"
    defaults: |
      [{"name": "kestra", "rating": "best in class"}]

  - id: uri
    type: URI
    defaults: "https://huggingface.co/datasets/kestra/datasets/raw/main/csv/orders.csv"
    displayName: "A URI input"

  - id: secret
    type: SECRET
    displayName: "A secret input"

  - id: yaml
    type: YAML
    defaults:
      - user: john
        email: [email protected]
      - user: will
        email: [email protected]
    displayName: YAML

  - id: nested.string
    type: STRING
    defaults: "Hello World!"
    displayName: "A nested string input"

Input types

Inputs in Kestra are strongly typed and validated before starting the flow execution.

Here is the list of supported data types:

  • STRING: It can be any string value — inputs of type STRING are passed to the execution in its raw format without parsing; for additional validation, you can add a custom regex validator to allow only specific string patterns.
  • INT: Must be a valid integer value (without any decimals).
  • FLOAT: Must be a valid float value (with decimals).
  • SELECT: Must be a valid string value from a predefined list of values. You can either pass those values directly using the values property or use the expression property to fetch the values dynamically from a KV store. Additionally, if allowCustomValue is set to true, the user can provide a custom value that is not in the predefined list.
  • MULTISELECT: Must be one or more valid string values from a predefined list of values. You can either pass those values directly using the values property or use the expression property to fetch the values dynamically from a KV store. Additionally, if allowCustomValue is set to true, the user can provide a custom value that is not in the predefined list.
  • BOOLEAN: Must be true or false passed as strings.
  • DATETIME: Must be a valid full ISO 8601 date and time with the timezone expressed in UTC format; pass input of type DATETIME in a string format following the pattern 2042-04-02T04:20:42.00Z.
  • DATE: Must be a valid full ISO 8601 date without the timezone from a text string such as 2042-12-03.
  • TIME: Must be a valid full ISO 8601 time without the timezone from a text string such as 10:15:30.
  • DURATION: Must be a valid full ISO 8601 duration from a text string such as PT5M6S.
  • FILE: Must be a file sent as Content-Type: multipart/form-data with Content-Disposition: form-data; name="files"; filename="my-file", where my-file is the name of the input.
  • JSON: Must be a valid JSON string and will be converted to a typed form.
  • YAML: Must be a valid YAML string.
  • URI: Must be a valid URI and will be kept as a string.
  • SECRET: a SECRET input is a string that is encrypted and stored in the database. It is decrypted at runtime and can be used in all tasks. The value of a SECRET input is masked in the UI and in the execution context. Note that you need to set the encryption key in your Kestra configuration before using it.
  • ARRAY: Must be a valid JSON array or a YAML list. The itemType property is required to ensure validation of the type of the array items.

All inputs of type FILE will be automatically uploaded to Kestra's internal storage and accessible to all tasks. After the upload, the input variable will contain a fully qualified URL of the form kestra:///.../.../ that will be automatically managed by Kestra and can be used as-is within any task.

Input Properties

Below is the list of available properties for all inputs regardless of their types:

  • id: The input parameter identifier — this property is important as it's used to reference the input variables in your flow, e.g. {{ inputs.user }} will reference the input parameter named user.
  • type: The data type of the input parameter, as described in the previous section.
  • required: Whether the input is required or optional; if required is set to true and no default value is configured and also no input is provided at runtime, the execution will not be created as Kestra cannot know what value to use.
  • defaults: The default value that will be used if no custom input value is provided at runtime; this value must be provided as a string and will be coerced to the desired data type specified using the type property.
  • dependsOn: Allows you to make the input dependent on another input to be inputted first.
  • displayName: A different name that will display in the Execution interface instead of the id.
  • description: A markdown description to document the input.

Input validation

Kestra validates the type of each input. In addition to the type validation, some input types can be configured with validation rules that will be enforced at execution time.

  • STRING: A validator property allows the addition of a validation regex.
  • INT: min and max properties allow the addition of minimum and maximum value ranges.
  • FLOAT: min and max properties allow the addition of minimum and maximum ranges.
  • DURATION: min and max properties allow the addition of minimum and maximum ranges.
  • DATE: after and before properties help you ensure that the input value is within the allowed date range.
  • TIME: after and before properties help you ensure that the input value is within the allowed time range.
  • DATETIME: after and before properties help you ensure that the input value is within the allowed date range.

Example: using input validators in your flows

To ensure that your input value is within a certain integer value range, you can use the min and max properties. Similarly, to ensure that your string input matches a regex pattern, you can provide a custom regex validator. The following flow demonstrates how this can be accomplished:

yaml
id: regex_input
namespace: company.team

inputs:
  - id: age
    type: INT
    defaults: 42
    required: false
    min: 18
    max: 64

  - id: user
    type: STRING
    defaults: student
    required: false
    validator: ^student(\d+)?$

  - id: float
    type: FLOAT
    defaults: 3.2
    min: 0.2
    max: 5.3

  - id: duration
    type: DURATION
    min: "PT5M6S"
    max: "PT12H58M46S"

  - id: date
    type: DATE
    defaults: "2024-04-12"
    after: "2024-04-10"
    before: "2024-04-15"

  - id: time
    type: TIME
    after: "11:01:01"
    before: "11:04:01"

  - id: datetime
    type: DATETIME
    defaults: "2024-04-13T14:17:00Z"
    after: "2024-04-10T14:19:00Z"
    before: "2024-04-15T14:19:00Z"

tasks:
  - id: validator
    type: io.kestra.plugin.core.log.Log
    message: User {{ inputs.user }}, age {{ inputs.age }}

The age, float, and duration input must be within a valid range between min and max values. Specifically for the age input, we specify that this input will be by default set to 42, but it can be overwritten at runtime to a value between 18 and 64. If you attempt to execute the flow with the age input set to 17 or 65, the validation will fail and the execution won't start.

Similarly, the Regex expression ^student(\d+)?$ is used to validate that the input argument user of type STRING follows the following pattern:

  • ^student: This part of the regex asserts that the string must begin with the lowercase string value student.
  • \d: This part of the regex matches any digit (0-9).
  • +: This part of the regex asserts that there is one or more of the preceding token (i.e., one or more digits are allowed after the value student).
  • ()?: The parentheses group the digits together, and the question mark makes the entire group optional — this means that the digits after the word student are optional.
  • $: This part of the regex asserts the end of the string. This ensures that the string doesn't contain any additional characters after the optional digits.

With this pattern:

  • "student" would be a match.
  • "student123" would be a match.
  • "studentabc" would not be a match because "abc" isn't a sequence of digits.
  • "student123abc" would not be a match because no more characters are allowed after the sequence of "students" with the following numbers.

Lastly, the date, time, and datetime inputs must be within a valid range between after and before. In the date example, the date provided must be between 10th May 2024 and 15th May 2024. Anything outside of this range will fail and the execution won't start.

Try running this flow with various inputs or adjust the regex pattern to see how the input validation works.

Nested Inputs

If you use a . inside the name of an input, the input will be nested.

Here's an example that includes 2 nested inputs:

yaml
id: nested_inputs
namespace: company.team

inputs:
  - id: nested.string
    type: STRING
    required: false

  - id: nested.int
    type: INT

tasks:
  - id: log_inputs
    type: io.kestra.plugin.core.log.Log
    message: "{{ inputs.nested.string }} and {{ inputs.nested.int }}"

You can access the first input value using {{ inputs.nested.string }}. This syntax provides a convenient type validation of nested inputs without using raw JSON that would not be validated (JSON-type input values are passed as strings).

Array Inputs

Array inputs are used to pass a list of values to a flow. The itemType property is required to ensure validation of the type of the array items.

It's particularly useful when you want the end-user triggering the workflow to provide multiple values of a specific type, e.g. a list of integers, strings, booleans, datetimes, etc. You can provide the default values as a JSON array or as a YAML list — both are supported.

yaml
id: array_demo
namespace: company.team

inputs:
  - id: my_numbers_json_list
    type: ARRAY
    itemType: INT
    defaults: [1, 2, 3]

  - id: my_numbers_yaml_list
    type: ARRAY
    itemType: INT
    defaults:
      - 1
      - 2
      - 3

tasks:
  - id: print_status
    type: io.kestra.plugin.core.log.Log
    message: received inputs {{ inputs }}

Here is how the array inputs are rendered in the UI when you create an execution:

array_inputs

Using an input value in a flow

Every input is available with dynamic variables such as: {{ inputs.name }} or {{ inputs['name'] }}. If you use characters inside of your input id such as -, you'll need to use the {{ inputs['name-example']}} format.

For example, if you declare the following inputs:

yaml
inputs:
  - id: mystring
    type: STRING
    required: true

  - id: my-file
    type: FILE

You can use the value of the input mystring inside dynamic task properties with {{ inputs.mystring }} but my-file would have to use {{ inputs['my-file'] }} because of the -.

We can see a full example here where inputFiles property is set to {{ inputs['my-file'] }}:

yaml
id: input_files
namespace: company.team

description: This flow shows how to pass files between inputs and tasks in Shell scripts.

inputs:
  - id: my-file
    type: FILE

tasks:
  - id: rename
    type: io.kestra.plugin.scripts.shell.Commands
    commands:
      - mv file.tmp output.tmp
    inputFiles:
      file.tmp: "{{ inputs['my-file'] }}"
    outputFiles:
      - "*.tmp"

Set input values at flow execution

When you execute a flow with inputs, you must set all inputs (unless optional or with a default value) to be able to create the execution.

Let's consider the following example that defines multiple inputs:

yaml
id: kestra_inputs
namespace: company.team

inputs:
  - id: string
    type: STRING
    defaults: hello

  - id: optional
    type: STRING
    required: false

  - id: int
    type: INT

  - id: float
    type: FLOAT

  - id: instant
    type: DATETIME

  - id: file
    type: FILE

Here, the inputs {{ inputs.string }} and {{ inputs.optional }} can be skipped because the string input has a default value and the optional input is not required. All other inputs must be specified at runtime.

Set inputs from the web UI

When creating an execution from the web UI, you must set the inputs in the UI form. Kestra's UI will generate a dedicated form based on your inputs definition. For example, datetime input properties will have a date picker.

The input form for the inputs above looks as follows:

Flow inputs

Once the inputs are set, you can trigger an execution of the flow.

Set inputs when executing the flow using the API

To create an execution with these inputs using the API, we can use the curl command to make an API request:

bash
curl -v "http://localhost:8080/api/v1/executions/example/kestra-inputs" \
    -H "Transfer-Encoding:chunked" \
    -H "Content-Type:multipart/form-data" \
    -F string="a string"  \
    -F optional="an optional string"  \
    -F int=1  \
    -F float=1.255  \
    -F instant="2023-12-24T23:00:00.000Z" \
    -F "files=@/tmp/128M.txt;filename=file"

All files must be sent as multipart form data named files with a header filename=my-file which will be the name of the input.

Set inputs when executing the flow in Python

To create an execution with these inputs in Python, you can use the following script:

python
import io
import requests
from kestra import Flow

flow = Flow()

with open('/tmp/example.txt', 'rb') as fh:
  flow.execute('example',
               'kestra-inputs',
               {'string': 'a string',
                'optional': 'an optional string',
                'int': 1,
                'float': str(1.255),
                'instant': '2020-01-14T23:00:00.000Z',
                'files': ('file', fh, 'text/plain')})

You can also use the requests library in Python to make requests to the Kestra API. Here's an example to execute a flow with multiple inputs:

python
import io
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

with open("/tmp/128M.txt", 'rb') as fh:
  url = f"http://kestra:8080/api/v1/executions/io.kestra.docs/my-flow"
  mp_encoder = MultipartEncoder(fields={
    "string": "a string",
    "optional": "an optionnal string",
    "int": 1,
    "float": 1.255,
    "instant": "2020-01-14T23:00:00.000Z",
    "files": ("file", fh, "text/plain")
  })
  result = requests.post(
      url,
      data=mp_encoder,
      headers={"Content-Type": mp_encoder.content_type},
  )

Set inputs when executing the flow in Java

To create an execution with these inputs in Java (with Apache Http Client 5), you can use the following script:

java
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.FileBody;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.entity.mime.StringBody;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;

import java.io.File;

class Application {
  public static void main(String[] args) {
    HttpEntity multipartEntity = MultipartEntityBuilder.create()
        .addPart("string", new StringBody("test", ContentType.DEFAULT_TEXT))
        .addPart("int", new StringBody("1", ContentType.DEFAULT_TEXT))
        .addPart("files", new FileBody(new File("/tmp/test.csv"), ContentType.DEFAULT_TEXT, "file"))
        .build();

    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build()) {
      HttpPost request = new HttpPost("http://kestra:8080/api/v1/executions/com.kestra.lde/inputs");
      request.setEntity(multipartEntity);

      CloseableHttpResponse response = httpclient.execute(request);

      System.out.println("Response " + response);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}

Difference between inputs and variables

Variables are similar to constant values. They have the same behaviour as an input during execution but they can't be overridden once the execution starts. Variables must be defined before execution whereas inputs can be set at execution.

Variables are best suited for values that you don't want to change, and are used in multiple places within the flow. For example, a URL you will use for an API request that won't change would be best as a variable whereas an email address that changes every time you execute your flow would be best as an input.

Dynamic inputs

Inputs in kestra are strongly typed. Currently, it's not possible to enforce strong types and simultaneously use dynamically rendered Pebble expressions. However, you can use Pebble expressions in default values within STRING inputs.

This example wouldn't work:

yaml
id: test
namespace: company.team

inputs:
  - id: date
    type: DATETIME
    defaults: "{{ now() }}"

tasks:
  - id: print_date
    type: io.kestra.plugin.core.log.Log
    message: hello on {{ inputs.date }}

However, if you change the input type to STRING, you can use Pebble expressions such as {{ now() }} in the default value:

yaml
id: test
namespace: company.team

inputs:
  - id: date
    type: STRING
    defaults: "{{ now() }}"

tasks:
  - id: print_date
    type: io.kestra.plugin.core.log.Log
    message: hello on {{ render(inputs.date) }}

Keep in mind that since Kestra 0.14, inputs are no longer rendered recursively. Therefore, you need to use the {{ render(inputs.date) }} syntax to render the Pebble expression specified within the STRING input value. This improves security by preventing the execution of arbitrary code within the Pebble expression.

You can read more about this change in the Migration Guide.

Conditional Inputs for Interactive Workflows

Starting in Kestra 0.19.0, you can set up inputs that depend on other inputs, letting further inputs to be conditionally displayed based on user choices. This is useful for use cases such as approval workflows or dynamic resource provisioning.

How It Works

You can create inputs that change based on conditions using the dependsOn and condition properties. Here's an example where different inputs show up depending on the resource type a user selects:

yaml
id: request_resources
namespace: company.team

inputs:
  - id: resource_type
    displayName: Resource Type
    type: SELECT
    values:
      - Access permissions
      - SaaS application
      - Development tool
      - Cloud VM

  - id: access_permissions
    displayName: Access Permissions
    type: SELECT
    expression: "{{ kv('access_permissions') }}"
    dependsOn:
      inputs:
        - resource_type
      condition: "{{ inputs.resource_type == 'Access permissions' }}"

  - id: saas_applications
    displayName: SaaS Application
    type: MULTISELECT
    expression: "{{ kv('saas_applications') }}"
    dependsOn:
      inputs:
        - resource_type
      condition: "{{ inputs.resource_type == 'SaaS application' }}"

  - id: cloud_provider
    displayName: Cloud Provider
    type: SELECT
    values:
      - AWS
      - GCP
      - Azure
    dependsOn:
      inputs:
        - resource_type
      condition: "{{ inputs.resource_type == 'Cloud VM' }}"

  - id: cloud_vms
    displayName: Cloud VM
    type: SELECT
    expression: "{{ kv('cloud_vms')[inputs.cloud_provider] }}"
    dependsOn:
      inputs:
        - resource_type
        - cloud_provider
      condition: "{{ inputs.resource_type == 'Cloud VM' }}"

In this example:

  • The resource_type input controls which additional inputs (like access_permissions, saas_applications, and cloud_vms) appear.
  • The dependsOn property links the inputs, and the condition property defines when to display the related input.

Before running the above flow, you need to set up the key-value pairs for each input. Expand the example below to see how to set up the key-value pairs for all inputs using a flow.

Flow adding key-value pairs

You could also add those key-value pairs using the API or from the UI.

Custom Values in the SELECT and MULTISELECT Inputs

If you want to allow users to enter other value if the predefined values shown in the dropdown don't fit their needs, you can set allowCustomValue to true on any input. This enables you to provide a list of default values but still (optionally) allow users to enter custom ones.

In the example below, the cloud_provider input allows users to select from a list of the most common cloud providers (AWS, GCP, Azure) or enter a custom value if they use some less common cloud provider e.g. Oracle Cloud.

yaml
id: custom_values
namespace: company.team

inputs:
  - id: cloud_provider
    displayName: Cloud Provider
    type: SELECT
    allowCustomValue: true
    values:
      - AWS
      - GCP
      - Azure

tasks:
  - id: print_status
    type: io.kestra.plugin.core.log.Log
    message: selected cloud provider {{ inputs.cloud_provider }}

Was this page helpful?