Skip to content

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
Intermediate · practicalDevelopers

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.
A coding laptop beside a notebook of test results
Illustration: AI Ping

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.

  1. 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
    ItemVagueSpecific
    GoalFix loginFix 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.

  1. 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.

    A code note with two repeated send marks
    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
    StepAsk forDone when
    1A test that reproduces the bugThe test fails
    2Fix the cause of the duplicate sendNew and existing tests pass
    3Handle two simultaneous requestsA concurrent-request test passes
    4Tidy logs and commentsChanges 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 code
    import 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"); });
  2. 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.
  3. 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.
  4. 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.

    Before-and-after code notes with one duplicate line removed
    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.

  1. 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.

  2. 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.

  3. 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.

  1. 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.

Contents

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. Skipping does not mark a lesson complete.

References

Keep learning