From Prompt Engineering to Loop EngineeringValerii Iatsko

From Prompt Engineering to Loop Engineering

Stop prompting. Start designing loops.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Valerii Iatsko

Software engineer at Google

With GitNation since 2016

Work on AI data pipelines and AI developer workflows

From Prompt Engineering to Loop EngineeringValerii Iatsko

You were the loop

"I don't prompt Claude anymore. I have loops running that prompt Claude and figure out what to do. My job is to write loops."
โ€” Boris Cherny, Claude Code (Anthropic)

Prompt โ†’ inspect โ†’ re-prompt โ†’ repeat.

The agent was fast. The steering was manual.

Then models got capable enough to run faster, longer, and in parallel.

Your attention carried state, chose next work, and decided when to stop.

That is how you became the bottleneck.

QR code for ghuntley.com/ralph
Scan QR for source note
From Prompt Engineering to Loop EngineeringValerii Iatsko

Move decisions out of your head

Start by asking: what steering decisions am I still making by hand?

Loop engineering gives those decisions a place to live:

read state โ†’ choose work โ†’ run agent
           โ†’ check result โ†’ record state โ†’ repeat

The human keeps goals, boundaries, and gates.

The loop takes repetitive steering.

From Prompt Engineering to Loop EngineeringValerii Iatsko

What can loops build?

Not just chores.

Loops can build:

The question is not "can the model do it once?"

It is "can the loop make progress you can inspect?"

From Prompt Engineering to Loop EngineeringValerii Iatsko

Three months of while true

while :; do cat PROMPT.md | claude-code; done

The same PROMPT.md went in every time. An excerpt:

Follow @fix_plan.md and choose the most important thing.
Before making changes, search the codebase โ€” don't assume
something isn't implemented. When the tests pass, update
@fix_plan.md, then git add -A, git commit, git push.
9999999999. ALWAYS KEEP @fix_plan.md up to date.
99999999999. When you learn how to build, update @AGENT.md.

The prompt never says what to build. specs/ define the target. fix_plan.md is the live backlog. AGENT.md is local operating knowledge.

github.com/ghuntley/cursed

QR code for github.com/ghuntley/cursed
From Prompt Engineering to Loop EngineeringValerii Iatsko

Where the "what" lives: specs/

Straight from Huntley's public cursed writeup:

CURSED code consists of the following token categories:

- `KEYWORD`    - Reserved language keywords
- `bool_lit`   - Boolean literals (`based`, `cringe`)
- `nil_lit`    - Nil literal (`nah`)
- `เถž`          - Among Us symbol for pointer types

- Line comments start with `fr fr` and continue to end of line
- Block comments start with `no cap` and end with `on god`

Fifteen files like this: grammar, memory management, concurrency, FFI, the LLVM target. The loop reads these, not your mind.

He didn't type them by hand either. They came out of a planning conversation with the agent, one file per topic, and his job was reviewing them. A duplicated keyword in this very file cost him a month of confused loops.

QR code for ghuntley.com/cursed/#lexical-structure
lexical proof
From Prompt Engineering to Loop EngineeringValerii Iatsko

Rules that survive fresh starts

How to build, test, and run the project. Every fresh iteration reads it first, and the prompt makes the loop maintain it, verbatim:

When you learn something new about how to run the
compiler or examples make sure you update @AGENT.md
using a subagent but keep it brief. For example if
you run commands multiple times before learning the
correct command then that file should be updated.

Huntley calls it the heart of the loop. Run a command wrong three times, write down the right one, and the mistake only happens once.

The practice, in his own words: ghuntley.com/ralph

QR code for ghuntley.com/ralph
From Prompt Engineering to Loop EngineeringValerii Iatsko

What came out

slay main_character() {
    sus i normie = 1
    bestie i <= 100 {
        ready i % 15 == 0 {
            vibez.spill("FizzBuzz")
        } otherwise ready i % 3 == 0 {
            vibez.spill("Fizz")
        } otherwise {
            vibez.spill(i)
        }
        i = i + 1
    }
}

FizzBuzz, verbatim. slay is a function, sus a variable, bestie a for-loop. It compiles: LLVM backend, three platforms, a standard library. Nobody was hand-prompting after kickoff.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Takeaway: repo state drives the loop

Clean starts are useful only when the repo remembers.

fix_plan.md was not a static roadmap.

That is how a fresh run knows what to do next.

Source: ghuntley.com/ralph

QR code for ghuntley.com/ralph
fix_plan prompt
From Prompt Engineering to Loop EngineeringValerii Iatsko

"We put a coding agent in a while loop and it shipped 6 repos overnight"

A real HN headline. The whole setup, from their writeup:

while :; do cat prompt.md | claude -p; done
Your job is to port browser-use monorepo (Python) to
better-use (Typescript) and maintain the repository.
Make a commit and push your changes after every file edit.

Six projects overnight: React to Vue, Python to TypeScript, TypeScript to Python, plus specs-to-code experiments from docs. About 1,100 commits, just under $800.

Nothing stopped the loops. Humans looked in the morning.

github.com/repomirrorhq/repomirror

QR code for github.com/repomirrorhq/repomirror/blob/main/repomirror.md
writeup
QR code for news.ycombinator.com/item?id=45005434
HN thread
From Prompt Engineering to Loop EngineeringValerii Iatsko

Big diffs die waiting

The same team pointed a loop at their own frontend. The actual prompt, committed in the PR (condensed):

0a. Read REACT_CODING_STANDARDS.md โ€” the ideal architecture
1.  Read REACT_REFACTOR_PLAN.md and implement the SINGLE
    highest-priority change, with tests
2.  Run the checks and tests, fix until all are passing
3.  Update the plan, commit, push

