Skip to main content

The Prompt Is Not the Product: Why AI Coding Needs Loops and Harnesses

The biggest AI coding gains are not coming from better prompts. They are coming from custom loops that turn large migrations into bounded, reviewable, and repeatable systems.

By Marco Porracin
Model: GPT-5.6 Sol (On Cursor)
#AI#Claude Code#agents#workflows#software engineering#automation

When coding agents first became useful, I treated them like very fast developers sitting beside me. I would describe a task, wait for the code, review it, and start another conversation.

That already felt powerful. But it still made me the orchestrator.

Recently, we needed to migrate a private financial operations product away from one database access pattern and toward direct Postgres queries. This was not one function or one folder. The old pattern appeared across dozens of server modules, browser modules, and API routes. Authentication and storage had to stay untouched. Public TypeScript interfaces could not change. Client-side calls had to move behind authenticated server endpoints.

Asking an agent to "migrate the codebase" would have been reckless.

So we built a small system that could do it in loops.

That distinction, between prompting an agent and engineering a process around agents, is where I think the next major productivity jump is happening.

The Bun Rewrite Made the Pattern Impossible to Ignore

In July 2026, Jarred Sumner published Rewriting Bun in Rust. The headline numbers are difficult to process: a codebase with more than half a million lines of Zig was mechanically ported to roughly one million lines of Rust, with the full test suite passing across all supported platforms, in 11 days.

The easy takeaway is that the model was very capable.

The more useful takeaway is that this was not one heroic prompt.

The Bun team ran around 50 dynamic workflows. At peak, four workflows across separate worktrees kept 64 agents working in parallel. One agent implemented a change. Two independent agents reviewed it adversarially. Another applied the feedback. Compiler errors became a work queue. Failing tests became another work queue. CI failures became another loop.

The rewrite worked because the problem was turned into a system:

The model mattered, of course. But the harness decided what the model should do next, what it was allowed to touch, how its output would be checked, and when the process should stop.

That is much closer to engineering than prompting.

Our Smaller, Private Version of the Same Idea

Our migration was nowhere near Bun's scale. It was still large enough that doing it manually would have been slow, repetitive, and surprisingly risky.

The product is private, so I will keep the business and implementation details intentionally generic. The technical shape is what matters.

The application had accumulated direct calls to a hosted database SDK in many parts of the TypeScript codebase. We wanted table access to use parameterized Postgres queries instead, while continuing to use the existing provider for authentication and file storage.

There were two different migration paths:

  1. Server modules could replace SDK table calls directly with Postgres queries.
  2. Browser modules could not connect to Postgres, so each one needed authenticated API routes plus a client wrapper that preserved the old exports.

That second path is where a naive global search and replace would have failed badly. The migration crossed a security boundary.

We created our own Node.js harness with explicit phases.

The first end-to-end run almost one-shotted the entire migration in about 40 minutes. By the end, the result was:

  • 61 files changed
  • More than 20,000 lines edited
  • Less than $10 in model API costs

That cost was not an accident. We routed the high-volume work through inexpensive models on OpenRouter and reserved stronger models for tasks that failed or were rejected during verification.

Phase 1: Turn the Repository into an Inventory

The first agent did not write code. It classified every candidate file:

  • Server-side data access
  • Browser-side data access
  • Authentication
  • Storage
  • Mixed responsibilities
  • Already migrated
  • Safe to skip

That inventory was serialized to JSON and converted into separate queues. We also maintained explicit skip lists for areas where automatic migration would be dangerous.

This sounds like preparation, but it is one of the most important parts of the system. Agents become much more useful when the work is represented as data.

Phase 2: Migrate One Bounded Unit at a Time

Each worker received one file, a migration contract, and a short list of known-good reference modules.

The contract was specific:

  • Preserve exported function names, signatures, and return shapes.
  • Use parameterized SQL.
  • Do not touch authentication or storage.
  • Keep changes local.
  • Check for leftover calls to the old data API.

We started with a tiny pilot batch before increasing concurrency. This exposed gaps in the prompt and reference patterns while the cost of being wrong was still small.

Phase 3: Separate Implementation from Verification

After each migration, a different model received a verification prompt.

Its job was not to be helpful. Its job was to reject the work if it found unsafe SQL, broken interfaces, accidental authentication changes, client-side database access, or incomplete migration.

If verification failed, the harness escalated the task to a stronger model and ran verification again. Failed files were recorded instead of silently disappearing from the queue.

This separation matters. The agent that wrote a change has context about why its choices felt reasonable. A fresh reviewer only sees whether those choices satisfy the contract.

