Skip to content

goal ​

Hand the task to the agent as its own goal: the model keeps working, turn after turn, until it says the goal is met. One call, one session, and the model decides when it is done.

ships with humanize

Nothing to install: it is in hmz from the first run, with chat and the other loops, and its code is humanize's flows/builtin/goal.

worker: claude · codex · dsh · kimi
text
❯ $goal get the benchmark under 200 ms without changing its output
sh
hmz exec -f goal -a worker=claude/claude-opus-5:max \
    -p budget.duration=4h,budget.cost=40 "$(cat TASK.md)"
goalsimulated

The whole run, at rest. Step through it with the buttons, or drag the bar.

One turn of the flow. The ticks inside it are turns the backend started itself: a turn that would have ended starts another, until the model says the goal is met.

The run, turn by turn
  1. worker — /goal <task>; a session opened for this turn; hands the finish as words: the goal is met

It ends when the model says the goal is met, or the budget runs out.

When to use it ​

In ralph_loop, a loop that cannot read the work decides when a round is over. Here the model that has just done the work decides, every turn. The catch is that it is judging its own work; rlar asks a separate reviewer instead.

The flow sends /goal <task> to a backend that has a goal feature of its own. Only claude, codex, dsh and kimi do, and any other backend is refused before the first turn. Which backends have one.

Roles and params ​

RoleWhat it isHow it is filled
workeragent, required-a worker=…Pursues the goal, in one session.
workspaceenvironment, localthe directory you start in; no -eWhere the goal is pursued.

Each agent role takes one -a role=CLI[@PROVIDER]/MODEL[:EFFORT]; several roles may share one -a, comma-separated. There is no -e to give: workspace is a local environment, the directory you start the run in, and an -e naming it is refused. See Command-line specs.

No params.

What ends it ​

  • The model says the goal is met.
  • The budget. It counts every turn the goal took, not one per call.

The whole goal is one turn

A budget lets the turn under way finish by default, and here that turn is the whole goal. If the budget is a hard ceiling, pass -p budget.graceful=false, which cuts the goal off the moment a limit is reached.

Picking it up ​

goal keeps nothing for --resume: running it again starts from the task and the repository, as the first run did.

See also ​