A DAG (directed acyclic graph) template is the primary composition primitive in Aether. Every task node in a DAG declares which other nodes it depends on, and the engine uses those edges to determine what can run concurrently and what must wait. Because edges only flow forward and no cycles are allowed, the engine can always make progress: when a task finishes, it inspects all tasks whoseDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/BabySid/aether/llms.txt
Use this file to discover all available pages before exploring further.
dependencies list is now fully satisfied and dispatches them immediately. This means you never write explicit sequencing logic — you express intent through the graph, and the scheduler does the rest.
Anatomy of a DAG Template
A DAG is declared inside atemplates entry with the dag key. The required fields are name and tasks; everything else is optional.
tasks is a call site — it references a named template and optionally supplies arguments, dependency edges, a when guard, retry policy, timeout, and hooks.
Field reference
| Field | Type | Description |
|---|---|---|
name | string | DAG-local node name. DNS-1123 label (max 63 chars). |
tasks | Task[] | Ordered list of task nodes. |
inputs | Inputs | Parameters this DAG accepts when called as a sub-DAG. |
outputs | Outputs | Parameters exported by this DAG (use valueFrom). |
entrypoints | string | string[] | Restrict execution to a subgraph rooted at these nodes. |
continueOn | ContinueOn | Whether to keep running past task failures at the DAG level. |
timeout | string | Duration string for the entire DAG (e.g. "30m"). |
Linear Chains (A → B → C)
The simplest topology is a sequential chain where each task declares the previous one independencies.
arguments[].valueFrom. The expression tasks.<node-name>.outputs.parameters.<param> references the named output of a completed upstream task. Tasks cannot access sibling state directly — all data flow must be declared explicitly through arguments.
Parallel Fan-Out and Joins
Omittingdependencies (or listing no common predecessor) causes tasks to start immediately and run concurrently. A downstream join node lists both parallel branches in its dependencies array and waits for all of them.
task-a and task-b dispatch simultaneously. The engine holds join in PhaseCreated until both predecessors are in a terminal state, then dispatches it with the merged arguments.
Diamond Patterns
A diamond graph — one source, two branches, one sink — combines fan-out and fan-in in a single DAG:left and right receive start’s seed output, execute concurrently, and both must complete before join is dispatched.
DAG-Level Inputs and Outputs
A DAG template can declare its owninputs and outputs, making it reusable as a sub-DAG callable from an outer DAG with arguments.
Inside the inner DAG, reference its own inputs with inputs.parameters.<name>. The outputs valueFrom expression must point to a task inside that DAG — the outer DAG then references the sub-DAG’s outputs with tasks.<sub-dag-node>.outputs.parameters.<name>.
Named Entrypoints
Theentrypoints field restricts execution to the subgraph reachable from the named starting nodes. Tasks not reachable from any listed entrypoint are never created.
entrypoints: ["task-a"], only task-a and task-b execute. task-c and task-d are excluded because they are not reachable from task-a.
Failure Propagation with continueOn
By default, if a task fails the DAG stops scheduling new tasks and transitions to a failed state. The continueOn field overrides this at two levels.
- Task-level continueOn
- DAG-level continueOn
Apply
continueOn to a specific task node so that its downstream dependents can still be dispatched even if that node fails:step-b fails, but because it declares continueOn: {failed: true}, step-c is still dispatched. The DAG itself also needs continueOn: {failed: true} to prevent the container from marking itself failed while children are still succeeding.continueOn does not mask the failing task’s own phase — step-b in the example above still records PhaseFailed. It only controls whether the failure blocks downstream scheduling and whether the DAG container itself treats the failure as terminal.Nested DAGs
A DAG task node can reference another DAG template by name. The engine creates a child scope for the inner DAG, runs it to completion, then propagates its outputs to the outer DAG.inner-dag) runs as its own scope with its own tasks. When it completes, tasks.sub.outputs.parameters.result resolves to the inner DAG’s declared output. Nesting is bounded by spec.maxNestedDepth (default 3, max 10).
Topology Design Tips
Prefer fine-grained tasks for maximum parallelism
Prefer fine-grained tasks for maximum parallelism
Each task node is an independent unit of work. Tasks with no shared dependencies run concurrently. Break monolithic tasks into smaller pieces wherever possible to take advantage of the scheduler’s parallel dispatch.
Make data flow explicit in arguments
Make data flow explicit in arguments
Tasks cannot read sibling outputs directly. All cross-task data must pass through
arguments[].valueFrom at the call site. This is intentional — it makes data flow visible in the workflow document and eliminates hidden coupling.Use sub-DAGs to encapsulate reusable logic
Use sub-DAGs to encapsulate reusable logic
A multi-step process (fetch → validate → transform) can be wrapped in a named DAG template and called from multiple parent DAGs. Each call site creates its own independent scope, so runs are fully isolated.
Combine entrypoints with continueOn for partial execution
Combine entrypoints with continueOn for partial execution
Use
entrypoints to scope execution to a subgraph, and continueOn to keep the DAG healthy when non-critical branches fail. This combination supports partial pipeline patterns where the important path must always complete regardless of auxiliary step outcomes.