Reading and reviewing AI-written code
AI code often runs and is still wrong. Learn a repeatable way to read it: run it, trace it, ask what could go wrong, test the edges and ask AI to explain or critique it. Practise on a real order-total function with hidden bugs.
In this tutorial you will review a small piece of AI-written code the way a professional reviews a teammate's code. You will find three real problems in a function that looks fine and works for the example the AI showed, then fix it and test the fix.
Prerequisites: Python 3 installed (run python --version; on some machines the command is python3), VS Code and a free AI assistant from *Set up your machine*. You do not need to be a Python expert; the code is short and every line is explained.
Why you must read the code
When AI writes code, you are the reviewer, even as a beginner. The code might run and still be wrong in ways that matter: charging the wrong amount, crashing on unusual input, or exposing data. You are responsible for what you ship, and a client or interviewer will ask "why did you write it this way?" "The AI did it" is not an answer.
You do not need to understand every symbol. You need a method.
The five-step review method
How to review AI code
- 1Run it with a normal example. Does it do what you asked?
- 2Read it top to bottom and explain each part to yourself. Mark anything you cannot explain.
- 3Ask what could go wrong: empty input, missing values, huge or negative numbers, wrong types, unknown ids, two users at once.
- 4Test the edges by actually running those cases.
- 5Compare with the spec: did it do only what you asked? Look for extra files, libraries or features.
The code under review
You asked an AI: "Write a Python function that calculates the total of a coffee order, given a list of items with item_id and qty." It gave this answer and an example that prints 240. Save it as order_total.py and run it.
# order_total.py
MENU = {"espresso": 120, "cappuccino": 180, "masala-chai": 90}
def calculate_total(items):
total = 0
for item in items:
price = MENU[item["item_id"]]
total += price * item["qty"]
return total
if __name__ == "__main__":
print(calculate_total([{"item_id": "espresso", "qty": 2}]))
print(calculate_total([{"item_id": "espresso", "qty": -5}]))
Looks up each item's price in MENU, multiplies by quantity and adds up the result.
python order_total.pyOn some machines use python3 instead of python.
240
-600The first line is right: 2 espressos at 120 is 240. The second line is the problem: a quantity of -5 gave a total of -600. A shop would owe the customer money. Running the happy path alone would never have shown you this.
Step 1 and 2: run and read
Read line by line:
- MENU = {...} is a dictionary from item id to price in rupees.
- for item in items: goes through each ordered item.
- MENU[item["item_id"]] looks up the price. If the id is not in MENU, Python raises KeyError.
- price * item["qty"] multiplies by quantity. Nothing checks that qty is sensible.
- return total gives back the sum.
The code is correct only when the input is perfect. Real input is not. This is where the next steps come in.
Step 3: ask what could go wrong
Risk questions and what this code does
| Question | What happens here | Problem? |
|---|---|---|
Empty list [] | Returns 0 | Yes: a free empty order is accepted |
Unknown item such as mocha | Crashes with KeyError | Yes: ugly crash instead of a clear message |
| Negative quantity | Negative total | Yes: serious bug |
| Quantity 2.5 or the text "2" | 2.5 gives a fractional total; "2" crashes with a TypeError | Yes: types are not checked |
| Where do prices come from? | The server's MENU | Good: prices are not taken from the user |
That last row is a good sign worth keeping. If the AI had accepted a price from the request, a customer could send a price of 1 rupee. Never trust totals or prices that come from the client. This idea returns in *Security pitfalls in AI-written code*.
Step 4: test the edges
Prove the problems exist by running them. Add this to the bottom of the file temporarily, or open a Python terminal and import the function.
print(calculate_total([]))
try:
calculate_total([{"item_id": "mocha", "qty": 1}])
except KeyError as error:
print("KeyError:", error)240
-600
0
KeyError: 'mocha'Step 5: ask AI to review and explain
AI is a good second reader if you ask it to critique instead of just agree. Ask for a list of problems, then judge them yourself; sometimes it will flag things that are not real issues.
Act as a strict code reviewer. Review the [language] code below, which is meant to [what it should do].
1. List real bugs and risky edge cases, most serious first, with a one-line example input for each.
2. List anything that is unclear or missing (validation, error handling, security).
3. Do not rewrite the code yet. I will ask for the fix after I check your findings.
[paste code]What to expect: A good review names negative quantity, unknown ids and an empty order, and gives an example input for each. Verify each claim by running it before believing it.
Explain the code below to a beginner, line by line. Then list any language features or functions I should look up in the official documentation, and 2 questions to test my understanding.
[paste code]What to expect: If the explanation mentions a function you cannot find in the official docs, treat it with suspicion; AI sometimes invents functions.
The fixed version
Now ask the AI to fix only the problems you confirmed, or write the fix yourself. This version checks the input before calculating and raises a clear error. Replace the contents of order_total.py and run it.
# order_total.py
MENU = {"espresso": 120, "cappuccino": 180, "masala-chai": 90}
def calculate_total(items):
if not items:
raise ValueError("Order must have at least one item")
total = 0
for item in items:
item_id = item.get("item_id")
qty = item.get("qty")
if item_id not in MENU:
raise ValueError(f"Unknown item: {item_id}")
if not isinstance(qty, int) or qty < 1 or qty > 20:
raise ValueError(f"Quantity must be a whole number from 1 to 20, got {qty}")
total += MENU[item_id] * qty
return total
if __name__ == "__main__":
print(calculate_total([{"item_id": "espresso", "qty": 2}, {"item_id": "masala-chai", "qty": 1}]))
for bad in ([], [{"item_id": "espresso", "qty": -5}], [{"item_id": "mocha", "qty": 1}]):
try:
calculate_total(bad)
except ValueError as error:
print("Rejected:", error)
Rejects an empty order, unknown ids and bad quantities, and still takes prices from the server's MENU.
330
Rejected: Order must have at least one item
Rejected: Quantity must be a whole number from 1 to 20, got -5
Rejected: Unknown item: mochaCheck the first number by hand: 2 espressos is 240 plus 1 masala chai at 90, which is 330. In a real API, those ValueErrors would become a clear "400 Bad Request" message for the customer, which you will build in the API project.
Keep your edge cases as tests
The edge cases you just ran are tests. In the *Test the API with AI-written tests* lesson you will turn them into automated tests so you never have to remember them.
A reading checklist for any AI answer
Before you accept the code
- I ran it and saw the result myself.
- I can explain every line, or I looked up what I could not explain.
- I tried empty, missing, negative, huge and wrong-type inputs.
- Imports and function names exist in the official docs or the project (no invented ones).
- No passwords, keys or tokens are written in the code.
- The AI did only what I asked: no extra libraries, files or features.
- I commit only after all of this passes.
Signs that AI code needs a closer look
Red flags
| Red flag | Why it matters | What to do |
|---|---|---|
| A library or function you cannot find in the docs | May be invented or outdated | Search the official docs; if absent, ask for another way |
| Secrets or URLs hard-coded in the file | Leaks when you share the code | Move them to environment variables |
| Prices, totals or user roles taken from the request | Users can fake them | Compute or check on the server |
| No error handling at all | Crashes on real input | Add checks and clear messages |
| Many files changed for a small request | Hard to review | Ask for the smallest change |
| Confident explanation but no way to run it | Might not work | Run it, or ask for a test |
Try it: Review a function of your own
Ask an AI: "Write a Python function apply_discount(total, code) for Brew & Bean. The code FIRST10 gives 10 percent off. Any other code gives no discount."
Then review it with the five steps. Try a negative total, a total of 0, the code in lower case (first10), None as the code, and a very large total. Write down every problem you find and fix at least one.
Key takeaways
- You are the reviewer of AI code; running the happy path is not enough.
- Use five steps: run, read, ask what could go wrong, test the edges, compare with the spec.
- Typical AI bugs: missing validation, trusting client data, no error handling, invented functions, extra features.
- Never trust prices or totals sent by the client; compute them on the server.
- Use AI as a second reader (ask it to critique), then verify its claims yourself.
- Turn the edge cases you try into tests, and commit only after they pass.
Check yourself
Finishing the quiz marks the lesson as done.
1. The function returned 240 for a normal order. Why is that not enough to accept it?
2. Why is it good that the code took prices from MENU on the server?
3. An AI review says your code has a bug in a function you have never heard of. What should you do?
4. Which request makes the AI a better reviewer?
5. Which is a red flag when reviewing AI code?
Saved on this device. Create a free account to keep it on every device.
Practise this with Sam
A real mock interview, out loud, with an honest scorecard. Free to start.