Six hours of that produced +19,392 / โˆ’1,367 across 131 files and zero formal reviews. A diff that size never even reached review. While it sat, main kept moving; the conflicts outgrew the refactor. PR #513: closed, not merged.

"Waking up to one small refactor every morning is better than waking up to none โ€” and better than waking up to 50."

Their fix: once per night, a diff sized to review over coffee and merge the same morning. The bottleneck was never the agent. It's how fast humans absorb change.

QR code for github.com/humanlayer/humanlayer/pull/513
From Prompt Engineering to Loop EngineeringValerii Iatsko

Takeaway: speed moves the bottleneck

Parallel loops turn calendar time into attempts.

They do not remove human accountability.

When code gets cheap, the scarce thing becomes:

From Prompt Engineering to Loop EngineeringValerii Iatsko

Hand off repetition. Keep judgment.

the loop can doyou still own
repeat promptsthe objective
work the checklistthe spec
chase green teststest authority
propose next tasksapproval
merge routine branchesreview bandwidth

Before it runs unattended, be able to answer: What goal is it serving? What is it allowed to change? What makes it stop?

From Prompt Engineering to Loop EngineeringValerii Iatsko

What should you automate?

Put loops where work is:

Good first loops: CI triage, flaky-test diagnosis, dependency bumps, doc drift, small bug queues.

Bad first loops: broad refactors, architecture rewrites, "make it better."

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5

The starter loop is five artifacts

Each one is reviewable. That is the point.

The loop can move work forward, but these files keep the work legible.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5 ยท file 1

SPEC.md: own the target

# SPEC.md

Goal: a tiny expression language.

...

Done means:
- every checklist item is ticked
- node --test is green

Non-goals:
- no package manager
- no syntax not described in this spec

This is not a prompt. This is the contract the loop keeps rereading.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5 ยท file 2

PLAN.md: make work claimable

# PLAN.md

- [ ] 1: lexer tests for numbers and operators
  done when: the new test fails for missing lexer

- [ ] 2: implement the lexer
  done when: node --test is green

- [ ] 3: parser tests for expressions
  done when: the new parser test fails

One checkbox = one iteration. Small enough to review.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5 ยท file 3

AGENTS.md: put rules where agents look

# AGENTS.md

- Run tests with `node --test`
- Work only on the first unchecked PLAN.md item
- During implementation, do not edit `test/`
- Append one PROGRESS.md line before exit

The prompt can stay short because the repo carries the rules.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5 ยท file 4

PROGRESS.md: give the next agent memory

# PROGRESS.md

- 09:12 wrote lexer tests; next implement token shape
- 09:18 lexer green; next write parser expression tests
- 09:25 parser test expects BinaryExpression.operator

A fresh agent starts from files, not from yesterday's chat context.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 1 of 5 ยท file 5

loop.sh: repeat the handoff

while grep -q "\[ \]" PLAN.md; do
  codex exec "Read SPEC.md, PLAN.md, AGENTS.md, PROGRESS.md.
              Build the first unchecked item. Test it.
              Tick it only if green. Append progress."
done

That's the first handoff: the loop works the plan now. The spec is still yours.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 2 of 5

Protect the tests from the loop

Still one agent, one loop, but now it runs unattended. A loop was told "make the tests pass":

iteration 4: 3 tests failing
iteration 5: 0 tests failing   โ† it deleted the tests

Not a naughty model. A badly specified objective: you asked for green, you got green.

So who writes the tests? The loop can โ€” writing a test is its own iteration. The rule protects the other iterations: when the job is "make the tests pass," the test files are off-limits, enforced by the tools, not by a polite sentence in the prompt.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 3 of 5

Hire a skeptic

The first time we add a second agent. It's nothing new: the same claude -p, a different prompt, no shared memory with the writer.

git diff | claude -p "Try to prove this change is wrong.
                      Run the tests.
                      Verdict: pass or fail, and why."

Ask it to prove the work wrong, not to approve it. Models reviewing their own output don't get better, they get agreeable (Huang et al., ICLR 2024).

On fail, the loop stops and a human looks.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 4 of 5

Let it refill its own backlog, carefully

When the plan runs dry, one extra run gets a different prompt: read the goal, propose at most two tasks, build nothing.

The output is just new candidate tasks:

## Backlog โ€” agent-proposed
- [ ] 7: clear command โ€” prune completed todos
- [ ] 8: stats command โ€” open/done counts

Proposals follow the same rules as human tasks, are labeled as machine-written, and wait for a person to approve them.

This handoff: the loop proposes work now. The goal stays with you.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Step 5 of 5

Scale by adding loops, not chaos

Start with one loop on main: no branches, no merging, one task at a time. That's not a limitation, it's the baseline.

When review capacity grows, scale in this order:

From Prompt Engineering to Loop EngineeringValerii Iatsko

Should you use loops?

Yes, when the work is:

No, when "done" is unclear or nobody owns the gate.

Loops are not a way to avoid judgment.

They are a way to spend judgment where it matters.

From Prompt Engineering to Loop EngineeringValerii Iatsko

Start with loops today

Ask where you are still doing routine steering

Keep real-time judgment with the human

Give the loop the routine path

Start with one tiny loop, one state file, and one review gate

From Prompt Engineering to Loop EngineeringValerii Iatsko

Take the demo

Repro demo:

github.com/viatsko/loops-demo

More examples:

github.com/viatsko/awesome-loop-engineering-examples

Great article on loop engineering:

addyosmani.com/blog/loop-engineering

Thank you.

QR code for github.com/viatsko/loops-demo
repro demo
QR code for github.com/viatsko/awesome-loop-engineering-examples
examples
QR code for addyosmani.com/blog/loop-engineering
article