“Loop engineering” is a hot buzzphrase after mentions of it by Boris Cherny (Claude Code’s creator) and Peter Steinberger (OpenClaw's creator) went viral on social media. Loops are now a key part of how we get AI agents to iterate at length to build software. In this letter, I’d like to share my 3 key loops, shown in the image below, for building 0-to-1 products. These loops guide not just how I build software, but also how I decide what software to build.
Agentic coding loop: Given a product specification and optionally a set of evals (that is, a dataset against which to measure performance), we can have an AI agent write code, test its work, and keep iterating until the code is bug-free and meets its specification. This idea of closing the loop took off around the end of last year, and it has been a game changer in enabling coding agents to work longer productively without human intervention. For example, over the weekend, I was building an app for my daughter to practice typing, and my coding agent could easily work for around an hour, using a web browser to check what it had built multiple times before getting back to me, without needing my intervention.
The engineering loop executes quickly. Every few minutes, the coding agent might build and test a new version of the software. I hear frequently from developers who are finding new ways to engineer more effective engineering loops. This is an active area of invention!
Developer feedback loop: In this loop, a developer examines the current product and steers the coding agent to improve it. Last year, a lot of developers (including me) were acting as the QA (quality assurance) function for our coding agents, manually finding bugs and then asking the agent to fix them. But with coding agents much more able to test their own code, the amount of time we need to spend on this function has decreased significantly. This allows us to make higher-level product decisions, such as what key features to offer, where the UI needs improvement, and so on.
The developer-feedback loop operates over time intervals between tens of minutes and hours — that's how frequently a developer might review a product and give feedback. In the case of the typing app, I changed my mind a few times about the visual design, what cat costumes she can unlock as she learns (she loves cats), and the user flow for a grown-up to log in and steer the child's learning experience.
When a developer has a clear vision for what to build, it is still a lot of work to translate that vision into a specification for a coding agent to implement. Further, after the developer has seen an implementation, they might update (or perhaps clarify) the spec to steer it toward what they want. If you find that the system repeatedly runs into certain problems, building a set of evals for the agent becomes useful.
AI-native teams are increasingly using AI to help shape product direction, for example, automating the gathering and analysis of usage data, summarizing written and verbal customer feedback, or carrying out competitive analysis. However, for pretty much all the products I’m involved in, I see humans as having a significant context advantage over current AI systems — we know a lot more than the AI system about the users and the context the product has to operate in — and thus humans play a critical role. Many people describe this human contribution as “taste,” but I prefer to think of it as humans having a context advantage, since that gives us a clearer path to helping AI systems get better. This also speaks to why this step can’t be automated: So long as the human knows something the AI does not, human-in-the-loop is needed to to inject that knowledge into the system.
External feedback loop: This includes a wide range of tactics like asking a few friends for feedback, launching to alpha testers, or putting the code into production with A/B testing. These tactics are usually slow, rarely taking less than hours and sometimes taking days or even weeks. This data informs the developer vision, which in turn continues to drive the detailed product spec, which in turn drives the coding agent.
With coding agents speeding up software development, more engineers are starting to play a partial product management role. For many engineers who are growing into this role, the hardest part is shaping the product vision and striking a balance between building (bridging the gap between vision and spec) and getting user feedback to evolve the vision. It is important to do both!
I will write more about how to do this in future posts, but for now, I find it encouraging that engineers are playing an expanded role (just as product managers and designers now do more engineering).
[Original text: The Batch]
Talking to smarter folks than me, I'm convinced many of the AI folks in my timeline are full of shit.
Nobody is "running 20 agents over night" and building stuff for actual users. Maybe some are building internal tools or disposable software. Maybe.
But building software people like using? That doesn't get hacked on day one or blow up after the 3rd user? Nope.
I don't even understand what that's supposed to look like. Do you work out a 57 pages document that perfectly describes what you want to build and then summon 14 agents and have them run wild for 6 hours? And what comes out on the other end isn't a broken pile of shit?
Nope. Not buying it.
PS: it may also be that I have an IQ of 82 and can't figure it out.
OVERRATED: running tons of agents in parallel; working on too many things at once; perpetual context-switching; opening lots of low-quality PRs that may never land.
UNDERRATED: using one or two agents at a time; focusing on the task in front of you; thinking deeply; finishing stuff; making your code works in prod.
I work with multiple companies where nearly all code is AI generated now. However, the productivity probably has only increased 20-30%. Why?
I suspect because writing code is really running code. Changes are the result of a business learnings. Or an operational learnings. For mature companies, the majority of PRs are sub 10 lines codifying these learnings.
AI clearly helps here (e.g. debugging, running tests, building tools) but less so. Operations and business learnings are workload and company specific.
Until AI can perfectly predict what the market needs, or how a system will be used this bottleneck will exist.
Team is not a group of people working on the same codebase.
Team is a group of people that share the same goal and help each other to achieve it.
They value team success over the success of individuals. Or to rephrase it: individuals succeed when the team succeeds.
Effort feels like productivity.
Working harder feels like getting more done.
Rushing feels like producing.
Struggling feels like doing something worthwhile.
Busyness feels productive.
Solo feels fast, because you're at your own maximum pace.
Feeling-driven development
The main reason for me to use Lombok was @Value annotation in combination with @Builder. Considering recent developments in Java language - especially records, the value of Lombok gradually decreases.
With this in mind, I do not recommend using Lombok anymore.
@mitsuhiko As far as I understand these type of problems come from HTTP streaming with the App router / RSC. Can't even change the http status code anymore in the top-level react component because the stream has already started.
Or, if you prefer, "I am a full product engineer."
And this ^^^ is what we should all be trending towards. The days when you could put up your hands and protest, "I'm just a backend engineer. Get someone else to write those five lines of javascript" -- are ending.
Many people say you should *never* create Utils classes
I disagree, but I follow rules:
1. Utils fill gaps in a language or a library.
2. They should be not specific to the domain or application logic.
3. Write utils class like it would be open sourced in the future.
1/4
In the Monolith vs Microservices discussion it often looks like you can go either with one large monolith or tiny microservices while in my experience multiple *right sized services* is usually the answer
@tdpauw @emilybache PR are asynchronous code reviews. They create blockers and queues. And those two things are bad. Useful on open source development due to the difficulty synchronising. Should not be used in most companies.
Writing tests is not about ensuring that your software works at the moment of writing it; it primarily gives us the possibility to evolve in the future. Can't be repeated often enough.
"Definition of ready" is, IMO, nothing but a waterfall up-front design, plan, requirements-gathering phase. It's an active destroyer of agility—a complete failure to grasp the concept.
Something that's helped me: Don't refactor and change behavior at the same time. Do one and then the other.
Doesn't always need to be separate PRs but should at least be separate commits.
Remote pair programming:
Outline:
1. When to do it,
2. When NOT to do it,
3. Practical Tips on how to do it,
4. Recommended tools,
5. Additional references.
But first, let's start with WHY to do it.
0. Why to do it
WHY?