Everyone's talking about AI coding. Most of the conversation is theoretical.
I've been shipping production software with AI assistance since 2022 — when ChatGPT was brand new, and when this was genuinely weird. In that time, I've built many products, including (most recently) security APIs processing real transactions, marketing automation systems, and a 360-degree agent security toolkit.
Along the way, I've learned that the practices matter more than the model. Here's what actually works.
The 66% Problem
Stack Overflow's 2025 survey found that 66% of developers spend more time fixing "almost-right" AI-generated code than they would have spent writing it themselves.
I've seen what happens when developers skip the discipline. But I learned early to avoid that trap.
In late 2022 into 2024, I wasn't letting AI write directly into my codebase. I'd generate code for specific problems, cut and paste it in myself, study how it worked, and test relentlessly — at the file level, unit level, and system level. The pain wasn't shipping code I didn't understand. The pain was working with a minuscule context window where the AI had almost no understanding of my full codebase. I could only trust it to develop specific functions, one file at a time.
That limitation forced discipline. I couldn't let the AI loose on my system because it literally couldn't see most of it. So I stayed in the driver's seat, treating AI as a code generator I had to validate and integrate manually.
The context windows got bigger. The tools got better. But those early lessons still serve me today. Here's what actually works.
Practice 1: Questions Are Your Superpower
The biggest reason developers ship code they don't understand? They don't ask questions.
AI is an incredible teaching tool. I constantly ask:
- "Why was this decision made?"
- "How does this work under the hood?"
- "Show me the technical details."
- "Develop a mockup of the data flow."
- "What happens if this input is malformed?"
Deep, detailed questions. Not "does this work?" but "explain to me exactly what happens when X calls Y."
This serves two purposes: I understand the code, and I catch mistakes before they're committed. When the AI can't explain something clearly, that's a red flag that it doesn't understand either.
Practice 2: Never Auto-Accept Mission-Critical Code
For anything that matters, I watch the AI work in real time. I read every line as it's being generated. When I see it heading in the wrong direction, I interrupt and correct course.
This single practice has saved me more debugging time than any other.
The instinct is to let it finish and review later. Don't. By the time it's done, you're reviewing 2000 lines and the context of each decision is gone. But watching it write 20 lines and catching the third line that's wrong? That's a 10-second fix instead of an hour of debugging.
Auto-accept is for boilerplate. Anything else, you watch.
Practice 3: Start by Integrating, Not Generating
When AI coding tools first emerged, I didn't have the agent write code directly into my codebase.
Instead, I had it generate code, then cut and paste it in myself — essentially using AI like Stack Overflow. I'd read the code, understand it, decide where it fit, and manually integrate it.
This taught me crucial lessons about what AI does well (boilerplate, patterns, syntax) and what it doesn't (architecture, edge cases, your specific codebase conventions). More importantly, it kept me in control.
That early discipline is why Practice 2 now works for me. I trained myself to read and evaluate AI code before it became habit to just accept it.
If you're new to AI coding, start here. Generate, review, integrate manually. Build the muscle of evaluating AI output before you let it touch your codebase directly.
Practice 4: Think Like a Systems Engineer
AI excels at implementing individual functions. It struggles with how pieces fit together.
That's my job.
Before asking AI to implement anything, I think through:
- How does this feature connect to existing systems?
- What data flows in and out?
- What other components will this affect?
- Where does this fit in the overall architecture?
The AI doesn't have the full picture of your system. You do. If you don't do this thinking, no one will — and you'll end up with a codebase of individually-correct components that don't work together.
Practice 5: Limit Scope Ruthlessly
I never have an agent develop anything top-to-bottom for me. Never.
Instead, I develop individual features with the agent:
- Plan it — What exactly are we building?
- Discuss it — How should it work? What are the edge cases?
- Ask questions — Many, many questions before implementation
- Review proposed code — Have AI generate example code during discussion
- Then implement — One feature, one piece at a time
It's more than a spec. It's a conversation to ensure the final output is what actually works. By the time implementation starts, I know exactly what the code will look like because I've already seen drafts during the discussion phase.
Practice 6: Relentless Systems Testing
Unit tests are often inadequate. They test that a function does what the function does — which tells you nothing about whether it works in your actual system.
For every feature, I create multiple types of tests:
- Does it work in isolation?
- Does it integrate correctly with existing code?
- What errors appear that shouldn't?
- What was accidentally reverted or broken?
- Does it handle real-world inputs, not just happy-path test data?
I'll often conduct at least 5 different system and integration tests for a single feature before considering it done.
The feature-first development approach (Practice 5) is vital here. When you're developing one feature at a time instead of letting AI build an entire application, you can actually test each piece thoroughly.
Practice 7: Build Shared Understanding Before Implementation
Programming is problem-solving. The code is just the output.
Before touching code, I have extended conversations with the AI to build a shared understanding of the problem. Not just "what should we build?" but deep exploration:
- Have the AI read and summarize the relevant modules
- Ask it to diagram the data flow and architecture
- Run diagnostic tests together to understand current behavior
- Identify what's working, what's not, and why
- Explore options and tradeoffs together
Here's what this looks like in practice. Before improving my ML LLM attack classifier's detection rate, I had the AI:
- Map out the entire pipeline architecture (client → server, what each layer contributes)
- Run tests to check what the ML model was actually detecting vs. missing
- Analyze what features the model was trained on vs. what it needed
- Identify gaps in the training data (attack patterns that existed but weren't included)
- Propose a plan to expand training data while maintaining balance
Only after this exploration — after both the AI and I understood the current system, the problem, and the solution — did we write any code.
This creates a shared baseline. The AI understands the context. I understand the approach. By the time implementation starts, I've already seen example code during the discussion, asked questions about it, identified issues, and refined the approach. The actual implementation becomes almost mechanical.
Practice 8: Automate What AI Misses
AI is not reliable for security review. It can miss SQL injection, XSS vulnerabilities, hardcoded credentials, and other OWASP top 10 issues that deterministic scanners catch every time.
I run automated security scanning as part of standard CI/CD discipline:
- Static analysis that flags dangerous patterns
- Dependency vulnerability checks
- Pre-commit hooks that block obvious security issues
These aren't AI-powered. They're deterministic pattern matchers that catch the same vulnerability the same way every time. No hallucinations, no missed edge cases, no "I didn't notice that."
The value is catching what's lurking in the code that neither you nor the AI were thinking about. You're focused on the feature. The AI is focused on what you asked. Neither is systematically checking for injection attacks in that database query you wrote three files ago.
Automated scanners don't replace security expertise. But they're a reliable safety net that catches the obvious issues before they ship.
What I've Shipped Using These Practices
These aren't theoretical. Using them, here's some of what I've built:
- AI Security Guard — A security scanning API with 5 specialized ML/NLP detection experts, processing real x402 micropayment transactions
- AgentGuard 360 — An upcoming 360-degree security toolkit for AI agents with device hardening, content scanning, and operations visibility
- Marketing automation — Internal frameworks with deterministic systems, including a purpose-built CRM, smart post generation and scheduling, automated lead detection and nurturing, and a content generation system that has produced AI-powered educational and strategic content that has been viewed nearly 2 million times
All production. All with AI assistance. All with these practices.
The Meta-Lesson
The developers who thrive with AI coding won't be the ones who use AI the most. They'll be the ones who develop the discipline to use it well.
AI doesn't replace engineering judgment. It amplifies whatever judgment you bring. Good practices + AI = production software. No practices + AI = technical debt factory.
Build the discipline.
I'm building AI Security Guard — security scanning for AI agents. If you're working with MCP, tool-using agents, or any AI that processes untrusted content, check out aisecurityguard.io/v1/skill.md.
Top comments (0)