Skip to content

Outputs ​

Use step outputs when one step needs to pass a validated value or a materialized file path to a later step.

The current validated reference form is:

text
${steps.<step_id>.outputs.<output_name>}

For value outputs from command steps, the producer must have an id, declare each output name in outputs, and write the value to DAGU_OUTPUT_FILE. Built-in actions can provide their own output contract. For example, a human task derives outputs from its form properties and publishes the validated operator input without an authored outputs field or DAGU_OUTPUT_FILE, and a decision step publishes its answers the same way.

A build workflow can instead declare path on an output. The command writes the file to ${outputs.<name>}, and dependent steps receive its final absolute path through ${steps.<id>.outputs.<name>}. Path outputs are not written to DAGU_OUTPUT_FILE.

Basic Example ​

yaml
steps:
  - id: get_version
    run: |
      printf 'version=%s\n' "$(cat VERSION)" >> "$DAGU_OUTPUT_FILE"
    outputs:
      - name: version

  - id: build_image
    depends: get_version
    run: docker build -t "myapp:${steps.get_version.outputs.version}" .

This is more explicit than a bare ${VERSION} reference:

  • get_version declares that it publishes version
  • build_image declares the dependency that makes the output available
  • Dagu can report a passive notice if the step id, output name, or dependency is wrong

Human-task outputs use the same ${steps.<step_id>.outputs.<output_name>} reference and dependency rules. See Human Tasks for the generated-output behavior.

Output File Format ​

For each step attempt, Dagu creates an output file and exposes its path as DAGU_OUTPUT_FILE.

Write single-line values as name=value:

yaml
steps:
  - id: inspect_build
    run: |
      printf 'version=v1.2.3\n' >> "$DAGU_OUTPUT_FILE"
      printf 'artifact_url=https://example.test/app.tgz\n' >> "$DAGU_OUTPUT_FILE"
    outputs:
      - name: version
      - name: artifact_url

Write multi-line values with a delimiter:

yaml
steps:
  - id: summarize
    run: |
      {
        printf 'report<<REPORT\n'
        ./generate-report --format markdown
        printf '\nREPORT\n'
      } >> "$DAGU_OUTPUT_FILE"
    outputs:
      - name: report

Rules:

  • Every declared output must be written exactly once.
  • Written output names must be declared.
  • Duplicate output names fail the step attempt.
  • Failed, aborted, timed-out, skipped, and not-yet-completed steps publish no outputs.

JSON Outputs ​

Declare type: json when the output value must be valid JSON.

yaml
steps:
  - id: inspect
    run: |
      cat >> "$DAGU_OUTPUT_FILE" <<'EOF'
      metadata<<JSON
      {"image":"api","tag":"v1.2.3"}
      JSON
      EOF
    outputs:
      - name: metadata
        type: json

  - id: print_metadata
    depends: inspect
    env:
      - METADATA: ${steps.inspect.outputs.metadata}
    run: printf '%s\n' "$METADATA"

Step output references read top-level declared output names. Nested output paths such as ${steps.inspect.outputs.metadata.tag} are not part of the strict reference syntax.

The separate ${<step_id>.output.<path>} form reads into a step's captured JSON output and does accept a path, which is how a decision step exposes ${classify.output.answers.department.choice}. It resolves against captured output rather than a declared output name, so the two forms are not interchangeable.

The matching ${<step_id>.outputs<path>} form reads into the payload a step published on its outputs channel, which need not be an object. A parallel step publishes an array there, so ${fanout.outputs} is the whole array and ${fanout.outputs[0].NAME} is one entry's value. Array indexes are valid in both path forms.

Dependencies ​

A step output reference makes the consuming step depend on the producing step. An explicit depends entry is optional.

yaml
steps:
  - id: build
    run: |
      printf 'image=registry.example.com/app:v1.2.3\n' >> "$DAGU_OUTPUT_FILE"
    outputs:
      - name: image

  - id: deploy
    run: ./deploy.sh "${steps.build.outputs.image}"

deploy runs after build and the reference resolves. dagu validate reports the edge as inferred: build -> deploy (steps[1].run), the API lists it in the step's inferredDepends field, and the UI graph draws it with a dashed line.

Rules:

  • Inferred dependencies are unioned with depends. An empty depends: [] does not suppress them.
  • A reference inside a foreach body makes the owning foreach step depend on the producer.
  • Lifecycle handlers under handler_on create no dependency. Neither do escaped references such as \${steps.build.outputs.image} or references in a template.render template body.
  • Two steps that reference each other's outputs, or a reference to a later step in a type: chain DAG, form a cycle and the DAG fails to load.
  • Inferred dependencies only order execution. Behavior that depends enables beyond ordering, such as chat history inheritance between LLM steps, still needs an explicit depends entry.

Running One Step ​

dagu start --only deploy runs deploy without the steps before it; they are recorded as skipped. The outputs deploy reads then come from one of two places:

bash
# Reuse the outputs a finished run recorded
dagu start --only deploy --outputs-from 20260925_101500 pipeline.yaml

# Supply the value yourself
dagu start --only deploy --output build.image=registry.example.com/app:dev pipeline.yaml
  • --outputs-from carries the outputs of steps that succeeded in that run, and copies its work directory.
  • --output <step>.<name>=<value> sets one output of a skipped step, and wins over --outputs-from. The name must be declared by the step's outputs unless the step declares none, and a type: json output needs valid JSON. The step needs an id, since references address steps by ID.
  • With neither, ${steps.build.outputs.image} stays unresolved, as for any output that was never published.

The REST API takes the same selection as steps, outputsFromRunId, and outputs; see Start DAG.

Output Names ​

Output names must match:

text
^[A-Za-z][A-Za-z0-9_]*$

Use names such as version, image_tag, artifact_url, or record_count.

Path Outputs ​

Path-backed outputs are available only in type: build workflows:

yaml
type: build
working_dir: /srv/build

steps:
  - id: compile
    inputs:
      - name: source
        path: source.txt
    outputs:
      - name: artifact
        path: artifact.bin
    run: compiler "${inputs.source}" -o "${outputs.artifact}"

path and type are mutually exclusive on one output declaration. An eligible reusable step declares exactly one output and that output is path-backed. See Build Workflows for dependency inference, staging, reuse, and eligibility rules.

Large Results ​

Do not use step outputs for large reports, logs, media files, or full datasets. Write those to an artifact instead and publish only the small path or summary that later steps need.

yaml
steps:
  - id: report
    run: ./generate-report --format markdown
    stdout:
      artifact: reports/report.md

See Artifacts for run artifact storage.

Dagu is open source under the GNU General Public License v3.0.