Loops and Goals
An agent working a ticket can split breadth-first work (many independent targets: every route module, every open PR, a codebase-wide audit) into a Loop: a pipeline the human can see, edit and approve before anything runs, instead of a plain prompt the agent promises to follow. The pipeline is a DAG the board executes in exactly the order its edges describe (Loop nodes), and it renders live on the ticket as it runs.
When to reach for one
Section titled “When to reach for one”Default to a single agent doing the work end to end: most tickets, and essentially every tightly coupled change, are best done that way. Splitting a coupled change only adds handoff and merge risk. A Loop pays off only for genuinely independent strands whose combined work exceeds one comfortable context: a codebase-wide audit, reviewing many open PRs, or parallel investigations.
When the work is breadth over a list of targets, the coverage should be structural: list the targets first, then give each child the targets it owns, so “covered everything” is a property of the graph rather than a claim in a summary.
The children’s work reaches the base branch only through the orchestrating ticket: it merges each child into its own branch, tests the combined result, and hands over one branch for review. See Run a Loop.
Goals: a Loop that runs until it is done
Section titled “Goals: a Loop that runs until it is done”A Loop carrying a goal block is a Goal (on the Create ticket form, Type set
to Goal). Instead of firing on a clock, each run ends by reporting a verdict, and a
continue verdict with budget left fires the next run immediately. A Goal therefore stops
for exactly two reasons: the objective was reached, or a ceiling in
params.resource_caps was hit.
The block has two fields, both prose:
text: the objective.done_when: the acceptance test in your own words, optional. It is deliberately a sentence rather than a predicate, because what judges it is a model reading the run ledger: “a spot-check of three entries matches the code” steers that better than anything the schema could check for you.
Each iteration appends one row to a ledger, and the next iteration is handed that
ledger up front, so it starts knowing where the last one got to instead of paying to
rediscover it. A run can report done or blocked as well as continue; both are
terminal, and they are kept separate on purpose, because “I got there” and “I cannot get
there” want different reactions from you.