Three levels of assistance
| Level | What it does | What you must supply |
|---|---|---|
| Completion | Finishes the line or block you're typing | Direction, constantly |
| Conversation | You describe a change, it returns code you paste | Context and judgement |
| Agent | It reads files, edits them, runs commands, iterates | A precise goal and a real review |
Moving down the table increases leverage and increases the cost of an unnoticed mistake. Completion errors are visible immediately. An agent working for twenty minutes can produce a large, confident, plausible change that is wrong in a way you'll only find in production.
What to delegate
The reliable division: delegate work where the correct answer is well known and the tedium is in the typing. Keep work where the difficulty is in deciding what correct means.
- Delegate — boilerplate, tests for existing behaviour, format conversions, regex, config files, repetitive refactors, first drafts of documentation
- Delegate carefully — a new feature in a well-established pattern, in a codebase it can read
- Keep — data models, security boundaries, anything touching money, and any decision that will be expensive to reverse
Writing a request that works
Most poor output is a poor request. The difference between the two versions below is the difference between something you rewrite and something you keep.
Weak: "Write a function to validate emails" Strong: "In this TypeScript file, add a function that checks whether a string is a plausible email address. Return a discriminated union { ok: true } | { ok: false, reason: string }. Don't add dependencies. Don't try to be exhaustive about the RFC — we send a confirmation email anyway. Match the existing style in this file."- Say where the code goes and what's around it
- Say what the output shape must be
- Say what not to do — new dependencies are the most common unwanted addition
- Say what the code is for, so it can make the right trade-off
Reviewing what comes back
Generated code arrives looking finished. It has consistent naming, comments, and error handling, and it reads like a competent colleague wrote it. That surface quality is uncorrelated with whether it's correct, and it makes review harder than reviewing a human's rough draft.
- Read the edges firstEmpty input, missing values, failed network calls. The happy path is nearly always fine; the edges are where confident guessing shows.
- Check every import and API call is realPlausible-but-nonexistent methods are a signature failure of this workflow.
- Check it fits your codebase, not the average codebaseIt may have introduced a second way of doing something you already do one way.
- Run it against a case you choseNot the case it suggested. Its example was chosen to succeed.
Common mistakes
- Accepting code you don't understand because it runs
- Asking for a large feature in one request instead of several reviewable steps
- Letting it add a dependency to solve a ten-line problem
- Reviewing generated code less carefully than a colleague's, because it looks tidier
- Using it to learn a subject and never verifying what you learned
Key takeaways
- Completion, conversation, and agents trade leverage against review cost
- Delegate the well-trodden; keep the decisions that are expensive to reverse
- Precise requests with constraints produce usable code; vague ones produce average code
- Review edges, imports, and fit — not the happy path
Try it yourself
Take a small function you wrote yourself and ask a model to write it from your description. Compare them line by line. The differences show you both what the tool assumes and where your description was ambiguous.
