Skip to content

ralph_loop ​

Leave one agent on a long task. Every round is a fresh session that starts from the task and the repository, so a run can go on for days without drowning in its own context.

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/ralph_loop.

text
❯ $ralph_loop make every test in tests/ pass
sh
hmz exec -f ralph_loop -a agent=claude/claude-opus-5:high \
    -p budget.duration=6h,budget.cost=50 "$(cat TASK.md)"
ralph_loopsimulated

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

Every round starts from the task and from whatever the round before it left in the working directory — never from what it said.

The run, turn by turn
  1. agent — the task; a session opened for this turn; hands agent in the tree: the repository
  2. agent — the task; a session opened for this turn; hands agent in the tree: the repository
  3. agent — the task; a session opened for this turn; hands agent in the tree: the repository
  4. agent — the task; a session opened for this turn

Then round again: nothing carries over but the repository.

It ends when the budget runs out, or 3 rounds in a row answer nothing.

When to use it ​

A round that starts clean reads the repository as it is, the test the last round broke and the file it left half-written, with none of the reasoning that got it there. The price is that an agent that forgets may redo work, or undo a decision it made an hour ago. Have it write its decisions into the repository, and every round reads them back.

Roles and params ​

RoleWhat it isHow it is filled
agentagent, required-a agent=…Takes every round, each in a fresh session.
workspaceenvironment, localthe directory you start in; no -eWhere every round works, and all that carries from one to the next.

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. The loop pauses 5 seconds between rounds.

What ends it ​

  • The budget. Whichever of its limits runs out first.
  • Three rounds in a row that answer nothing. A round whose turn fails counts as one that answered nothing, so a backend that refuses the account, or will not run the model, stops the run within three rounds instead of burning the budget's whole duration:
text
round 41
round 41 failed: <what the backend said>
round 42
round 42 failed: <what the backend said>
round 43
round 43 failed: <what the backend said>
stopping: 3 rounds in a row answered with nothing

Picking it up ​

--resume carries on the round count: a run stopped on round 40 starts again at round 41. Everything else the loop knows is in the repository, where it always was.

A run stopped by its budget or by a stall is not over. Fix what stopped it, then run the same line again with --resume and a fresh budget. See Picking a run up.

See also ​

  • stateful_ralph: one session instead, sent the task every round
  • Loops: writing a loop like this one yourself