The Pattern That Works: Human Judgment Plus AI Execution
The Problem
When I first started using AI for coding, I asked it questions like “what should I do?” or “how should I structure this?” The AI would respond with options, possibilities, and vague suggestions. It felt like spinning in place.
Here’s what a typical interaction looked like:
Me: "How should I handle the threading model for this epoll system?"
AI: "There are several approaches you could take:1. One epoll per thread with thread-local storage2. Shared epoll with mutex locking3. Event-driven architecture with a central dispatcherEach has pros and cons..."This was frustrating. I wanted answers, not a textbook. I had working code to ship, not philosophy papers to write.
Then I noticed something. When I gave the AI precise direction instead of asking for options, it executed flawlessly. The difference was in how I framed my requests.
The Solution: Direction, Not Questions
The effective pattern I discovered is simple but powerful:
Human discovers problem → Human defines constraint → AI executes changes → Human reviews resultsLet me show you what this looks like in practice.
Example 1: Thread-local epoll
I was working on an NGINX-like server where each thread needed its own epoll instance. The existing code passed epoll file descriptors around everywhere, creating complexity.
Instead of asking “how should I handle this?”, I told the AI:
Me: "Each thread has exactly one epoll. The epoll should be thread-local storage.Remove the fd parameter from all epoll-related functions."That one sentence—each thread has exactly one epoll—gave the AI everything it needed. The AI:
- Created thread-local storage for epoll
- Rewrote all epoll interfaces to use thread-local instead of parameters
- Found and updated every call site across 10+ scattered locations
- Removed the fd parameter from every function signature
Zero compilation warnings. All references updated. Consistent patterns throughout.
A human might miss one of those 20 changes. AI won’t. But the prerequisite was that I gave it an accurate judgment.
Example 2: Architectural Refactoring
Later, I noticed a field in the conn structure that didn’t belong there:
Me: "This field shouldn't be in conn. It belongs to a new concept called http_peer.Create the new struct, move the field, update all references."The AI:
- Created a new
http_peerstruct - Moved the field with correct type and initialization
- Found all 20+ references across 6 files
- Updated each reference to use the new struct
- Maintained all existing behavior
Again, zero missed references. Clean refactoring. The constraint “belongs to http_peer” gave the AI architectural direction, and it derived all specific changes.
Why This Pattern Works
AI Without Direction Spins in Place
When I ask AI “what should I do?”, it can’t make decisions. It lists options because it lacks context about my goals, constraints, and architecture. This is a feature, not a bug—the AI is being appropriately cautious.
But when I give a constraint like “this layer shouldn’t know about the layer above”, the AI has direction. It can derive specific changes from that principle without asking for permission at each step.
The Constraint → Execution Flow
BAD APPROACH: Question: "How should I refactor this?" Result: Options, possibilities, no decision made Human: Still has to decide and specify every change
GOOD APPROACH: Constraint: "This layer shouldn't know about the layer above" Result: AI derives all specific changes Human: Reviews the output, corrects if neededThe leverage is massive. One accurate judgment propagates across dozens of files through AI execution.
Wrong Direction Propagates Errors
But there’s a catch. Wrong direction efficiently propagates errors across your entire project.
I learned this the hard way when I told the AI to “make all functions static by default”. It did exactly that—breaking a dozen tests that relied on internal functions being accessible for mocking. The AI executed my constraint perfectly. The constraint was wrong.
This is why review matters. You’re not reviewing code for syntax errors. You’re reviewing whether your direction was correct.
The Full Workflow in Practice
Here’s the complete workflow I use:
1. DISCOVER: Human notices architecture problem Example: "fetch creates a new epoll for each call—that's pseudo-async"
2. DIRECTION: Human defines the constraint Example: "Global event loop + pending Promise architecture"
3. EXECUTE: AI makes all specific changes - Modifies 9 files - Updates all async interfaces - Maintains consistency across codebase
4. REVIEW: Human validates results - Tests pass ✓ - Performance improved ✓ - Architecture cleaner ✓
5. CORRECT: If needed, refine direction and loopReal Performance Results
After applying this workflow to the fetch concurrency problem:
Before: fetch creates new epoll per call → 905ms for concurrent operationsAfter: global event loop + pending Promise → 302ms for concurrent operationsThe performance improvement came from my architectural judgment (global event loop), not from AI magic. The AI just executed that judgment across 9 files without missing anything.
Common Mistakes I See
Mistake 1: Asking Instead of Telling
WRONG: "What's the best way to handle threading?"BETTER: "Use thread-local storage for the connection pool. Each thread has its own pool."The first question produces discussion. The second constraint produces code.
Mistake 2: Micromanaging Implementation
WRONG: "On line 45, change the variable name to connectionPool. Then on line 52..."BETTER: "Rename this variable to reflect that it's a pool, not a single connection."When I micromanage, I limit the AI’s ability to find better solutions. Constraints give direction; implementation details emerge from that direction.
Mistake 3: Skipping Review
Just because AI is smart doesn’t mean I can skip review. I review for:
- Direction correctness: Did I give the right constraint?
- Scope creep: Did AI make changes I didn’t ask for?
- Test coverage: Did AI update tests along with code?
- Edge cases: Did AI handle error paths correctly?
Mistake 4: Using Weak Models for Architecture Changes
For simple refactoring, any model works. For architectural changes that require understanding context across multiple files, I use the strongest model available.
The difference is huge. Weak models miss context and make inconsistent changes. Strong models understand that changing one struct affects 20 files and handle all of them correctly.
Practical Tips From Experience
Build Judgment Through Practice
The leverage of this pattern depends on the quality of my judgment. Judgment comes from:
- Reading professional code
- Working with experts who explain their reasoning
- Making mistakes and learning from them
- Understanding system architecture at a deep level
AI cannot substitute for this. It amplifies good judgment and bad judgment equally.
Review Tests, Not Just Test Results
When AI makes changes, I don’t just run tests. I review the tests themselves. Did AI update tests to match the new architecture? Did it add tests for new code paths? Tests are code too, and they need to reflect architectural changes.
Use Code Review as Learning
After AI executes my constraint, I review the diff. I learn from how AI solved problems I might have approached differently. This improves my future constraints.
Keep Constraints Atomic
One constraint per request works better than multiple constraints. If I need to make two architectural changes, I do them in sequence:
Step 1: "Create http_peer struct and move relevant fields from conn"Step 2: "Add connection pooling to http_peer with max 10 connections per peer"Each step gets reviewed before the next. This catches direction errors early.
When to Use This Pattern
This pattern works best when:
- I understand the architecture and can give accurate constraints
- The change affects multiple files or locations
- I know what the result should look like but not every implementation detail
It works less well when:
- I’m exploring what architecture to use
- I need the AI to suggest options for a complex tradeoff
- The problem domain is new to me and I need education
For exploration, I use a different approach: conversation and prototyping. For execution, I use constraints.
Summary
In this post, I showed the effective pattern for AI-assisted development: human discovers problem, thinks through direction, gives AI precise constraints, reviews results, corrects if needed.
The key insight is that AI excels at execution when given clear architectural direction. One sentence like “each thread has exactly one epoll” enabled AI to correctly modify 10+ scattered locations with zero warnings. But wrong direction efficiently propagates errors across the entire project.
The future of programming isn’t writing code—it’s making judgments. One accurate judgment, amplified by AI, can touch dozens of files. But judgment must come from human experience, reading code, and working with experts.
Next steps:
- Next time you use AI for coding, try giving constraints instead of asking questions
- Review AI output for direction correctness, not just code correctness
- Build your judgment muscle by reading professional code and working with experts
- Use stronger models for architectural changes that require context understanding
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 NGINX Engineer's Experience with AI Coding
- 👨💻 Claude Code Documentation
- 👨💻 AI-Assisted Development Best Practices
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments