DEV Community

Cover image for Loop engineering: stop prompting, start defining outcomes
Ayaan Ahmad
Ayaan Ahmad

Posted on

Loop engineering: stop prompting, start defining outcomes

A few years ago, I was integrating with an API that shall remain nameless. It told me almost nothing — no error messages, no logs worth reading. Just HTTP status codes and a dashboard with exactly one metric: failed requests over total requests.

It started at 1/1. Then 2/2. Then 13/13. Then 32/32. A perfect record of failure.

I was deep in it. Change something, re-send, change something else. Then I looked up, and the dashboard read:

67/68.

One request had worked.

Which one?

I had no idea. Somewhere in the last hour of frantic edits, one combination of changes had produced a success, and I had kept editing right past it. No log of what I'd tried. No commits between attempts. Just a number telling me I'd already solved the problem and thrown the solution away.

It took me two days to find it again.

The part that actually matters

Here's what I understood only later: none of that debugging required creativity.

It required repetition with memory. Try one variation. Observe the result. Write it down. Narrow the space. Repeat.

I was a slow, tired, increasingly bitter for-loop with a caffeine dependency.

That's not a job that needs a human. It needs something that doesn't get tired, doesn't forget what it tried on attempt #12, and doesn't edit past a working version without noticing.

Prompting vs looping

Most people using AI coding tools are still doing this:

Write me a function that does X.

Then, reading the output, spotting what's wrong, and typing a correction. Then another. This is prompt engineering — asking really precisely, once, and hoping.

A loop is a different shape:

A prompt asks for code. A loop asks for an outcome.

You don't write the fix, and you don't evaluate each attempt. You define what success looks like in a way a machine can check, hand over the ability to check it, and let the thing iterate until the condition is met.

The skill moves from phrasing to specifying.

The four parts of a working loop

Loops that work all have these. Loops that fail are usually missing one.

  1. An exit condition that the machine can verify. Not "make it work." A command that returns something unambiguous — a passing test, an HTTP 200, an exit code 0. If the agent can self-assess subjectively, it will, and it will grade itself generously.

  2. Feedback that can actually be read. The loop is only as smart as the errors it is given. Full response bodies, real stack traces, and actual test output. If your verification step prints "FAILED" and nothing else, you've built a loop that guesses.

  3. Boundaries. Which files may it touch? One change per attempt. Keep a log. Commit each attempt. Without these, you get a working solution buried inside forty unrelated "improvements."

  4. A budget. Max attempts, then stops and reports. This isn't about token cost — it's so a genuinely stuck loop escalates to you with a log instead of quietly redecorating your codebase for an hour.

What that looks like in practice

Here's the shape of a loop I'd hand to an agent for exactly my 67/68 situation today:

GOAL: POST /v1/transactions must return 200.

VERIFY WITH: ./scripts/test_api_call.sh
  (sends one request, prints status code + full response body)

RULES:
- After every change, run the verify script and read the FULL response
- Change ONE thing per attempt (auth header, payload field,
  encoding, endpoint version)
- Keep a running log in attempts.md: what changed, what came back
- Commit after every attempt with a one-line message
- Do NOT touch anything outside the api_client module

STOP WHEN: script prints 200, or after 25 attempts — then
summarize the log and hand it back to me.
Enter fullscreen mode Exit fullscreen mode

Every line is doing work.

The verify script is an exit condition the agent can't fudge — it has to print a real status code. One-change-per-attempt plus attempts.md is the memory I didn't have at 2 AM. Commit-every-attempt means "which one worked?" is answered by git log instead of two days of archaeology. And the boundary keeps an enthusiastic agent from "fixing" my database config while it's in there.

Come back later, and the log reads like a lab notebook you never had to keep:

#11  auth header: Bearer -> Token          -> 401
#12  payload: amount as string             -> 422
#13  endpoint: /v2/ -> /v1/                -> 404
#14  content-type: added charset=utf-8     -> 200 OK
Enter fullscreen mode Exit fullscreen mode

Two days of my life, expressed as fifteen lines of instructions.

Why this is really about trust

Here's the subtle part.

A loop does not make the AI's code more trustworthy. Individual attempts still fail — that's the entire premise; most attempts fail. What changes is where your trust lives.

I don't need to believe attempt #14 is correct. I need to believe my verification script can't be fooled.

That's a much smaller thing to trust. And unlike the model, it's a thing I wrote and fully understand.

That shift — from trusting the generation to trusting the checking — is what makes any of this workable at scale. Everything else (rules files, review passes, permissions) is elaboration on the same idea.

Where loops don't belong

Worth being honest about the limits, because "just loop it" is becoming its own kind of hype.

Anything without a cheap, honest verification. If the only way to know it worked is a human looking at it, you don't have an exit condition — you have a wish. UI polish, copy, architecture decisions: these don't loop.

Anything where a wrong attempt is expensive. Loops assume failed attempts are free. Payments, migrations against real data, anything touching production — the whole model breaks when attempt #7 costs money or can't be reverted.

Timing-sensitive bugs, unless you're careful. I once watched an agent "fix" a race condition by adding sleep(1) in three places. The tests went green. The race was still there, waiting for production traffic. A loop optimizes for the exit condition you gave it, which means a weak exit condition gets gamed with total confidence.

When you can't tell why it passed. If a loop goes green and you don't understand the fix, you haven't solved the problem — you've just relocated it to a future incident.

The takeaway

If your AI workflow is still prompt → read → correct → prompt, you're doing manual work that a loop could do.

Start small. Take one annoying bug you've been ignoring. Write an exit condition that proves it's dead. Give the agent boundaries and a budget. Then — and this is the actual hard part — walk away while it runs.

The attempts log will be there when you get back.

What's your version of 67/68? I've been collecting them.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.