Special Environment Variables
Dagu injects a small set of read-only environment variables whenever it runs a workflow. These variables carry metadata about the current DAG run (name, run identifier, log locations, status) and are available for interpolation inside commands, arguments, lifecycle handlers, and most other places where you can reference environment variables.
Availability
- Step execution – Every step receives the run-level variables plus a step-specific name and log file paths while it executes.
- Push-back re-executions – Steps re-executed because of approval push-back also receive the
DAG_PUSHBACKJSON payload, and the provided push-back inputs are injected as individual environment variables. - Lifecycle handlers –
onInit,onExit,onSuccess,onFailure,onAbort, andonWaithandlers inherit the same variables. They additionally receive theDAG_RUN_STATUSso that post-run automation can branch on success or failure. TheonWaithandler receivesDAG_WAITING_STEPSwith step names waiting for approval. - Nested contexts – When a step launches a sub DAG through the
daguCLI, the sub run gets its own identifiers and log locations; the parent identifiers remain accessible in the parent process for chaining or notifications.
Values are refreshed for each step, so DAG_RUN_STEP_NAME, DAG_RUN_STEP_STDOUT_FILE, and DAG_RUN_STEP_STDERR_FILE always point at whichever step (or handler) is currently running.
Reference
| Variable | Provided In | Description | Example |
|---|---|---|---|
DAG_NAME | All steps & handlers | Name of the DAG definition being executed. | daily-backup |
DAG_RUN_ID | All steps & handlers | Unique identifier for the current run. Combines timestamp and a short suffix. | 20241012_040000_c1f4b2 |
DAG_RUN_LOG_FILE | All steps & handlers | Absolute path to the aggregated DAG run log. Useful for attaching to alerts. | /var/log/dagu/daily-backup/20241012_040000.log |
DAG_RUN_STEP_NAME | Current step or handler only | Name field of the step that is currently executing. | upload-artifacts |
DAG_RUN_STEP_STDOUT_FILE | Current step or handler only | File path backing the step's captured stdout stream. | /var/log/dagu/daily-backup/upload-artifacts.stdout.log |
DAG_RUN_STEP_STDERR_FILE | Current step or handler only | File path backing the step's captured stderr stream. | /var/log/dagu/daily-backup/upload-artifacts.stderr.log |
DAG_RUN_STATUS | Lifecycle handlers only | Canonical status: running (init handler), succeeded, partially_succeeded, failed, rejected, aborted, or waiting (wait handler). | failed |
DAG_WAITING_STEPS | Wait handler only | Comma-separated list of step names currently waiting for human approval. | approval-step,review-step |
PWD | Current step only | Working directory for the step. Defaults to DAG's working_dir or the DAG file's directory. | /home/user/project |
DAG_RUN_WORK_DIR | All steps & handlers | Absolute path to the per-DAG-run working directory. Each run gets its own isolated directory. In local mode, this is <dag-run-dir>/work/. In shared-nothing (distributed) mode, this is a temporary directory under the system temp dir. Not set during dry runs. | /data/dagu/dag-runs/daily-backup/dag-run_20241012_040000Z_c1f4b2/work |
DAG_RUN_ARTIFACTS_DIR | All steps & handlers when artifact storage is enabled | Absolute path to the per-DAG-run artifact directory, or a worker-local staging directory in shared-nothing mode. Not set when artifacts.enabled is not true. | /data/dagu/artifacts/daily-backup/dag-run_20241012_040000Z_c1f4b2 |
DAG_DOCS_DIR | All steps & handlers | Per-DAG docs directory path. Computed as <paths.docs_dir>/<dag name> for default DAGs, or <paths.docs_dir>/<workspace>/<dag name> when the DAG has one valid workspace=<name> label. Not set when paths.docs_dir resolves to empty. | /var/dagu/dags/docs/ops/daily-backup |
DAG_PARAMS_JSON | All steps & handlers | JSON string containing the resolved parameter map. Resolved DAG params are serialized as strings; if the run was started with raw JSON parameters, the original payload is preserved. Not set when the DAG has no resolved parameters. | {"ENVIRONMENT":"prod","batchSize":"1000"} |
DAG_PUSHBACK | Steps re-executed after approval push-back only | JSON string containing the current push-back iteration, latest inputs, authenticated actor, server timestamp, and chronological history. Not set on the initial execution. | {"iteration":2,"by":"reviewer","at":"2026-04-26T06:18:43Z","inputs":{"FEEDBACK":"Tighten summary"},"history":[...]} |
WEBHOOK_PAYLOAD | Webhook-triggered runs only | JSON string containing the payload from the webhook request body. Only available when the DAG was triggered via a webhook. | {"branch":"main","commit":"abc123"} |
Per-Run Work Directory (DAG_RUN_WORK_DIR)
Each DAG run gets an isolated work directory. The path is set in DAG_RUN_WORK_DIR and is available to all steps and handlers during the run.
Local mode: The directory is <dag-run-dir>/work/. It lives at the dag-run level (not the attempt level), so it persists across retries of the same run. It is cleaned up automatically when the dag-run is removed (e.g., by history retention).
Shared-nothing (distributed) mode: The directory is a temporary directory under the system temp dir (/tmp/dagu_<dag-name>_<run-id>). It is cleaned up when the agent process exits.
Dry runs: The variable is not set.
Sub-DAGs: Each sub-DAG is a separate dag-run with its own DAG_RUN_WORK_DIR.
The directory is created lazily — the env var is always set, but the directory itself is only created on disk when a step accesses it (e.g., via mkdir -p).
Default process working directory
When a DAG does not have an explicit working_dir in its YAML or base config, the process working directory (PWD) for each step defaults to DAG_RUN_WORK_DIR. This gives each run an isolated workspace without any configuration.
When working_dir is explicitly set (in the DAG YAML, base config, or via DefaultWorkingDir option), the explicit value is used as the process working directory. DAG_RUN_WORK_DIR is still available as an environment variable.
# No working_dir set — steps run in DAG_RUN_WORK_DIR by default
steps:
- id: write_scratch_file
command: |
# PWD is DAG_RUN_WORK_DIR (e.g., /data/dagu/dag-runs/my-dag/dag-run_.../work)
echo "intermediate data" > scratch.txt
- id: read_scratch_file
command: cat scratch.txt # finds the file — same PWD
depends:
- write_scratch_file# Explicit working_dir — PWD uses /app/project, but DAG_RUN_WORK_DIR is still available
working_dir: /app/project
steps:
- id: build
command: make build # PWD is /app/project
- id: save_artifact
command: cp build/output.tar.gz "${DAG_RUN_WORK_DIR}/output.tar.gz"
depends:
- buildArtifacts Directory (DAG_RUN_ARTIFACTS_DIR)
DAG_RUN_ARTIFACTS_DIR is set only when the DAG enables artifact storage:
artifacts:
enabled: trueThe path uses the same per-run layout as log_dir:
<base>/<safe dag name>/dag-run_<YYYYMMDD_HHMMSSZ>_<dag-run-id>/Base directory resolution:
- If the DAG sets
artifacts.dir, that value is used as<base>. - Otherwise Dagu uses
paths.artifact_dir. - If
paths.artifact_diris not configured explicitly, the default is<paths.data_dir>/artifacts.
Execution mode behavior:
- Local and shared-filesystem distributed execution use the final artifact directory directly.
- Shared-nothing distributed workers receive a temporary worker-local directory in
DAG_RUN_ARTIFACTS_DIR. Dagu uploads its contents to the coordinator when the attempt finishes.
Example:
artifacts:
enabled: true
steps:
- id: write-report
command: |
mkdir -p "${DAG_RUN_ARTIFACTS_DIR}/reports"
printf '# Report\n' > "${DAG_RUN_ARTIFACTS_DIR}/reports/summary.md"See Artifacts for the full configuration, API, and Web UI behavior.
Docs Directory (DAG_DOCS_DIR)
Dagu sets DAG_DOCS_DIR from paths.docs_dir. The paths.docs_dir configuration defaults to <paths.dags_dir>/docs (see Configuration Reference).
For a DAG with no valid workspace label, Dagu sets:
DAG_DOCS_DIR=<paths.docs_dir>/<dag name>For a DAG with exactly one valid workspace=<name> label, Dagu sets:
DAG_DOCS_DIR=<paths.docs_dir>/<workspace>/<dag name>For example, a DAG named daily-backup with workspace=ops gets:
/var/dagu/dags/docs/ops/daily-backupInvalid or conflicting workspace labels fall back to the default path, <paths.docs_dir>/<dag name>.
DAG_DOCS_DIR is not set when paths.docs_dir resolves to an empty string.
Markdown files written under DAG_DOCS_DIR appear in the web UI's Documents page automatically. Workspace-scoped files appear only when the matching workspace, or all, is selected.
labels:
- workspace=ops
steps:
- id: generate_report
command: |
mkdir -p "${DAG_DOCS_DIR}"
python generate_report.py > "${DAG_DOCS_DIR}/report.md"Parameter Payload (DAG_PARAMS_JSON)
DAG_PARAMS_JSON contains the resolved parameters serialized as JSON. It is not set when the DAG has no parameters and none were supplied at runtime.
- Defaults declared in the DAG plus CLI/API overrides are merged into a single JSON object.
- Resolved DAG params are serialized as strings, even when inline param definitions use
integer,number, orbooleantypes. - Raw JSON input may be an object or an array. For named params, prefer an object.
- When the run was started with raw JSON parameters (e.g.,
dagu start dag.yaml -- '{"foo":"bar"}'), the original JSON string is preserved verbatim.
steps:
- id: inspect_params
command: echo "Full payload: ${DAG_PARAMS_JSON}"
- id: read_environment
type: jq
with:
raw: true
script: ${DAG_PARAMS_JSON}
command: '"Environment: \(.ENVIRONMENT // "dev")"'Push-back Context (DAG_PUSHBACK)
DAG_PUSHBACK is set only when a step is executing as part of a push-back / rewind cycle for an approval step.
- It is not set on the first execution before any push-back happens.
- It is available to every step that was reset and later re-executed within the rewound scope.
- Dagu also injects the provided push-back keys as individual environment variables on those steps.
Example payload:
{
"iteration": 2,
"by": "reviewer",
"at": "2026-04-26T06:18:43Z",
"inputs": {
"FEEDBACK": "Tighten the executive summary",
"FORMAT": "markdown"
},
"history": [
{
"iteration": 1,
"by": "reviewer",
"at": "2026-04-26T06:12:10Z",
"inputs": {
"FEEDBACK": "Add error counts",
"FORMAT": "markdown"
}
},
{
"iteration": 2,
"by": "reviewer",
"at": "2026-04-26T06:18:43Z",
"inputs": {
"FEEDBACK": "Tighten the executive summary",
"FORMAT": "markdown"
}
}
]
}Notes:
atis a server-generated UTC timestamp in RFC3339 format.historyis ordered oldest to newest.- If the current step declares
approval.input, theinputsobject is filtered to that allowlist for that step. - If the current step does not declare
approval.input, all provided push-back keys are exposed on that step.
For approval semantics and examples, see Approval.
Webhook Payload
When a DAG is triggered via a webhook, the request payload is made available through the WEBHOOK_PAYLOAD environment variable. This allows your DAG steps to receive and process data from the triggering system.
Example Usage
Access payload fields directly using Dagu's JSON field access syntax:
name: webhook-triggered-dag
type: graph
steps:
- id: deploy
command: |
echo "Deploying branch ${WEBHOOK_PAYLOAD.branch}"
echo "Commit: ${WEBHOOK_PAYLOAD.commit}"
./scripts/deploy.sh
- id: notify
command: echo "Deployed by ${WEBHOOK_PAYLOAD.sender.login}"
depends:
- deployFor complex payloads with nested structures:
steps:
- id: process_github_push
command: |
echo "Repository: ${WEBHOOK_PAYLOAD.repository.full_name}"
echo "Pusher: ${WEBHOOK_PAYLOAD.pusher.name}"
echo "First commit message: ${WEBHOOK_PAYLOAD.commits.0.message}"Notes
- Dagu automatically parses the JSON payload and allows direct field access using dot notation.
- For arrays, use numeric indices (e.g.,
${WEBHOOK_PAYLOAD.commits.0}for the first element). - Maximum payload size is 1MB.
- The variable is empty when the DAG is triggered by other means (scheduler, API, CLI).
- Always validate the payload contents in your DAG before processing.
