Make Flows Dynamic with Typed Inputs and Runtime Parameters

For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append .md to any kestra.io/docs/* URL for plain Markdown.

Inputs are typed, validated parameters passed to a flow at execution time.

Flow inputs are stored in the execution context and accessed with {{ inputs.parameter_name }}. All inputs are validated when the execution is created — invalid or missing required inputs prevent the execution from being created and it will not appear in the executions list.

Declaring inputs

Inputs are declared under the inputs key. Each input requires an id and a type. Inputs are required by default; set required: false to make one optional.

id: inputs_demo
namespace: company.team
inputs:
- id: username
type: STRING
defaults: "alice"
description: The user to greet.
- id: threshold
type: INT
min: 1
max: 100
- id: environment
type: SELECT
values:
- dev
- staging
- prod
defaults: dev
- id: config_file
type: FILE
allowedFileExtensions: [".json", ".yaml"]
- id: optional_note
type: STRING
required: false
tasks:
- id: log
type: io.kestra.plugin.core.log.Log
message: "Hello {{ inputs.username }} — deploying to {{ inputs.environment }}"

Input types

Inputs are strongly typed and validated before execution starts.

TypeAcceptsConstraints & extra properties
STRINGAny stringvalidator (regex)
EMAILValid email addressvalidator (regex)
INTIntegermin, max
FLOATFloatmin, max
BOOLtrue or false
DATETIMEISO 8601 datetime in UTC — e.g. 2042-04-02T04:20:42.000Zafter, before
DATEISO 8601 date without timezone — e.g. 2042-12-03after, before
TIMEISO 8601 time without timezone — e.g. 10:15:30after, before
DURATIONISO 8601 duration — e.g. PT5M6Smin, max
SELECTOne value from a predefined listvalues, expression, allowCustomValue, autoSelectFirst
MULTISELECTOne or more values from a predefined listSame as SELECT
FILEUploaded file, nsfile:/// (namespace file), or file:/// (local allowed path)allowedFileExtensions; stored in internal storage; the only type that accepts a multipart file upload via the API — all other types require a plain string value
JSONValid JSON stringjsonSchema (JSON Schema Draft 2020-12)
IONIon-formatted text, parsed into a structured object (Map or List) accessible with dot notation — e.g. {{ inputs.record.name }}; use Ion syntax for defaults: '{name:"Ada",score:21}'
YAMLValid YAML string
URIValid URI, kept as a string
SECRETEncrypted string, decrypted at runtime and masked in UI and logsvalidator (regex); requires encryption key
ARRAYJSON array or YAML listitemType (required)
FORMGroups child inputs as a multi-step wizard in the Execute modalCannot nest; no defaults/prefill on the FORM itself
REUSABLE_INPUTSReferences a namespace-level named input group (Enterprise Edition)See Reusable Inputs

Input properties

PropertyDescription
idIdentifier used to reference the input — e.g. {{ inputs.user }}.
typeData type, as listed above.
requiredWhether the input is required. Defaults to true.
defaultsDefault value applied when no value is provided at runtime.
prefillInitial value shown in the UI that can be cleared to null. Unlike defaults, a cleared prefill resolves to null.
displayNameLabel shown in the UI instead of the id.
descriptionMarkdown description displayed in the UI.
validatorRegex pattern for STRING and SECRET types.
expressionPebble expression used to populate SELECT and MULTISELECT values dynamically — e.g. {{ kv('MY_LIST') }}.
dependsOnMakes this input conditional on other inputs being provided or matching a condition.
autoSelectFirstAuto-selects the first value in SELECT/MULTISELECT lists as the default.

Input validation

Type constraints

INT, FLOAT, and DURATION accept min and max. DATE, TIME, and DATETIME accept after and before. STRING and SECRET accept a validator regex.

inputs:
- id: age
type: INT
min: 18
max: 64
- id: username
type: STRING
validator: ^[a-z0-9_]{3,20}$
- id: start_date
type: DATE
after: "2024-01-01"
before: "2025-01-01"

JSON Schema validation

Use the jsonSchema property to validate a JSON input against a schema at execution time. An invalid payload rejects the execution before any task runs:

id: json_schema_validation
namespace: company.team
inputs:
- id: payload
type: JSON
jsonSchema: |
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" }
},
"additionalProperties": false
}
tasks:
- id: log
type: io.kestra.plugin.core.log.Log
message: "Hello, {{ inputs.payload.name }}!"

Nested inputs

Use . in an input id to create a nested structure, accessible with the same dot notation in expressions:

inputs:
- id: db.host
type: STRING
defaults: localhost
- id: db.port
type: INT
defaults: 5432
tasks:
- id: log
type: io.kestra.plugin.core.log.Log
message: "Connecting to {{ inputs.db.host }}:{{ inputs.db.port }}"

FORM inputs

FORM groups related inputs under a shared label and renders a multi-step wizard in the Execute modal:

id: provision_environment
namespace: company.team
inputs:
- id: requester
type: STRING
required: true
- id: environment
type: FORM
displayName: Environment setup
description: Where the environment runs and what size it needs.
inputs:
- id: region
type: SELECT
defaults: eu-central-1
values:
- eu-central-1
- eu-west-1
- us-east-1
- id: instance_type
type: SELECT
defaults: t3.medium
values:
- t3.medium
- t3.large
- t3.xlarge
tasks:
- id: log
type: io.kestra.plugin.core.log.Log
message: |
Requester: {{ inputs.requester }}
Region: {{ inputs.environment.region }}
Instance: {{ inputs.environment.instance_type }}

When triggering a flow with FORM inputs via the API, use flat dotted field names:

curl -X POST "http://localhost:8080/api/v1/main/executions/company.team/provision_environment" \
-H "Content-Type: multipart/form-data" \
-F "requester=platform-team" \
-F "environment.region=eu-central-1" \
-F "environment.instance_type=t3.large"

Array inputs

ARRAY accepts a JSON array or YAML list. The itemType property is required:

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

Using inputs in a flow

Reference inputs with {{ inputs.name }} in any dynamic property. Use bracket notation for IDs containing hyphens or other special characters:

inputs:
- id: message
type: STRING
- id: my-file
type: FILE
tasks:
- id: use_inputs
type: io.kestra.plugin.scripts.shell.Commands
commands:
- echo "{{ inputs.message }}"
inputFiles:
upload.tmp: "{{ inputs['my-file'] }}"

Setting inputs at execution time

Provide input values from the UI (Kestra generates a form based on your input definitions), the API, the CLI (kestractl), Python (kestra pip package), or any HTTP client. See Execute a flow for full examples with curl, Python, and kestractl.

Inputs vs. variables

Variables are defined before execution and cannot be changed once it starts. Inputs are provided at execution time and can differ between runs. Use variables for fixed values reused across tasks; use inputs for values that change per execution.

Dynamic inputs

SELECT and MULTISELECT inputs support an expression property that populates the dropdown from a Pebble expression — a KV store lookup, an HTTP API call, or a subflow result:

inputs:
- id: environment
type: SELECT
expression: "{{ kv('ENVIRONMENTS') }}"

See the Dynamic inputs how-to guide for HTTP function examples, subflow-populated dropdowns, and chaining dependent dropdowns.

Conditional inputs

Use dependsOn and condition to show inputs only when a previous input matches a value:

inputs:
- id: notify
type: BOOL
defaults: false
- id: slack_channel
type: STRING
dependsOn:
inputs:
- notify
condition: "{{ inputs.notify == true }}"

slack_channel only appears in the Execute modal when notify is true. See the Dynamic inputs how-to guide for full conditional provisioning examples.

Label/value pairs in SELECT and MULTISELECT

Each entry in values can be a plain string or a {label, value} object. The UI shows label; {{ inputs.x }} resolves to value:

inputs:
- id: aws_account
type: SELECT
displayName: AWS Account
values:
- label: "Production"
value: "123456789012"
- label: "Staging"
value: "987654321098"
tasks:
- id: log
type: io.kestra.plugin.core.log.Log
message: "Account ID: {{ inputs.aws_account }}"

defaults, autoSelectFirst, and validation all operate on the value field, not the label.

Custom values in SELECT and MULTISELECT

Set allowCustomValue: true to let users enter a value outside the predefined list:

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

Was this page helpful?