How We Handle AI in Development



Like most software teams, we didn't have a policy for AI coding tools. We just started using them. And for a while, that felt like enough — because the early results were genuinely exciting.
This is the honest account of how our thinking evolved: from uncritical enthusiasm, through some hard-won frustration, to the grounded approach we practice today.
The Honeymoon Phase
When AI coding assistants first became useful, the appeal was immediate. You could describe an issue and get a working draft in seconds. Tickets that used to take half a day started landing in a couple of hours. The efficiency gains felt real and measurable.
We leaned in. Developers started reaching for AI as a first step, not a last resort. For a while, the feedback loop was positive: faster output, fewer context switches, more time for the interesting problems.
The code looked right. It compiled. The tests passed. And then, three weeks later, something broke in a way nobody could explain.
That was the first sign something was off. The bugs introduced by AI-generated code aren't always obvious bugs. They're the subtle kind — logic that almost makes sense, abstractions that almost fit your architecture, edge cases that almost get handled. They survive code review precisely because they look intentional.
Debugging them was expensive. More expensive, in several cases, than just writing the code by hand would have been. The efficiency gains we celebrated in the first sprint quietly disappeared in the third.
What We Got Wrong
The core mistake wasn't using AI. It was the implicit assumption that because the code came out quickly, the developer's responsibility for it was somehow reduced. It wasn't. If anything, it increased.
When you write code yourself, you understand it — by definition, in the act of writing it. When you accept code from an AI, understanding becomes a deliberate extra step that's easy to skip when you're in a hurry. And in our experience, that step is exactly when the subtle bugs get shipped.
Lesson learned: AI doesn't reduce the cognitive load of understanding what's in your codebase. It just decouples that load from the act of writing. You still have to carry it — just separately, and more consciously.
We also noticed that AI tools have a tendency to generate more code than necessary. Ask a simple question, get an entire scaffold back. That's not always helpful. More code means more surface area to review, more dependencies to understand, more places for something to quietly go wrong.
The Principles We Landed On
We didn't ban AI tools — that would have been an overcorrection, and frankly, most of our developers find them genuinely valuable. But we did get explicit about what responsible use looks like. Here's what that means in practice:
Human responsibility is non-negotiable. Every line of code that gets committed is owned by the developer who committed it — regardless of how it was generated. "The AI wrote it" is not a defence in a code review, and it's not an explanation for a production bug.
Understand before you commit. If you can't explain a piece of code to a colleague, you're not ready to merge it. AI output that you don't understand is a liability, not an asset. Read it. Think about it. Rewrite the parts that don't sit right.
Our code guidelines still apply, fully. AI doesn't always follow our conventions, our internal framework patterns, or the specific constraints of our architecture. Applying our standards isn't optional just because the first draft came from a model.
Proper human review is still required. AI-generated code gets the same review as human-written code — ideally more scrutiny, not less. Reviewers shouldn't assume it's fine because it looks polished.
Developers use what works for them. We're not prescriptive about whether or how AI is used. Some of our developers use it heavily and love it. Others barely touch it. Both are fine. The goal is good software, not uniform process.
Smaller Pieces, Better Results
One of the most practical changes we made was how we scope AI prompts. Early on, we'd hand a large, vague problem to a model and wait for it to produce something substantial. That almost never went well.
The better approach is divide and conquer. Before involving AI at all, break the problem down into its smallest meaningful pieces. Then, when you do prompt, you're asking for something narrow and verifiable — not a complete solution to a fuzzy requirement.
The goal is to have AI generate as little code as possible, not as much as it can.
This sounds counterintuitive — isn't the point of AI to write code faster? — but it turns out the real value isn't in volume. It's in filling the gaps in well-understood structures. The less you ask it to invent, the more useful what it produces tends to be.
AI That Stitches, Not AI That Builds
Our codebase is built on a collection of internal libraries, shared abstractions, and established patterns that the team has developed over years. AI tools don't know any of that by default. If you ask a model to build something from scratch in our stack, you'll get code that's technically plausible but architecturally foreign.
The framing that actually works for us: AI is at its best when it's stitching things together for a concrete use case, not architecting systems from nothing. It can take well-understood components and assemble them for a specific task. That's genuinely useful. Building entire features from scratch, with no grounding in our existing patterns? That's where things tend to go sideways.
One concrete example: we use Turborepo generators to produce boilerplate for new modules. Those generators are human-written, encode our conventions, and produce code we trust. What AI can help with is providing the parameters — filling in the specifics for a given use case. The scaffold comes from a tool we control. The AI contributes configuration, not structure.
The practical pattern: Use human-written generators for structure and human-written, well-defined components for reuse. Use AI to fill in the specifics and configure components. Keep the architectural decisions in human hands, and let AI handle the parts where the shape is already clear .
AI coding tools aren't going away, and we're not trying to resist them. But we've learned — sometimes the hard way — that the efficiency gains are real only when the discipline around them is also real. The developer is still the engineer. The review is still required. The understanding is still mandatory.
The tools change. The responsibility doesn't.