Getting good results from AI coding assistants
Give context, work in small steps, verify with tests — a workflow that makes AI-written code something you can trust.
About 17 min readingAs of Oct 2026
Lesson guide · goals & preparation
By the end of this guide
- Write requests with a goal, constraints and a definition of done, so the assistant stops changing the wrong things.
- Have it write a test that reproduces the bug first, so you can judge its fix objectively.
- Know what to ask when it reviews code, and what to check yourself.
Who this is for
- Developers who find AI coding tools hit-or-miss
- Teams evaluating AI coding tools
What you need
- An AI coding tool (editor plugin or terminal agent)
- A project where you can run tests
This reading lesson explains how to use external AI tools. Read from theory to the workflow, examples and explanations, or use the contents to jump to a section.
1 / 4
Theory
Understand what to ask AI to do, how to ask, and the ideas behind the workflow.
State the goal, constraints and definition of done
Suppose one reset-button click appears to send two messages. Define what “once” means: a click, a server request and a mailer call are different events. This exercise isolates two mailer calls within one function invocation.
No account or mail service is connected. A fake mailer appends to an array, and user@example.com is a test string. This is an editorial reproduction exercise, not a report about an actual repository defect.
Provide the assistant with the relevant file, input, expected result and observed result. Remove secrets and personal data from any real logs and respect approved scope. Start with the smallest relevant files.
The same task, asked vaguely and specifically Item Vague Specific Goal Fix login Fix password reset emails being sent twice Scope (none) src/auth/reset.ts, src/mail/send.ts Constraints (none) Don't change the email template or the public API Done when (none) One email per reset request; existing tests pass Example prompt Goal: fix password reset emails being sent twice Files: src/auth/reset.ts, src/mail/send.ts Constraints: don't change the email template or the public API Done when: one email per reset request, and existing tests pass
2 / 4
Step-by-step use
Learn what to prepare, how to request help and how to revise the result through examples and explanations.
Ask in small steps
Save the reproduction as mail.test.mjs and run node --test mail.test.mjs. It uses Node’s built-in test runner, with no mail account or extra library. The last two lines of the function record the same message twice.
Figure: A code note with two repeated send marks · AI Ping Ask the assistant to locate the duplicate while preserving arguments and message text. Success means one recorded mail per function call. Renaming unrelated code or adding a global sent-mail list is unnecessary here.
A plan needs reproduction, a minimal repair and rerunning the same check. File-count limits do not guarantee a safe change; explain how each edit addresses the failure.
One bug, split into reviewable steps Step Ask for Done when 1 A test that reproduces the bug The test fails 2 Fix the cause of the duplicate send New and existing tests pass 3 Handle two simultaneous requests A concurrent-request test passes 4 Tidy logs and comments Changes stay within the two files Example prompt Don't change any code yet. First show me a plan that splits this into easy-to-review steps, with how to check each step is done.
Worked example & explanation Before repair, this must fail with expected 1 and actual 2. It is not a production password-reset endpoint and implements neither tokens nor network delivery.
Example codeimport test from "node:test"; import assert from "node:assert/strict"; async function requestPasswordReset(email, { mailer }) { const message = { to: email, subject: "Practice reset" }; await mailer.send(message); await mailer.send(message); // Intentional practice bug } test("one recorded mail per invocation", async () => { const sent = []; const mailer = { async send(message) { sent.push(message); } }; await requestPasswordReset("user@example.com", { mailer }); assert.equal(sent.length, 1); assert.equal(sent[0].to, "user@example.com"); });Have it write the test first
Confirm that the assertion reports two messages. A syntax error or missing module is not reproduction of the duplicate-send bug. If the test passes immediately, check which file and function ran.
Remove one duplicated await mailer.send(message) line. Changing the expected count to two or counting only the first element merely redefines the defect as acceptable. Preserve the requirement when editing tests and code together.
Rerun the same test and keep the recipient assertion. Hard-coding a recipient to make the count pass creates another bug. In a real repository, then run the relevant existing checks.
Example prompt Before changing anything, write a test that reproduces the duplicate reset email. It should fail against the current code.
Check it
- Record failure at two messages before repair and success at one afterward.
- Explain the result in terms of the single removed duplicate call.
Let it review, but make the call yourself
Treat concurrency and delivery-failure findings as claims to investigate. This fixture covers duplication within one invocation, not double clicks or network retries.
Make the fake mailer throw and verify that the function fails. Swallowing the error and returning success hides a failure. A global “already sent” flag can wrongly block a legitimate later request.
Real deduplication needs request identity, storage constraints, retry policy and delivery-system behavior. Recording after delivery leaves a crash window for duplicates; recording before delivery leaves one for omissions. This one-line repair does not establish delivery guarantees.
Example prompt Review the change you just made. Pay particular attention to two requests arriving at once and to the email send failing.
Worked example & explanation Review questions: is this a retry of the same request or a new request? Did delivery fail, or only its response? This fixture lacks the storage and network evidence needed to answer, so record them as follow-up design questions.
Check it
- Don't take the findings on trust: turn each case into a test and see whether it actually reproduces.
- Changes that touch security, payments or personal data get a human review as well.
Read the diff and check scope
The diff should remove one duplicate send. If the assistant restructures the function, ask why. Unrelated formatting, wording or dependency changes expand review without proving this repair.
Figure: Before-and-after code notes with one duplicate line removed · AI Ping A useful note says: removed the duplicate send within one invocation; confirmed one entry with a fake mailer; did not test a live service or concurrent requests. That is a precise account of evidence.
Customer-facing release requires its own version and recovery decisions. This exercise stays inside a local file. Do not extend the meaning of an isolated passing check to production delivery.
3 / 4
Check & explain
Think about what you would ask AI, then read the explanation. Written submissions and external AI use are optional.
This is a learning check, not a test you must pass. Use the explanations to understand the ideas.
Q1The test passes after changing the expectation from 1 to 2. Is that a repair?
Write your thoughts (optional)
Your writing is not sent anywhere. It disappears when you leave or reload this page, so copy anything you want to keep.
Read the answer and explanation
No. The requirement is one mail per invocation; changing the expectation accepts the defect. Remove the duplicate call and keep the original criterion. These counts are fixture conditions.
This is your own review, not an automatic score.
Q2Does a “module not found” failure reproduce the bug?
Write your thoughts (optional)
Your writing is not sent anywhere. It disappears when you leave or reload this page, so copy anything you want to keep.
Read the answer and explanation
No. The function under test never ran. Fix the setup and confirm the failure is specifically caused by two recorded messages.
This is your own review, not an automatic score.
Q3Can a passing fixture establish exactly one delivery under concurrent requests?
Write your thoughts (optional)
Your writing is not sent anywhere. It disappears when you leave or reload this page, so copy anything you want to keep.
Read the answer and explanation
No. It covers duplication within one invocation. Concurrency and retries require separate design and verification across request identity, storage and the delivery system.
This is your own review, not an automatic score.
Common mistakes
- Pasting files that contain API keys or passwords
- Handing over work too large to review
- Merging because it "seems to work," without tests
Your learning record
Completion is optional. Mark this lesson when you feel ready, or move to the next lesson without marking it.
Completion is saved in this browser.
4 / 4
Apply to your work
Consider how new material changes the workflow and checking criteria. Trying an external AI tool is optional.
Try it: add a second check
Keep the first test and add a second recipient with a fresh fake mailer. It should catch an incorrect hard-coded user@example.com recipient.
Then make send throw and assert that requestPasswordReset rejects. Test whether failure reaches the caller, not whether its wording looks nice. No network mail is sent.
Record the normal, alternate-recipient and failing-mailer outcomes. Ask for a change description, then remove claims such as “all duplicate delivery solved.” Completion reports must match the evidence too.
Write a note (optional)
Use this only if you want to record a prompt or your understanding. This is a notebook, not a connected AI assistant.
Your writing is not sent anywhere. It disappears when you leave or reload this page, so copy anything you want to keep.
References
- Best practices for Claude Code — Claude Code Docs (Anthropic)
- Best practices for using GitHub Copilot — GitHub Docs
- API key best practices: keep your keys safe and secure — Claude Help Center (Anthropic)