AOT for hmz: the flow that writes a flow - a description in, a loaded, smoke-run and reviewed flow out.
Describe a flow, and get one you can run. A writer drafts it; hmz
loads the draft and runs it on fake agents; a critic reads it fresh. Only a draft that passes
all three lands among this project's own flows, the local flowverse.
You need hmz. In hmz, open /flow, go to
Flowverses → official → aot and Install it.
To run a release without installing it, name it by its git ref:
hmz exec -f git+https://github.com/humanfia/aot-flow@v0.2.0#aot ...❯ $aot two agents take turns until a reviewer says it is done
hmz exec -f aot -a writer=claude/claude-opus-5:high -a critic=codex/gpt-5.6-sol:high \
-p budget.cost=10 "two agents take turns until a reviewer says it is done"When it lands, it prints what the new flow drives, takes and ends on, and the line that runs it:
compiled: turn_taking_review -- two agents take turns until a reviewer approves
landed: .hmz/flows/turn_taking_review
drives: worker -- an agent
drives: reviewer -- an agent
ends: by verdict -- reviewer says done, within 6 rounds
hmz exec -f local/turn_taking_review -a worker=CLI/MODEL:EFFORT -a reviewer=CLI/MODEL:EFFORT -p budget.cost=USD "the task"
At the prompt, the new flow is $local/turn_taking_review.
- A spec first. The writer draws up the roles the flow drives, what each must be able to do, its params and what ends it. A capability no backend serves is sent back to be restated, then put to you. A name that is already taken is put to you too.
- It loads. hmz loads the draft and reads back what it declares.
- It ends on its own. The draft runs on fake agents in three worlds: an agent that never
says it is done, one that says so at once, and one that answers nothing. It must end in
every one within
seconds. - A critic approves it. A fresh session that may only read, and never saw it written.
A refusal at any step goes back to the writer word for word, for up to repairs rounds.
| Role | |
|---|---|
writer |
Draws the spec, then drafts and repairs the flow, in one session. |
critic |
Reads each draft that passed the gates, in a fresh session. It may only read. |
human |
You, filled in by hmz. Asked about names, capabilities, and a draft whose repairs ran out. |
Both agents carry the flow's own skill,
writing-flows: how a flow is written against hmz. Any backend can fill either role.
| Param | Default | |
|---|---|---|
name |
blank | What to call the new flow. Blank takes the name the spec gives it. |
into |
local |
local lands it among this project's flows; user among yours, in your home directory. |
repairs |
3 |
Rounds of repair after the first draft, 0 to 6. |
strict |
false |
Send a draft back for every warning, not only for what blocks it. |
seconds |
60 |
How long each run on fakes may take. |
- The flow lands. It is moved into place whole, and never over a flow that is already there.
- Nothing lands. No spec could be drawn, you declined a name or a capability, or the
repairs ran out and you did not take the draft as it stands. Under
hmz execnobody is there to say yes, so every such question is a no. - The budget.
aot keeps nothing for --resume: each run is one description, and running it again writes
another flow. To write a flow by hand instead, see
Writing a flow.
@futrime, as listed in .github/CODEOWNERS.
Issues and pull requests are welcome. The flow is the aot/ directory; its tests are in
tests/. With uv:
uv sync
uv run ruff check
uv run ruff format --check
uv run pytesttests/test_aot_golden.py compiles real flows with real agents, so it is skipped unless
AOT_WRITER=cli/model:effort (and optionally AOT_CRITIC, AOT_BUDGET, AOT_SMOKE=1) says
which to use.
CI runs the same on every pull request. A release is a vX.Y.Z tag on main; it reaches hmz
users once a flows/aot/X.Y.Z/flow.yaml pointing at it is merged into
humanfia/flowverse.
Apache-2.0 © Humanfia