Data Access Functions
For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append.mdto anykestra.io/docs/*URL for plain Markdown.
These functions bridge expressions to external or stored data. Use them when the value is not already present in the execution context and must be resolved at runtime.
secret()
Use secret() for sensitive values that should not appear in the flow definition. The namespace defaults to the flow’s namespace; pass a namespace to read a secret stored in another namespace, and a subkey to extract a single field from a JSON secret:
{{ secret('API_KEY') }}{{ secret('GITHUB_ACCESS_TOKEN') }}{{ secret('SHARED_SECRET', namespace='other.namespace') }}{{ secret('DB_CREDENTIALS', subkey='password') }}Arguments:
key— the secret keynamespace— defaults to the flow’s namespace; the secret is resolved using that namespace’s secret backend, with values inherited from parent namespacessubkey— optional field to extract when the secret holds a JSON objectfull— whentrue, returns a map with two fields:value(the primary secret) andmetadata(any additional fields exposed by the secret manager). Cannot be combined withsubkey.
Cross-namespace reads stay within the same tenant. In the Enterprise Edition, a flow may read another namespace’s secrets by default; restrict this by configuring allowedNamespaces on the target namespace.
Retrieving multi-field secrets with full=true
Some secret managers store credentials as structured objects — for example, a database credential with a password, username, and domain. Pass full=true to retrieve all fields at once:
{% set cred = secret('prod-mssql', full=true) %}{{ cred.value }} {# primary secret, same as secret('prod-mssql') #}{{ cred.metadata.username }} {# additional field from the secret manager #}{{ cred.metadata.domain }} {# additional field from the secret manager #}cred.value is always present and holds the primary secret. cred.metadata is only present when the secret manager exposes additional fields — for single-value backends (AWS, Azure, GCP, Doppler, internal), the metadata key is absent and only cred.value is accessible.
| Backend | cred.metadata |
|---|---|
| Delinea | credential fields from the secret template |
| CyberArk | account fields (username, address, etc.) |
| BeyondTrust | credential fields |
| 1Password | item fields |
| AWS, Azure, GCP, Doppler, internal | absent — use cred.value only |
env()
Reads an environment variable from the execution context by name. Use env() when the variable name is dynamic — composed at runtime from inputs or outputs — something not possible with the static envs.varname dot notation.
{{ env('API_HOST') }}{{ env('API_HOST', 'localhost') }}{{ env('api_url_' ~ inputs.environment) }}Arguments:
name— the environment variable name, after normalization (lowercase, prefix stripped)default— optional value returned when the variable is missing or empty
Environment variables are exposed via the envs context map. By default, only variables prefixed with ENV_ are available; the prefix is stripped and the name lowercased: ENV_API_URL_PROD is accessible as env('api_url_prod'). The prefix is configurable via kestra.variables.env-vars-prefix in the runtime configuration.
The key difference from {{ envs.api_url_prod }} is that the name argument accepts any expression, allowing the key to be composed dynamically:
inputs: - id: environment type: STRING defaults: prod
tasks: - id: log_url type: io.kestra.plugin.core.log.Log message: "{{ env('api_url_' ~ inputs.environment) }}"With ENV_API_URL_PROD and ENV_API_URL_DEV set in the host environment, running the flow with environment set to prod resolves to the production URL and dev to the development URL — without any if/switch logic in the flow.
credential()
In Enterprise Edition, use credential() to inject a short-lived token from a managed credential:
{{ credential('my_oauth') }}credential() returns the token only, while the credential definition itself is managed in the Kestra UI:
tasks: - id: request type: io.kestra.plugin.core.http.Request method: GET uri: https://api.example.com/v1/ping auth: type: BEARER token: "{{ credential('my_oauth') }}"read()
read() is the simplest way to turn a file URI back into inline content for a later expression:
{{ read(outputs.someTask.uri) }}{{ read('subdir/file.txt') }}read() accepts both namespace files and internal-storage URIs, which makes it useful after download or transformation tasks that write files as outputs.
For files in CSV, JSON, XML, YAML, or any other non-ION format, read() returns a String. For binary ION files — the format used by ION task outputs — read() returns byte[] to preserve binary fidelity. Pass the result directly to fromIon() to deserialize it:
{{ fromIon(read(outputs.transform.uri)) }}{{ fromIon(read(outputs.transform.uri), allRows=true) }}Do not perform string operations such as contains directly on read() when the URI points to an ION task output — use fromIon() first.
fileURI()
Returns the internal URI of a namespace file without reading its contents. Use fileURI() when a task parameter expects a URI rather than inline content:
{{ fileURI('my_file.txt') }}Use read() instead when you need to embed the file contents inline in a later expression.
kv()
Reads a value from the KV store by key. The namespace defaults to the flow’s namespace; set errorOnMissing to false to return null instead of throwing when the key is absent:
{{ kv('MY_KEY') }}{{ kv('MY_KEY', 'other.namespace') }}{{ kv('OPTIONAL_KEY', namespace, false) }}Arguments:
key— the KV store keynamespace— defaults to the flow’s namespaceerrorOnMissing— defaults totrue
encrypt() and decrypt()
Encrypt and decrypt string values using Kestra’s encryption service. Both require a key argument that identifies which encryption key to use:
{{ encrypt('MY_ENCRYPTION_KEY', inputs.sensitiveValue) }}{{ decrypt('MY_ENCRYPTION_KEY', outputs.encryptTask.value) }}Was this page helpful?