AI Pair Programming: How to Actually Work with an AI Coding Assistant
Treating an AI assistant like a search engine or like an infallible senior engineer both fail the same way. The working model that actually holds up: a fast, literal junior who needs precise direction and never gets tired of review.
Two failure modes show up constantly with AI-assisted coding: treating the tool as a search engine ("just tell me the answer") and treating it as an infallible senior engineer (trusting output without review). Neither mental model holds up. The one that does: a very fast, very literal collaborator who does exactly what you say — which means the quality of your direction and the rigor of your review are what actually determine the outcome.
A working session, structured
- Specify before generating. State the task, the constraints, and the expected shape of the output before asking for code — not after seeing a first attempt and iterating from vague to specific.
- Generate in reviewable chunks. Ask for one function or one focused change at a time on anything non-trivial, rather than a whole feature in one pass — a smaller output is a smaller thing to verify.
- Review before running, run before trusting. Read generated code the way you'd read a colleague's PR — then compile/run it. A plausible-looking diff and a working one are not the same thing.
- Ask for a self-critique pass on anything important. "Review this as a skeptical senior engineer — what edge cases or assumptions might be wrong" catches a meaningful fraction of first-pass mistakes before you do.
- Iterate on the prompt, not just the code. If the output is wrong, diagnose which part of your prompt was missing (context, constraint, example) rather than manually patching the output and moving on — the same gap will recur on the next similar task otherwise.
What to hand off vs. what to keep
| Hand off to AI | Keep for yourself |
|---|---|
| First-draft implementation of a well-specified task | Deciding what the task actually should be |
| Boilerplate, standard patterns, test scaffolding | The specific edge cases and business rules that make your system different from a textbook example |
| Explaining unfamiliar code, summarizing a large diff | Judging whether a change is actually a good idea for your system's constraints |
| A first pass at debugging, given good evidence | The final call on root cause when evidence is ambiguous — verify before accepting |
| Draft documentation, ADRs, PR descriptions | The actual decision the documentation is recording |
Not "the AI wrote bad code" — it's "nobody reviewed the AI-written code with the same rigor as human-written code." Generated code needs the same review bar as any other source, not a lower one because it looked confident and well-formatted.
When to NOT reach for AI assistance
- When you're trying to learn a fundamental concept yourself — using AI to generate the answer instead of working through it yourself trades short-term speed for long-term understanding you'll need later.
- For a change small enough that specifying it precisely takes longer than just writing it — a one-line fix doesn't need a prompt.
- When the task requires context that's genuinely faster to hold in your own head than to write out — sometimes the overhead of a good prompt exceeds the task's complexity.
This working model — specify precisely, generate in reviewable pieces, verify rigorously — is the practical core of everything the Foundations program teaches, applied across coding, debugging, testing, and documentation rather than left as an abstract principle.