AI takes the path of least resistance.

That one characteristic explains most of what changed for me about architecting a system once an agent was in the loop.

It is genuinely faster than I am on frameworks, patterns, and the standard way to wire something up. Since it has read more on them than I have. But "least resistance" means it optimizes for the thing in front of it, e.g., getting an endpoint to work or a test to pass. It cannot optimize for the shape the system needs for your use case because it does not know all details. You still own 100% of that part.

Two ways least-resistance goes wrong

Left alone, the path of least resistance breaks in two opposite directions. It cuts a corner to make the immediate thing work: collapses a boundary, hardcodes a value, skips the seam that would have let two pieces move independently later. And when you try to correct it, it will over-engineer and reach for patterns, layers, and abstractions you did not ask for and don't need yet.

Both come from the same place: it is solving the prompt, not steering the architecture.

Here is the version I lived with. My app is layered the usual way: an API layer, a service layer under it, a data-access layer under that, with clear rules about what each one is allowed to do. Database transactions belong in the service layer. The agent kept ignoring that. Commits I had scoped to the service layer kept turning up in the data layer, or up in the API. The worst one was a transaction that opened in the service layer and got committed two layers down. If left at simple prompts, it will run and deliver you something that works, but you'll find that along the way it has quietly broken the boundary and created a brittle system.

Here is the flip side, from just the other day. I was working on a bug fix with the agent on its own branch off main. Mid-test, I hit a separate gap, related to the feature but not the bug, and asked the agent to fix that too. It sensibly put the gap on its own branch, but branched off main instead of off the bug-fix branch, and I missed that. Both were named fix/..., so at a glance nothing looked off. It made the change and, per my workflow, asked me to test before it committed. The gap was handled well, but the bug was back. When I flagged it, the agent agreed: of course, that's expected since this branch came off main.

So I asked it to reconcile the two. The plan it came back with made my head spin: commit the work on the stray branch, rebase that onto the bug-fix branch, fast-forward the target, delete the stray branch, then re-verify the whole thing. But nothing was committed yet. The entire fix was three commands: git stash, switch to the bug-fix branch, git stash pop, then commit on the right branch. When I asked why not just do that, it agreed at once: "you're right, that was over-engineered."

A cut corner does not stay cut

This is the part that surprised me. Even when there was a good reason at the time, a cut corner does not stay a local mistake. Future sessions keep finding it and repeating it. The agent reads the current state of the code, sees the shortcut, and treats it as the pattern to follow. Murphy's Law seems to be in full play here. You'll have 10 good examples it could have followed, but it will find the one that it should not.

That boundary problem was exactly this. It was not a one-time slip. The agent generated code that broke the layering over and over, every session, and every time I had to catch it and send it back. Early on I would just fix it by hand. That was the mistake. Fixing it myself did nothing to stop the next session from doing it again. So I stopped hand-fixing and started making the agent fix it and write the rule down, where the next session would read it and follow it. But it still is not 100% foolproof.

Two things turned it around:

  • Plan reviews and a convention check became a fixed part of my workflow. Until they were, a lot of my attention was going to catching these leaks instead of the actual work. Once they were in the loop the leaks mostly stopped, and I ran a dedicated cleanup milestone to fix the ones that had already slipped through.
  • Isolation. I keep a full separate system-test stack and a dev stack for manual testing, non-negotiable. For anything parallel, I use worktrees, so each line of work has its own isolated stack and nothing bleeds across. Exploration you leave sitting in the main context is exploration the agent keeps copying, so keep the main context clean.

The rhythm I settled into on new work: experiment, clean up, then move on. The cleanup is not optional. It's what stops today's throwaway work/context from unintentionally becoming part of your conventions.

You bring the vision; it fills in the frameworks

The division of labor that works for me:

  • You own the judgment calls and the direction. State the bigger vision up front, even if you don't have every detail yet. AI can help you work out the details, but only against a destination you have set.
  • It knows the frameworks; it does not know your context. It's more up to speed than we are on approaches and trade-offs in the abstract. It does not know your constraints, your users, your history, any of it, until you tell it.
  • When it hands you a choice you don't understand, make it explain. Don't rubber-stamp an approach because it sounds authoritative. Ask it to walk you through the options and the trade-offs, then you decide.

Example: When it was time to integrate LLMs into the product I was building, I decided to make it a plugin-based system that could be driven via configs and specs. I spent a good amount of time going back and forth with it on requirements and goals. After many iterations, I had a design for an aspirational system that was the shape I wanted. Then we went back and forth on pieces that we would build now and others that would come later as needed. And then I asked it to add a lever: because it all deploys to a single container anyway, it can run the code built in instead of loading plugins every time. The agent was fine building the plugin machinery, but it would not have warned me that the pure-plugin path is a very painful operational choice.

AI can build it. You still need to define precisely for it and own the decisions.

Destination and constraints first, then a phased plan

The biggest shift is where I start. Not "let me build this piece and figure the rest out later." That's how you get architected into a corner.

Start with where you want to go and what bounds you: resources, timing, process. Then work out a phased plan to get there, and write it to disk as it evolves. Don't wait for the plan to be final before it exists on paper. A plan being figured out in the open is worth more than a perfect one still in your head, and the document keeps the history of the decisions. When you need to change something later, it tells you why it was done that way, which is exactly what you likely have forgotten by then.

A phased plan that paid off: Coming back to the same example, the AI service started as a library, imported straight into the app. Then I needed a second app that wanted almost all the same prompts. The quick path was to import it as a library again. Instead, I set the goal for the service to stand on its own over HTTP so any app can share it, and phased the way there. Stand it up as a microservice. Build the new app against it over HTTP. Keep the original app on the library path behind a flag. Prove the HTTP path works with the new app first, then migrate the original app over. The flag meant nothing broke while the new shape was still being proven.

What I keep

Architecting with AI did not lower the bar on judgment. It raised it. And it's very empowering if used correctly. For me, the agent removed the friction that used to slow me down, but it cuts both ways: because it does not have context (either you didn't specify or it rolled out of the current window), it's just as likely to speed you toward the wrong structure as the right one. The direction has to come from you, stated early, written down, and enforced.

I am still refining how much of the planning to hand over and how much to keep in my own head. But organizing your own thinking pays off in spades: get that right, and you can get the agent to follow as well.


A note on tools: I keep this deliberately tool-agnostic. Where it matters, I mean "the agent" generically. The models and tools are moving fast, so anything specific here is a snapshot, not a verdict.