Blog · Guide · 29 October 2026
AEGIS workflow states and transitions, step by step
Disclosure: 100monkeys.ai builds AEGIS, so read this guide as a maker's account. It was drafted by one of our AI agents from the public AEGIS documentation, chiefly the Workflow Manifest Reference and the CLI Reference, and reviewed by the company. Every YAML line and command below is copied from those pages; none was run for this guide. Where the docs leave a question open, the last section says so.
AEGIS by 100monkeys.ai, in beta, runs a workflow as a finite state machine written in one YAML file. The reference calls it "a durable, restartable sequence" that coordinates agents, containers, system commands and human approval gates. This guide writes one state at a time and shows how the engine chooses the next.
Step 1. Write the header
apiVersion: 100monkeys.ai/v1
kind: Workflow
metadata:
name: dev-pipeline
version: "1.0.0"
apiVersion must be exactly 100monkeys.ai/v1 and kind exactly Workflow. name follows ^[a-z0-9][a-z0-9-]{0,62}$, and the pair of name and version must be unique: overwriting an existing version needs the force parameter. metadata.input_schema is optional; when it is present, the caller's input is validated before the run starts, and a payload that fails is "rejected with HTTP 422; no workflow execution is created."
Step 2. Name the first state and the limits
Under spec, initial_state is required and must exist in spec.states. Two limits stop a loop that never ends. spec.max_total_transitions defaults to 50, with a ceiling of 100, after which "the workflow terminates". Each state's max_state_visits defaults to 5, with a ceiling of 20. Each state also has a timeout, 300s by default. spec.context holds constants every state reads as {{workflow.context.KEY}}, such as an iteration limit or a threshold.
Step 3. Pick a kind for each state
Every state names a kind. The reference lists eight:
Agentruns a deployed agent and writes itsstatus,output,scoreanditerationsunder the state's name.Systemruns a shellcommandand recordsstdout,stderrandexit_code.Actionruns one of the workflow's own operations, such asupdate_blackboardorrepository_commit: "no agent chooses or calls it, and no shell runs."Humansuspends the run until a person answers.ParallelAgentsruns several judges and combines their scores by a consensus strategy.ContainerRunandParallelContainerRunrun container steps, for CI and CD work.Subworkflowstarts another workflow, blocking or fire-and-forget, to a depth of at most 10.
Step 4. Write transitions in the order you want them tried
Transitions are "evaluated top-to-bottom. The first matching transition is taken." Each one names a target state and, optionally, a condition. This System state from the reference's own example branches on the exit code:
EXECUTE:
kind: System
command: python main.py
env:
CODE: "{{GENERATE.output}}"
PYTHONPATH: /workspace
transitions:
- condition: exit_code_zero
target: VALIDATE
- condition: exit_code_non_zero
target: REFINE
feedback: "Execution failed: {{EXECUTE.output.stderr}}"
The conditions each kind can use: on_success and on_failure for most kinds; exit_code_zero, exit_code_non_zero and exit_code with a value for System and ContainerRun; input_equals, input_equals_yes and input_equals_no for Human; consensus, all_approved and any_rejected for ParallelAgents; custom with a Handlebars expression for any kind; and always, or no condition at all, as the unconditional fallback. The reference's advice: "Always include an unconditional fallback as the last transition."
Step 5. Branch on a score
VALIDATE:
kind: Agent
agent: judge-v1
transitions:
- condition: score_above
threshold: 0.95
target: COMPLETE
- condition: score_below
threshold: 0.95
target: REFINE
feedback: "{{VALIDATE.output.reasoning}}"
Both comparisons are strict, so a score of exactly 0.95 takes neither transition above. The score is read from the state's score, else final_score, else consensus.score. A state that carries no score matches neither, and if nothing else matches the run fails with State "<name>" carries no score for its score transitions. score_between takes inclusive min and max for an Agent state.
Step 6. Carry what happened into the next state
A transition's feedback string becomes {{state.feedback}} in the state it leads to, which is how a failure message reaches the agent that retries. Each finished state is written to the Blackboard under its name, so later states read {{EXECUTE.output.stdout}} or {{VALIDATE.score}}. Keep two namespaces apart: {{input.KEY}} is what the caller passed and "is immutable", while {{blackboard.KEY}} grows as the run goes. A template that names a key no state has written yet renders a visible placeholder, ERROR: missing key with the state's name, rather than an empty string.
Step 7. Loop with a guard, and end the run
REFINE:
kind: System
command: update_context
env:
ITERATION: "{{blackboard.iteration_number + 1}}"
ERRORS: "{{state.feedback}}"
transitions:
- condition: custom
expression: "{{blackboard.iteration_number < workflow.context.max_iterations}}"
target: GENERATE
- condition: custom
expression: "{{blackboard.iteration_number >= workflow.context.max_iterations}}"
target: FAILED
COMPLETE:
kind: System
command: finalize
transitions: []
A state with transitions: [] is terminal: "When reached, the workflow execution completes with status completed." Give the loop its own guard on the Blackboard, as above, as well as relying on max_state_visits.
Step 8. Validate, deploy, run and watch the transitions
aegis workflow validate ./pipeline.yaml
aegis workflow deploy ./pipeline.yaml
aegis workflow run dev-pipeline --input '{"task": "..."}'
aegis workflow logs <execution_id> --transitions
validate checks the manifest locally; deploy registers it and fails on an existing name and version unless you add --force; logs --transitions shows "state entries/exits only", which is the quickest way to see which branch each state took.
What the docs leave open
- Gate words. The Workflow Manifest Reference has
input_equals_yesaccept "yes", "approve", "approved" or "true"; the Human Approvals page saysyes,yor1. Test your gate before you rely on either list. - A second syntax. The Blackboard example on the same page writes
kind: agent,input_templateand transitions ason: successwithnext:, where the rest of the reference writeskind: Agent,input,conditionandtarget. The page does not say whether the engine accepts both. - Arithmetic in templates. The example sets
{{blackboard.iteration_number + 1}}, but the operators listed for expressions are comparisons and logic only, with no+. - No match. Apart from the score case, the reference does not say what happens when a state finishes and none of its transitions matches.
- How many kinds. The docs index describes "all seven state kinds"; the reference's table lists eight.
Next
For the Human state in depth, with what the reviewer sees and what silence means, read How to give an orchestrator an approval step. AEGIS installs with the command printed on 100monkeys.ai:
curl -fsSL https://get.100monkeys.ai | bash