The AI-assisted coding interview
Questions in this set 6
- 01The interviewer says "you can use the AI assistant however you like." What do you do in the first two minutes?
- 02The assistant produces code that passes the test. Talk me through what you do before saying you are done.
- 03The assistant's answer is confidently wrong and you have spent six minutes on it. What now?
- 04We hand you an unfamiliar 4,000-line service and a bug report. Show us how you use the assistant on a codebase you have never seen.
- 05How do you use AI tools day to day, and where do you not?
- 06Does using an AI assistant well mean I need to know less?
This is the newest format in engineering hiring and the one candidates are least prepared for. Several large companies now run coding rounds with an AI assistant available, and a "code comprehension" round where you read, debug and extend an unfamiliar multi-file codebase with the assistant enabled.
The important shift: you are no longer scored on producing the code. The assistant can produce it. You are scored on prompting deliberately, validating output critically, debugging what comes back, and knowing when the suggestion is wrong. Candidates who lean on the assistant without demonstrating their own understanding receive explicitly negative feedback — that is the documented failure mode.
The interviewer says "you can use the AI assistant however you like." What do you do in the first two minutes?
Do not prompt first. Do this instead, out loud:
- Read the problem and restate it. Same as any interview.
- Orient in the codebase yourself — entry point, the module that owns the failing behaviour, the test that fails. Two or three minutes of your own reading buys you the ability to evaluate everything the assistant says afterwards. Skipping this is the single most damaging choice available to you.
- Say your plan before you prompt: "I'll use it to speed up the boilerplate and to explore this unfamiliar module, but I want to work out the fix myself because that's the part I need to be sure about."
- Then prompt with context and constraints, not with the raw problem statement.
That fourth point is where the observable skill is. Compare:
# weak — vague, unconstrained, invites a plausible-looking wrong answer
fix this bug
# strong — states the observed behaviour, the constraint, and what you want back
This test fails with `KeyError: 'region'` when the payload omits region.
`normalise_order()` in orders/transform.py assumes every key is present.
Suggest a fix that keeps the existing return shape and does not change the
public signature. Show only the diff for that function, and tell me what
edge cases it does not cover.The assistant produces code that passes the test. Talk me through what you do before saying you are done.
Review it as you would a colleague's pull request, out loud, in this order:
- Do I understand every line? If not, that is the first thing to resolve — either read it properly or replace it with something I do understand. Shipping code you cannot explain is the thing being tested for.
- Does it solve the actual problem or just satisfy the test? Assistants are very good at making a specific assertion pass. Ask what the test does not cover.
- Edge cases the test does not exercise: empty input, null, unicode, very large input, concurrent access, timezone, negative numbers, duplicate keys.
- Does it match the codebase? Assistants generate idiomatic-in-general code, not idiomatic-here code. If the repo has a
Resulttype, a logging convention, an error hierarchy, or a data-access layer, the suggestion probably ignored all of them. - Did it invent anything? A method that does not exist on that class, a package that is not installed, a config key that is not real. Hallucinated APIs are common and they compile in dynamic languages until runtime.
- Security and correctness sweep: string-interpolated SQL, an unvalidated input reaching a shell or a path, a widened permission check, a swallowed exception, a broadened
except. - Complexity and allocations: assistants reach for a nested loop or a full sort surprisingly often, and will happily load an entire table into memory.
# the kind of suggestion that passes the test and fails review
def get_orders(user_id, sort):
rows = db.execute(f"SELECT * FROM orders WHERE user_id={user_id} ORDER BY {sort}")
return [dict(r) for r in rows]
# injection through `sort`, no parameterisation, SELECT *, no pagination,
# and it ignores the repository layer this codebase uses everywhere else.The assistant's answer is confidently wrong and you have spent six minutes on it. What now?
The move is to stop and switch modes, and to say so:
"This isn't converging — I've prompted twice and it's still assuming the cache is write-through when this code is write-behind. I'm going to stop asking and read the cache module directly."
Then debug it the ordinary way: add a print or a breakpoint, read the actual implementation, write a minimal reproduction, check the library's real documentation. The failure mode being scored is the candidate who prompts a fourth and fifth time with slight rewordings, burning the clock in the hope that the model gets there.
Two habits that prevent the situation:
- Set a prompt budget. Two attempts; if the second is not better than the first, the model lacks context you have not given it, and a third rewording will not fix that. Either supply the missing context explicitly or take over.
- Ask it to explain rather than to fix. "Explain what
flush_policydoes in this module" is a question the model can answer reliably from the code in front of it. "Fix my bug" invites invention.
We hand you an unfamiliar 4,000-line service and a bug report. Show us how you use the assistant on a codebase you have never seen.
Where the assistant genuinely helps on unfamiliar code — use it for these, explicitly:
- "Explain the flow from the HTTP handler to the database for this endpoint." Excellent at tracing a path across files, which is otherwise the slowest part of orientation.
- "What are the callers of this function and what do they assume about its return value?" Good with the right files in context.
- "Summarise what this module is responsible for."
- "Write a failing test that reproduces this bug report." A very strong use: you get the reproduction fast and you have to verify it is a genuine reproduction, which forces understanding.
- "What could cause this symptom in this code?" — as a hypothesis generator, a list you then narrow yourself.
Where it hurts, and you should say so:
- Anything depending on institutional context — why the code is like this, which parts are load-bearing, what broke last time.
git logandgit blamebeat the model here, and using them signals experience. - Cross-cutting refactors: it will confidently change three call sites and miss the fourth.
- Anything requiring knowledge of runtime behaviour — the actual data distribution, what production config says, which branch is hot.
How do you use AI tools day to day, and where do you not?
A credible answer names specific uses and specific limits:
Where they earn their keep: boilerplate and scaffolding; test cases, especially edge cases I might not enumerate; unfamiliar APIs and syntax in a language I use rarely; explaining an unfamiliar codebase; first drafts of documentation, commit messages and migration scripts; converting between formats; regex and shell one-liners I would otherwise get wrong twice.
Where I do not, or verify heavily: security-relevant code (authentication, permission checks, crypto, anything handling untrusted input); concurrency, where plausible-looking code is subtly unsafe and tests will not catch it; anything where the model's training data is likely stale — a fast-moving framework's current API; architectural decisions, because the model cannot know our constraints and will produce a defensible-sounding answer to the wrong question; and anything I would be unable to debug at 3 a.m.
Then the process half, which is what distinguishes a senior answer: the same review bar applies regardless of who wrote it. AI-generated code in a pull request is not annotated as such and gets no discount. If I cannot explain it, it does not merge. And I read the diff before committing — the failure mode I watch for in myself is accepting a large change because it looked right in the moment.
Does using an AI assistant well mean I need to know less?
The opposite, and this is worth being direct about. Generating a plausible implementation is now cheap; judging one is not, and judgement is entirely a function of what you know. The scarce skills have shifted:
- Verification — knowing that this looks right but breaks under concurrency, or that this index will not be used, or that this retry will amplify an outage. You cannot verify what you do not understand.
- Problem framing — an assistant answers the question you asked. Asking the right one requires knowing the domain and the constraints.
- Architecture and trade-offs — the model has no access to your team size, your deadline, your existing systems or your on-call rotation.
- Debugging production — the assistant cannot see your metrics, your logs, or the data distribution that makes the query slow only for one tenant.
- Knowing what to not build, which has never been in the training data.
The things that got cheaper are typing, syntax recall and boilerplate. The things that got more valuable are the ones this handbook is about — which is why the depth still matters even in a round where you are allowed to ask a model for the answer.