New to Kestra?
Use blueprints to kickstart your first workflows.
Pass structured data between Kestra subflows. Call a child flow, wait for it, and reuse its outputs to build modular, reusable workflow architectures.
id: pass-data-between-subflows
namespace: company.team
tasks:
- id: call_child_flow
type: io.kestra.plugin.core.flow.Subflow
namespace: "{{ flow.namespace }}"
flowId: my_subflow
wait: true
- id: log
type: io.kestra.plugin.core.log.Log
message: "{{ outputs.call_child_flow.outputs.my_output }}"
Break large pipelines into small, reusable building blocks and pass structured data cleanly from a child flow back to its parent. This blueprint shows the core Kestra pattern for subflow orchestration: a parent flow invokes a child flow, waits for it to finish, and then consumes the child's declared outputs in later tasks. Instead of copy-pasting logic across many pipelines, you encapsulate a unit of work once as a subflow and call it wherever you need it, with explicit data handoffs and full execution visibility.
call_child_flow task (io.kestra.plugin.core.flow.Subflow) triggers a child flow. It targets flowId: my_subflow in the same namespace via namespace: "{{ flow.namespace }}", and sets wait: true so the parent blocks until the child execution completes.outputs (for example an output my_output mapped from a task result). Those outputs are returned to the parent once the child finishes.log task (io.kestra.plugin.core.log.Log) reads the returned value through {{ outputs.call_child_flow.outputs.my_output }}, demonstrating how downstream tasks consume child outputs.Subflow with wait: true.outputs.<taskId>.outputs.<outputId>.Kestra makes flow composition a first-class, declarative concept. You define everything in YAML, get automatic retries on failed tasks, and capture full lineage across parent and child executions. Event triggers can launch the parent on a schedule, a webhook, or an upstream event, and each subflow run is tracked as its own execution with logs and outputs. This is the gap a single script or a standalone scheduler cannot fill: real cross-flow data passing, dependency control with wait: true, and end-to-end observability without custom glue code.
my_subflow in the same namespace that declares an output (for example my_output).This blueprint references no secrets. If your child flow connects to external systems, store credentials with {{ secret('NAME') }} rather than hardcoding them.
my_subflow in the company.team namespace that produces a typed output such as my_output.log task output to confirm the child's value was passed back.inputs to my_subflow and supplying them from the parent.ForEach loop over a list.wait: false for fire-and-forget child executions when you do not need the result.