Loop engineering
The third lever is not what you say or what the model sees, it is what happens around each response, and it is where most silent failures get caught or missed.
Engineering the loop, not the prompt
Prompt engineering changes what you say. Context engineering changes what the model can see. Loop engineering is different again: it changes what happens around each response, before the model acts and after it acts, without touching the prompt or the context at all.
An agent does not produce one answer and stop. It runs a loop: decide on a next step, act by calling a tool, observe the result, and decide again. Left alone, that loop will happily stop as soon as it produces something that looks finished. Looking finished and being correct are not the same thing, and the gap between them is exactly what loop engineering closes.
The concrete moves are the tools you give the agent, the hooks that fire automatically on events like a file write, the subagents you send off to check a result independently, and the retry logic that sends the agent back around the loop when a check fails instead of accepting the first attempt. None of these change what the model was told or what it could read. They change the system the model operates inside.
This matters because it is a system-level decision, not a per-message one. You configure loop engineering once, in a hook script or a subagent definition or a settings file, and it applies to every request that follows. A sharper prompt only helps the one time you type it.
Select a numbered hotspot to see what occupies that part of the diagram.
A data migration task, walked through the loop, showing where a verify step catches a wrong result before anyone ships it.
Step 1: The request
You ask Claude Code to write a migration script that backfills a new `display_name` column on the `users` table, using `first_name` and `last_name` where both exist, falling back to `email` (the part before the @) otherwise. Decide: Claude reads the schema, sees the three columns, and plans a single UPDATE statement with a CASE expression.
Step 2: Act, then observe
Claude writes the migration file and, without a verify step, would normally report it done here. Act: it creates the SQL file with the CASE logic. Observe: the file write succeeds and the linter passes. Nothing so far has touched real data or checked the logic against real rows, a syntactically valid migration can still be behaviourally wrong.
Step 3: A verify step catches the bug
A PostToolUse hook is configured to run the migration against a snapshot of the staging database and diff a sample of rows against expected output whenever a file under migrations/ is written. It fires automatically. The check fails: for users where `first_name` and `last_name` are both empty strings (not null, empty strings), Claude's CASE expression treated them as present because it only checked for NULL. Those rows get a blank `display_name` instead of falling back to the email-derived name. Without this step, the migration looks complete: valid SQL, no lint errors, ran without an error. It would have shipped a silent data bug that only shows up later as blank names in the product.
Step 4: Iterate
The hook's failure output, which rows mismatched and why, gets appended back into Claude's context. Decide, again: Claude reads the diff, sees that empty strings were not being treated as missing, and rewrites the CASE expression to check for both NULL and empty string. Act: it rewrites the file. Observe and verify run again, this time the row diff matches. The loop stops here, at verified, not at the first plausible draft.
Question 1 of 4
What distinguishes loop engineering from prompt engineering and context engineering?