Three years ago I was copy-pasting code from ChatGPT, getting it mostly wrong, and manually fixing the gaps. That was fine. That was the beginning. What I did not expect was how long and bumpy the road from there to something genuinely useful would be.
Here's a bit of the essence of moving from copy-pasting code from ChatGPT and back, to trying Aider[^1], not really liking it, trying GitHub Copilot, not really liking it, using Cline for VSCode, being amazed by what is possible and with pretty fast adoption within my team at the time, then using Cursor, but it somehow does not feel right, being excited about Claude Code, thinking I would settle on it, and now finally settling on Pi[^5] (until something better comes along).
A large language model with hands and feet
A large language model just generates text based on probability. Word by word. Give it hands and feet (love that metaphor a colleague of mine used) and it starts Frolicking[^4].
It can interact with the world, not just through text, but through APIs, databases, tools, web searches, and more, its hands, its feet. That is what makes LLMs actually useful in classical software engineering: they can do more than generate code snippets in isolation. And the same applies in personal contexts. My Hermes agent can now book appointments for me, extract information from my emails, and write events to my calendar before I have even read the email myself.
Vibecoding ≠ agentic engineering
Andrej Karpathy coined the term vibecoding in early 2025. Essentially, it is when you describe what you want and accept whatever comes back. ↩ ↩ ↩ accept, accept, accept, --yolo.
It works, until it doesn't. The failure mode is not that the code does not run. It usually does.
The failure mode is that nobody, including the agent, knows why it does what it does. The codebase becomes a series of patches nobody fully understands, and each new prompt makes it worse. Or the code quality gets worse and worse. Or both.
Agentic engineering is deliberate. You research before you plan. You plan before you implement.
The agent is involved in all three phases, but you stay in the loop between them. Staying in the loop is not debatable. The skills you need to supervise an agent effectively are the same skills that erode when you lean on it too much. Anthropic's own researchers named this the supervision paradox: effectively using an AI agent requires supervision, and supervising it requires the very coding skills that AI overuse gradually erodes. Lars Faye's article on the subject is the most honest treatment of why this matters that I have read. A new failure mode, and a nasty one because it is invisible until it is not.
Build your harness
Instructions files are your friends, but they get nasty fast
Auto-generated CLAUDE.mds or AGENTS.mds are crap. You can use the /init command in almost every agent harness, wait a few moments letting Claude boondoggle[^4] a first draft of instructions, but you have to rewrite them.
The default instructions are typically extremely long and therefore context-expensive, and they provide no real value to the agent later on. Most harnesses read the instructions at the beginning of every session, automatically. Why would the agent need to read every single command you have available in your package.json? Or every single task in your Taskfile.yaml? Or the full structure of your project, when it can read that with a single tree command? The instructions file is a great place to put the rules of the game, the constraints, and the commands that are actually relevant every single time.
But it is not a good place to dump everything. It becomes unreadable for the agent, and therefore useless.
A good instructions file follows the KISS principle, does not repeat itself, is kept short and concise, and introduces only the most important rules to the model. It does not replicate the README, but it supplements it. If you are working with ADRs, it makes sense to link to them. Same goes for extensive rulesets, for example for testing: use progressive disclosure and only tell the model where it can find more information when it needs it. Whenever showing examples, never show bad ones, only good ones.[^2]
If you have a large project, nest instructions files across (sub)modules.
There is no template worth showing here. Instructions files are highly individual per project. Keep them living and accessible to everyone on the team, including to edit.
It also makes sense to use words like MUST, MUST NOT, SHOULD, and SHOULD NOT in your instructions file, as per RFC 2119. It is a great way to make sure the agent understands the importance of certain rules, and it can help enforce compliance. For example: "You MUST use Conventional Commits" or "You MUST NOT use APIs marked with the @deprecated decorator". Models that are known for strong instruction following tend to take these more seriously than informal phrasing.
Hooked on hooks
Hooks, especially Git hooks, always spark discussion. Many people dislike them.
pre-commit hooks are awful, they get in the way of interactive rebasing. pre-push is where they belong; save a round-trip through CI.
Can't stand pre-commit hooks. I want zero delay on commits. Checks can be run against pull requests in a GitHub action runner; no reason to force me to run them on my machine.
(Comments about Git hooks on HN)
That is what --no-verify is for. If you do not want to check your work before committing and are eager to wait on a probably slower CI/CD pipeline, fine. Your local harness however will never get informed that your pipeline failed, unless you specifically told it to. That is where Git hooks come into play.
Everything your QA pipeline checks, your pre-commit hooks should check too. Use the pre-commit framework or Husky to share your hooks and push them upstream.
Forbid your agent to use --no-verify, for example by setting ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "npx block-no-verify"
}
]
}
]
}
}
Research-Plan-Implement is not enough
RPI (Research-Plan-Implement) was the first framework that made deliberate agentic engineering concrete. It spread without marketing (if a hyped Hacker News entry counts as "without marketing") and worked well, until scale exposed three failure modes that only become visible in real-world codebases.
First: instruction budget overflow. Frontier LLMs lose consistency after around 150 to 200 instructions in a single prompt. RPI's system prompt grew to 85+ instructions, and the model silently dropped the constraints buried deepest in the list. No errors, no warnings. Just quietly skipped alignment steps.
Second: the magic words trap. Correct agent behavior depended on trigger phrases the user had to know[^3]. Without them, the agent skipped the interactive design discussion and jumped straight to writing a plan that looked right but had not been aligned through conversation.
Third: the plan-reading illusion. Plans felt like progress. Detailed, coherent prose describing how components would interact. But a plan that reads well does not necessarily build well. Architectural debt accumulated underneath because the agent's prose was convincing while its technical assumptions were wrong.
So Dex Horthy (Humanlayer) rebuilt it from scratch.
QRSPI is the result: eight stages, five of them pure alignment before a single line of code is written. The key moves: hide the ticket during research so the agent maps the codebase without forming opinions prematurely, then run a design discussion where the agent writes a rough summary of the current state, desired end state, and proposed architectural decisions, and the human does what Horthy calls "brain surgery" to correct assumptions before they get baked in. From there, the plan enforces vertical slices over horizontal layers so each checkpoint is actually testable. Keep context under 40%, start fresh at 60%, and use sub-agents as context boundaries rather than personas. The framework grew from three steps to eight.
I am staying at three steps for now, but with an improved RPI skill built by a colleague of mine at MaibornWolff and openly available on GitHub, plus an additional /grill-me / /grill-with-docs[^3] invoked automatically.
Slowing down
Mario Zechner, creator of Pi, stood at the AI Engineer Conference in London this year and shouted at the room: "Slow the fuck down!" Multiple times. He was not joking.
While it is tempting to spin up 15 coding sessions at once, get 30 tasks done in five minutes, and then move on to the next 30 tasks, the human brain just cannot cope with it. As someone who worked as a kindergarten educator in an earlier life, I know exactly how children react when they are met with more than two tasks at once. We are not much different as adults. The ceiling on parallel context is lower than we like to admit.
One too many times it happened: I open a minimized terminal window, find three tabs all mid-session on completely different things, waiting for my input, and realize I forgot about all of them hours ago. That is when I close the laptop for the day.
There is also a more structural problem. Agents are, as Mario puts it, merchants of complexity. They have absorbed enormous amounts of bad architectural decisions from their training data, and they will reproduce that complexity with confidence if you let them. Every session they produce the same categories of errors, because unlike a human, they do not learn from being corrected last time. A human is a bottleneck. Even a bad engineer can only introduce so many problems per day, and the pain of a growing mess eventually becomes visible and gets addressed. An agent has no such natural ceiling. Without a human actively reviewing the output and enforcing a standard, small problems compound at a rate that is genuinely unsustainable. You only feel it when it is already too late to recover quickly.
The agents do not know when to stop. They do not know when they took a wrong turn three commits ago. They do not have taste, and they do not have doubt. They will keep discombobulating[^4] confidently in the wrong direction until you intervene. That is your job now. And you cannot do that job if you are spread across 15 sessions you have not actually read.
In "Everything We Got Wrong About Research-Plan-Implement", Dex Horthy also makes clear that they were wrong about "It's okay to not read the code". It's not.
Mario's practical answer is blunt: set a daily limit on how much code you let the agent generate, calibrated to how much you can actually review. Anything that defines the core of your system, the architecture, the APIs, the data model, write it yourself. Or at minimum, do it in tight back-and-forth with the agent rather than just handing it off entirely. The friction of writing or closely reviewing that kind of code is not a cost, it is the mechanism by which you understand what you are building.
We are all now not just doing the job of one engineer. We are managing a small team of engineers: endlessly capable, but also endlessly stupid. A team lead who does not understand what their team is building is not a team lead, they are a bottleneck with a title. The same applies here. Throughput is not the goal. Understood output is.
The supervision paradox bites hardest at this point. The more you outsource without staying in the loop, the less equipped you are to catch the moment things go off the rails. And they will. The session that saved you two hours yesterday is the session that will cost you four hours tomorrow if you were not paying attention.
The scarce resource is not tokens. It is attention, mine specifically. One session at a time. Read before you fire the next prompt. Know what was built before you ask for more.
Slow the fuck down. 💯
[^1]: Aider was more or less the first agentic engineering tool I ever touched
[^2]: Kyle Mistele from Humanlayer writes more on this here.
[^3]: /grill-me is a skill by Matt Pocock that interviews you relentlessly about your plan until you reach shared understanding, walking down each branch of the decision tree. A good fix for the magic words trap, though not a complete one. /grill-with-docs does the same, but uses ADRs, existing docs, and creates them on the go.
[^4]: one of the many Claude Spinner Verbs
[^5]: I refer to CLI tools like Pi and Claude Code as agent harnesses