Skip to content

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_PUSHBACK JSON payload, and the provided push-back inputs are injected as individual environment variables.
  • Lifecycle handlersonInit, onExit, onSuccess, onFailure, onAbort, and onWait handlers inherit the same variables. They additionally receive the DAG_RUN_STATUS so that post-run automation can branch on success or failure. The onWait handler receives DAG_WAITING_STEPS with step names waiting for approval.
  • Nested contexts – When a step launches a sub DAG through the dagu CLI, 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

VariableProvided InDescriptionExample
DAG_NAMEAll steps & handlersName of the DAG definition being executed.daily-backup
DAG_RUN_IDAll steps & handlersUnique identifier for the current run. Combines timestamp and a short suffix.20241012_040000_c1f4b2
DAG_RUN_LOG_FILEAll steps & handlersAbsolute path to the aggregated DAG run log. Useful for attaching to alerts./var/log/dagu/daily-backup/20241012_040000.log
DAG_RUN_STEP_NAMECurrent step or handler onlyName field of the step that is currently executing.upload-artifacts
DAG_RUN_STEP_STDOUT_FILECurrent step or handler onlyFile path backing the step's captured stdout stream./var/log/dagu/daily-backup/upload-artifacts.stdout.log
DAG_RUN_STEP_STDERR_FILECurrent step or handler onlyFile path backing the step's captured stderr stream./var/log/dagu/daily-backup/upload-artifacts.stderr.log
DAG_RUN_STATUSLifecycle handlers onlyCanonical status: running (init handler), succeeded, partially_succeeded, failed, rejected, aborted, or waiting (wait handler).failed
DAG_WAITING_STEPSWait handler onlyComma-separated list of step names currently waiting for human approval.approval-step,review-step
PWDCurrent step onlyWorking directory for the step. Defaults to DAG's working_dir or the DAG file's directory./home/user/project
DAG_RUN_WORK_DIRAll steps & handlersAbsolute 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_DIRAll steps & handlers when artifact storage is enabledAbsolute 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_DIRAll steps & handlersPer-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_JSONAll steps & handlersJSON 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_PUSHBACKSteps re-executed after approval push-back onlyJSON 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_PAYLOADWebhook-triggered runs onlyJSON 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.

yaml
# 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
yaml
# 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:
      - build

Artifacts Directory (DAG_RUN_ARTIFACTS_DIR)

DAG_RUN_ARTIFACTS_DIR is set only when the DAG enables artifact storage:

yaml
artifacts:
  enabled: true

The path uses the same per-run layout as log_dir:

text
<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_dir is 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:

yaml
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:

text
DAG_DOCS_DIR=<paths.docs_dir>/<dag name>

For a DAG with exactly one valid workspace=<name> label, Dagu sets:

text
DAG_DOCS_DIR=<paths.docs_dir>/<workspace>/<dag name>

For example, a DAG named daily-backup with workspace=ops gets:

text
/var/dagu/dags/docs/ops/daily-backup

Invalid 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.

yaml
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, or boolean types.
  • 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.
yaml
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:

json
{
  "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:

  • at is a server-generated UTC timestamp in RFC3339 format.
  • history is ordered oldest to newest.
  • If the current step declares approval.input, the inputs object 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:

yaml
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:
      - deploy

For complex payloads with nested structures:

yaml
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.

Released under the MIT License.