Outputs
Capture small step results, publish structured values, and collect final run outputs.
Overview
Dagu supports two output: modes:
- String form captures a step's trimmed stdout into one variable such as
${VERSION}. - Object form publishes structured step-scoped output for
${step_id.output.*}references.
These modes solve different problems:
- Use string form when you want a flat variable and a final
outputs.jsonentry. - Use object form when you want structured downstream data without brittle
echoglue.
String Form
Capture stdout into a variable and include it in the DAG run's outputs.json:
steps:
- id: get_version
command: cat VERSION
output: VERSION
- id: build_image
command: docker build -t myapp:${VERSION} .The captured stdout is trimmed and becomes:
${VERSION}for downstream steps${get_version.output}for step-ID referencesversioninoutputs.json
The dollar prefix is optional:
output: $VERSIONObject Form
Object form publishes structured step output instead of a flat variable:
steps:
- id: inspect_build
script: |
printf '{"version":"v1.2.3","artifact":{"url":"https://example.test/app.tgz"}}'
output:
version:
from: stdout
decode: json
select: .version
artifact:
from: stdout
decode: json
select: .artifact
- id: deploy
depends: [inspect_build]
command: |
echo "Deploying ${inspect_build.output.version}"
echo "Artifact: ${inspect_build.output.artifact.url}"Entry Forms
Literal value
output:
versionLabel: "ver - ${build.output.version}"
meta:
env: stg
approved: trueString leaves are expanded with normal ${...} references. Backtick command substitution and shell expansion are not run in object-form output values.
Plain objects stay literal unless they use one of the reserved long-form keys: value, from, path, decode, or select. If you need a literal object containing one of those keys, wrap it with value:.
Source-backed value
output:
version:
from: stdout
decode: json
select: .version
warning:
from: stderr
decode: json
select: .warning
reportPath:
from: file
path: build/report.json
decode: json
select: .pathSupported Fields
| Field | Description |
|---|---|
value | Literal scalar, array, or object value to publish |
from | Runtime source: stdout, stderr, or file |
path | File path used when from: file |
decode | text, json, or yaml |
select | jq-style path applied after decode: json or decode: yaml |
value cannot be combined with from, path, decode, or select.
Publish-Only Steps
If a step only has object-form output: and no executor fields, Dagu treats it as a publish-only step:
steps:
- id: publish
output:
version: "${build.output.version}"
versionLabel: "ver - ${build.output.version}"This is useful for reshaping or renaming values without a fake echo step.
Step References
Step IDs expose several properties:
${id.stdout}- path to the stdout log file${id.stderr}- path to the stderr log file${id.exit_code}- exit code as a string${id.output}- captured string output or the full object-form payload as compact JSON
Nested access works when the output value is structured JSON:
steps:
- id: build
command: echo '{"version":"v1.2.3"}'
output: BUILD_JSON
- command: echo "Version: ${build.output.version}"For object-form output, nested access is the primary pattern:
${inspect_build.output.version}
${inspect_build.output.artifact.url}Substring slicing still works on the final string value:
${build.output:0:5}
${id.stdout}and${id.stderr}are file paths, not file content. Usecat ${id.stdout}to read the content.
Run Output Collection
When a DAG run completes, Dagu writes collected outputs to outputs.json for the Web UI and Outputs API.
Only string-form output: NAME participates in outputs.json today.
Example:
steps:
- id: build
command: cat VERSION
output: BUILD_VERSION
- id: test
command: pytest --collect-only -q | tail -1
output: TEST_COUNT
depends: [build]Result:
{
"outputs": {
"buildVersion": "1.2.3",
"testCount": "42 tests"
}
}Keys are converted from SCREAMING_SNAKE_CASE to camelCase.
If multiple steps write the same output variable name, the last collected value wins.
Web UI and API
The Web UI Outputs tab and the REST outputs endpoint read from outputs.json:
GET /api/v1/dag-runs/{name}/{dagRunId}/outputsExample response:
{
"metadata": {
"dagName": "my-workflow",
"dagRunId": "abc123",
"attemptId": "attempt_001",
"status": "succeeded",
"completedAt": "2024-01-15T10:30:00Z",
"params": "{\"env\":\"prod\"}"
},
"outputs": {
"version": "1.2.3",
"recordCount": "1000"
}
}Use latest as the run ID to fetch the most recent run's outputs.
Size Limits and Safety
- Captured stdout is limited by
max_output_size(default 1MB). - Object-form
from: stdout,from: stderr, andfrom: fileuse the same limit. - For large or untrusted data, write to a file and pass the path downstream instead of capturing the content.
If you need secrets, use Secrets and avoid printing them to stdout.
Related Documentation
- Data Flow - Data passing patterns
- Variables Reference -
${...}syntax and step references - YAML Specification - Full field reference
- API Reference - Outputs endpoint
