Writing Workflows
A Dagu workflow is a YAML file with a steps list. Start with a command you already run, then add dependencies and operational behavior only when the workflow needs them.
Start with one command
Save this as hello.yaml:
steps:
- run: echo "Hello from Dagu"Run it:
dagu start hello.yamlThat is a complete workflow. A name, schedule, queue, parameter block, and runner configuration are not required.
An id is optional for an isolated step. Add one when another step needs to depend on it or reference its output:
steps:
- id: hello
run: echo "Hello from Dagu"
- run: echo "Finished"
depends: helloAdd dependencies to build a DAG
Each step's depends field lists the steps that must succeed first. Dagu starts every step whose dependencies are ready.
steps:
- id: fetch
run: ./fetch.sh
- id: clean
run: ./clean.sh
depends: fetch
- id: analyze
run: ./analyze.sh
depends: fetch
- id: report
run: ./report.sh
depends: [clean, analyze]The run proceeds in three stages:
fetchruns first.cleanandanalyzebecome ready together, so they run in parallel.reportwaits for both branches.
There is no separate parallel-execution configuration. Parallelism follows directly from the graph.
Validate, preview, and inspect runs
Use the CLI while developing a workflow:
dagu validate pipeline.yaml # Check the YAML
dagu dry pipeline.yaml # Show the execution plan
dagu start pipeline.yaml # Run it now
dagu history pipeline # List recent runsStart the server to inspect the same workflows in the Web UI:
dagu start-all --dags .Open http://localhost:8080 to see the graph, live step status, logs, run history, and controls for starting, stopping, and retrying runs.
Add operational behavior when needed
Top-level fields configure the workflow as a whole. Fields inside a step configure that command.
Schedule it and retry failures
schedule: "0 2 * * *"
steps:
- run: ./nightly-sync.sh
retry_policy:
limit: 3
interval_sec: 30The scheduler starts this workflow every day at 02:00. A failed command is retried up to three times with 30 seconds between attempts. See Scheduling and Durable Execution.
Accept parameters
params:
- ENVIRONMENT: staging
steps:
- run: ./deploy.sh "${params.ENVIRONMENT}"Override the value when starting the workflow:
dagu start deploy.yaml -- ENVIRONMENT=productionParameters can also be typed and validated before a run starts. See Parameters.
Run the workflow in a shared container
container:
image: python:3.13
steps:
- run: python report.pyAll steps share one workflow container and its filesystem. See Container.
Use built-in actions
run executes a command through a shell. For operations with structured inputs, set action and pass its configuration under with. Actions use the same dependencies, retries, conditions, status tracking, and logs as command steps.
Run one step in Docker
Use docker.run when a step needs its own container:
steps:
- id: container_job
action: docker.run
with:
image: alpine:3
auto_remove: true
command: echo "Hello from Docker"The container is separate from containers used by other steps. See Docker.
Run a command over SSH
steps:
- id: check_server
action: ssh.run
with:
user: deploy
host: app.example.com
command: uptimeDagu captures the remote command's status, stdout, and stderr as a normal step result. See SSH.
Route to selected steps
router.route provides switch-style branching. Target steps implicitly depend on the router; steps in unselected routes are skipped.
type: graph
params:
- TARGET: staging
steps:
- id: choose_target
action: router.route
with:
value: ${params.TARGET}
routes:
staging: [deploy_staging]
production: [deploy_production]
- id: deploy_staging
run: ./deploy.sh staging
- id: deploy_production
run: ./deploy.sh productionExact values and re: regular-expression patterns can each select one or more target steps. See Router.
Run a coding agent
harness.run launches an external coding-agent CLI as a workflow step:
steps:
- id: review
action: harness.run
with:
provider: codex
prompt: Review the current branch and report correctness risksThe provider CLI must be installed and authenticated on the worker, or supplied through a containerized harness. See Harness and Sandboxed Execution.
Wait for a person
steps:
- id: confirm
action: human.task
with:
prompt: Deploy to production?
- id: deploy
run: ./deploy.sh
depends: confirmThe run enters Waiting at confirm and releases its worker slot. Complete the task from the Web UI, REST API, or CLI to resume the same run. See Human Tasks.
Other built-in actions cover HTTP requests, SQL, Kubernetes jobs, S3, Git, files, archives, templates, and persistent state.
Find the next topic
| When you want to… | Read |
|---|---|
| Learn step fields, scripts, dependencies, and defaults | Workflow Basics |
| Pass parameters, outputs, and files between steps | Data & Variables |
| Add conditions, loops, parallel iteration, or sub-DAGs | Control Flow |
| Configure retries, timeouts, handlers, and failure behavior | Durable Execution and Error Handling |
| Run HTTP, SQL, SSH, Docker, Kubernetes, or other actions | Built-in Actions |
| Start from copyable workflows | Examples |
| Look up every supported field | YAML Specification |

