Flows#
A flow chains steps into one durable piece of work: an agent reviews a pull request, a second agent looks for security problems, a person approves, a run merges. Each time a flow runs is an execution. This page explains steps, what passes between them, and what makes an execution durable.

Steps#
| Kind | Does | Done when |
|---|---|---|
agent |
Runs an agent (its current version, or one named) with an input. Budgets, guardrails, approvals of its tool calls and receipts apply as to any run of the agent. | The run ends. Its answer is written to /flow/<step>/answer.md. |
run |
Runs any container: one worker of a template (image, command, arguments, environment, resources…). | The run ends. |
approval |
Asks named people (an approval of kind flow step). | Someone approves. Denied, or not decided within wait_seconds (a day by default, at most 7), it fails. |
wait_event |
Waits for an event sent to the execution (by the console, astra or the API). |
The event arrives; its data are the step's outputs. One sent before the step waits counts. |
sleep |
Waits (1 second to 7 days). | The time has passed. |
flow |
Runs another flow as a child execution, at most three flows deep. | The child ends; its outputs are the step's. |
Every step may have:
needs: the steps that must be done first. Steps that need nothing of each other run at the same time; the graph has no cycles.when: a condition; when it does not hold, the step is Skipped. A step skipped for its condition counts as done for the steps that need it (a branch not taken); a step skipped because something it needed failed passes that on, and they are skipped too.retry:{max, backoff_seconds}— new attempts after a failure (2 by default, at most 10; back-off at most a day). Agents, runs and child flows are retried; an approval or an event is asked again only when a person retries the step.repeat:{until, max}— run the step again, as new attempts, until a condition holds (at most 20 times).timeout_seconds: one attempt's limit (1 second to 30 days).
A flow has at most 64 steps, its inputs, its outputs (expressions
computed when it ends), a timeout_seconds for the whole execution (a
minute to 30 days) and on_failure: stop (the default: a failed step
fails the execution and steps under way are cancelled) or continue (steps
that do not depend on it go on; the execution fails at the end).
What passes between steps#
Outputs are small and explicit. A step's outputs are what its run
writes to the file $ASTRAEUS_OUTPUTS, one key=value per line — as a
GitHub Actions step writes $GITHUB_OUTPUT. Keys are lowercase letters,
digits and _; all of a step's outputs together at most 4 KiB. They are
what expressions read, and the only data of a step that reaches Astralyx.
Files go on the drive. Each execution has a drive mounted read-write
at /flow in every step; an agent's file tools reach it too. Name a
shared drive of the workspace in the flow's drive and each execution
gets its own folder of it — every step, on any machine, sees what earlier
steps wrote. Without one, each execution gets a drive of its own, deleted
with the execution, which is a copy per machine: steps on different
machines do not see each other's files. Use a shared drive when steps pass
files.
Expressions are a small, safe language: inputs.<name>,
steps.<id>.outputs.<key>, steps.<id>.state, execution.name; literals;
== != < <= > >= && || !; and contains(a, b). Text fields (an agent's
input, an approval's target, a run's command, arguments and
environment, a child's inputs) are templates: each ${{ … }} is replaced.
A step may read only steps it depends on. See
Flow specification.
Durable#
- A machine going away loses nothing. Each step's state is kept by the cluster, not by a process. A step whose machine is lost gets a new attempt elsewhere; steps already finished never run again.
- Nothing runs twice by accident. Every run, approval or child an attempt makes is named after the execution, the step and the attempt, so a restart finds it instead of making another.
- Versions. Each change writes a new, immutable version; an execution keeps the version it started with, and the flow's current version runs by default.
An execution is Pending, Running, Waiting (only on people or
events), Succeeded, Failed or Cancelled. Its page draws the graph
live, with each step's attempts, their runs and approvals, the receipts of
its agent runs, its outputs and the events it received.
Three ways to write one#
- The console's editor draws the graph: add steps, connect them, fill in each; the same flow is shown as YAML.
- YAML applied with
astra anemoi flows apply -f. - Python, with the
astralyx.anemoiSDK.
See Build and run a flow.