Phase 4: Use the TypeScript Compiler as Another Queue

Per-file verification catches local mistakes. It does not catch every integration problem.

After each migration phase, the harness ran tsc --noEmit. Compiler errors became input to a separate repair loop. The loop stopped when the compiler passed, when it reached its maximum number of rounds, or when two rounds produced no meaningful progress.

The stop condition is important. "Keep trying until it works" is not a safety strategy.

Phase 5: Persist Everything

The harness saved:

  • Completed files
  • Failed files and reasons
  • Phase results
  • Agent summaries
  • Token usage and estimated cost
  • The last update time

That made the workflow resumable and idempotent. If it stopped halfway through, the next run skipped completed work and continued from the remaining queue.

The final global type check passed. More importantly, the process was inspectable. We could see which files had changed, which verifier approved them, where retries happened, and what remained outside the automated scope.

The Agent Should Be an Untrusted Worker

The most useful mental model we found was not "AI teammate."

It was "untrusted worker inside a well-designed pipeline."

That framing changes how you build the system:

  • Tools are constrained. Our agents could read and write inside the repository, but shell access was allowlisted to a small set of inspection and validation commands.
  • Work is bounded. One worker gets one file or one clearly defined failure group.
  • Concurrency is limited. More parallelism is not automatically better if workers can edit shared dependencies.
  • Outputs are structured. Agents return machine-readable summaries so the harness can branch on success or failure.
  • Progress is durable. State lives outside any model's context window.
  • Quality is external. Type checks, tests, linters, and adversarial reviewers determine whether work advances.
  • Humans keep control. Risky domains are excluded, pilot runs happen first, and the process pauses for review between major phases.

This is also why simply opening 20 terminal tabs is not orchestration. Parallelism without ownership, isolation, and a merge strategy creates collisions faster than it creates value.

Dynamic Workflows Put the Orchestration into Code

Claude Code now documents this pattern as dynamic workflows.

The key idea is simple: move the plan out of a conversation and into a JavaScript program. The script owns the loop, branching, concurrency, and intermediate results. Agents perform the work.

A simplified workflow looks like this:

The real power is not the syntax. It is that the orchestration becomes a reusable artifact.

You can review it before running it. You can save it with the repository. You can change the concurrency. You can add a second verifier. You can route simple work to a cheaper model and reserve a stronger model for failures. When a pattern produces bad code, you fix the workflow instead of repairing every output by hand.

Claude Code's workflow runtime now provides much of the machinery we built ourselves. A custom harness is still valuable when you need a different model provider, stricter tool controls, domain-specific state, or integration with your own infrastructure. In both cases, the principle is the same: the process should be code.

This Should Feel Familiar to Data Engineers

At Blueprint, this way of thinking feels natural because it resembles data orchestration.

A reliable data pipeline does not say, "please move all the data and do not make mistakes." It defines tasks, dependencies, retries, state, observability, resource limits, data quality checks, and failure behavior.

Agent workflows need the same discipline.

The model is an execution engine. The prompt is configuration. The harness is the orchestrator. Git, compilers, tests, and reviewers are the quality layer. Persistent state is what makes the system recoverable.

Once we looked at coding agents through that lens, many decisions became obvious.

What We Are Experimenting with at Blueprint

We are still early. We are not pretending these systems can be left alone indefinitely or trusted with every kind of change.

But we are actively testing them on real work:

  • Repetitive migrations across many files
  • Data modeling tasks with strong conventions
  • Codebase inventories and audits
  • Independent review passes
  • Compiler and test repair loops
  • Internal agents that package our team's recurring knowledge

The goal is not to generate the most code. The goal is to make ambitious changes safer, faster, and more repeatable.

This is vanguard technology, which means some of the most valuable work is not using the newest model. It is discovering the operating patterns that make the technology reliable.

The Bigger Picture

For the last two years, a lot of AI coding advice has focused on prompts, context files, and choosing the best model. Those things still matter.

But I think the durable advantage is moving up one level.

The most effective teams will build repository-specific harnesses that know how work should be discovered, divided, implemented, reviewed, tested, retried, and stopped. Their knowledge will live not only in documentation, but in executable workflows.

Today, creating our own harnesses and designing our own loops seems to be the way.

The prompt is not the product. The loop is.

RSS Feed

Prefer RSS? Subscribe to our RSS feed to get updates directly in your feed reader.

Subscribe to RSS

Want to talk through a similar data problem?

If this is close to the kind of work your team needs, request a conversation and tell us what you are trying to solve.

Request a Conversation