Skip to main content
Every Aether execution begins with a Workflow document — a JSON (or struct) resource that declares what to run, in what order, with which parameters, and under what constraints. The document follows the aether/v1 protocol and is fully declarative: the engine interprets it without the caller writing any scheduling logic. Understanding the top-level shape of this document is the foundation for everything else in Aether.

Resource structure

A Workflow resource has four top-level fields:

Metadata

The Metadata struct holds identification and tagging information:

Naming rules (DNS-1123)

metadata.name, template names, DAG task names, and parameter names all follow the DNS-1123 label format, enforced by the validator:
  • Lowercase alphanumeric characters and hyphens only
  • Must start and end with an alphanumeric character
  • Maximum 63 characters
  • Pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
Dots (.) are reserved as the system namespace separator (e.g., loop_iter.index) and are not allowed in user-defined names.
If metadata.namespace is omitted, it defaults to "default" when FillDefaults is applied.

WorkflowSpec fields

1

entrypoint

Required. The name of the template to execute first. Must match the name field of exactly one template in spec.templates.
2

arguments

Workflow-level parameters declared here are available to all templates via workflow.arguments.parameters.<name> references. See Workflow-level arguments below.
3

timeout

Maximum wall-clock duration for the entire workflow (e.g., "30m", "2h"). Defaults to "1h" when omitted.
4

priority

Integer scheduling priority. Higher values are preferred when the broker has a queue. Defaults to 500.
5

maxNestedDepth

Cap on static template nesting depth (DAG-in-Loop-in-DAG, etc.). Defaults to 3. The absolute ceiling enforced by the engine is 10 — values above 10 are clamped down silently.
6

templates

Required. The flat list of all templates (DAG, Task, Loop) referenced anywhere in this workflow. See Templates for details.
7

hooks

Optional lifecycle hook handlers at the workflow level. Hook templates must be Task templates (not DAG or Loop). Available hooks: onStart, onSuccess, onFailure, onError, onCancel, onExit.

Workflow-level arguments

spec.arguments declares parameters that act as workflow-wide inputs. They are injected into the binding environment under the key workflow.parameters.<name> (the workflow.arguments.parameters.<name> form is a supported alias, normalized internally):
Parameters support the full Parameter type, including type, value, default, enum, and valueFrom. See Parameter Binding for how values flow from here into templates.

Complete minimal workflow example

The following is a real, runnable example from the playground (01-single-task.json):

Validation rules

The engine validates every submitted workflow before execution begins. Key rules from internal/validate.go:

Required fields

apiVersion must be "aether/v1". kind must be "Workflow" or "CronWorkflow". metadata.name and spec.entrypoint are both required.

Entrypoint resolution

The value of spec.entrypoint must match the name of exactly one template in spec.templates. An unknown entrypoint is rejected at submission time.

Template union constraint

Each template must have exactly one of dag, task, or loop set. Zero or two-or-more is a validation error.

DAG integrity

DAG tasks must be non-empty. Task names must be unique within a DAG. Dependencies must reference known tasks. Cycles are detected and rejected.

Hook templates

Hook template references must point to Task templates only. DAG and Loop templates are not permitted as hooks.

Nesting depth

Static template nesting (resolved from the entrypoint) must not exceed spec.maxNestedDepth (default 3, max 10).
Validation is performed by internal.Validate() and internal.FillDefaults() in sequence. FillDefaults runs first, so omitted timeout, priority, and maxNestedDepth fields receive their defaults before validation checks them.

CronWorkflow

CronWorkflow is the scheduled variant of Workflow. It wraps a full WorkflowSpec inside a CronWorkflowSpec, adding scheduling fields:
Key scheduling fields:
  • schedule: Required. A 5-field cron expression ("0 9 * * 1-5") or a macro (@hourly, @daily, @weekly, @monthly, @yearly).
  • timezone: IANA timezone name (e.g., "America/New_York"). Defaults to "UTC".
  • startAt / endAt: Optional RFC3339 timestamps bounding the active scheduling window.
  • concurrencyPolicy: Allow (default), Forbid, or Replace — controls what happens when a new trigger fires while a previous run is still active.
  • suspend: Set to true to pause scheduling without deleting the resource.
For a complete guide to scheduling and concurrency policies, see the CronWorkflow guide.