What you'll learn: how to answer six more technical interview questions (a Python default-argument trap, finding where latency went, choosing a chunk size, choosing a retrieval method, stopping a runaway agent loop, and evaluating an agent, not just its answers) with a structure, a number and a test you can name.
At a glance
Figure 1. Where the six questions sit in one request
How to read this: Q2 and Q6 look at the whole path, and the other four each zoom into one box.
- Optional extension: six more questions in the same shape as the reference pages, each shorter.
- Two sketches use tested code from the capstone lesson folder; the rest use illustrative numbers with the arithmetic shown.
- Technical answers are scored on four things: a measurement, a number, a bound and a test.
- The capstone's retrieval is BM25 keyword search and its default provider is a rule-based mock, so no answer here claims behaviour of a real model.
- None of this describes how any company interviews.
Scenario
Composite scenario, not a real company. A Node.js engineer is preparing for a technical round for a forward deployed role. The practice customer is Lumen Industrial Supply, the fictional distributor whose product discovery copilot is the course capstone. The round is one hour: two coding questions and four design questions. The candidate wants answers that name a measurement and a test, because those are what an interviewer can check. All numbers are illustrative.
What you will be able to do
- Explain the mutable default argument trap and the standard fix, and show it with a test.
- Locate a latency regression by timing stages, and explain why the added stage is not always the slow one.
- Choose a chunk size by testing against a question set, using a token budget to bound the choice.
- State the limits of an agent loop and how you would evaluate its path, not only its final answer.
Prerequisites
- Python for Java and Node developers and Testing with pytest.
- RAG: chunking, RAG: search and Workflow limits and state.
- The reference pages Python and API questions and RAG and agent questions; the six questions here are different.
Core ideas
In the interview: "Walk me through how you would find out." Technical answers earn marks for a first measurement, a number that would change your decision, a bound on cost or time, and a test you would add so it stays fixed.
Q1. What does this Python function return on its second call, and why?
What it assesses. Whether you know that a default value is created once, when the function is defined, and can fix and test it.
Answer framework.
- Predict the output before you explain it.
- State the rule: the default is evaluated once, at definition time.
- Say which defaults are risky: lists, dictionaries and most objects.
- Show the fix:
Noneas the default and create the object inside. - Name the test that would have caught it.
Strong answer sketch. The function and its fix are both in tested code.
Verified: capstone/fde-product-discovery-copilot/lessons/M8-L7/m8_l7_gotchas.py
def add_tag_buggy(tag: str, tags: list[str] = []) -> list[str]: # noqa: B006 (the bug is the point)
tags.append(tag)
return tags
def add_tag(tag: str, tags: list[str] | None = None) -> list[str]:
if tags is None:
tags = []
tags.append(tag)
return tags
The first call returns
["a"]and the second returns["a", "b"], because the empty list was created once, whendefran, and every call that omitstagsshares it. The Python tutorial gives the same warning. The fix is aNonedefault and a fresh list inside the function. I would add a test that calls the function twice and checks the second result is["b"], so a refactor cannot bring the bug back.
One common mistake. Saying "Python passes by reference, so the list is shared". The cause is when the default is evaluated, not how arguments are passed.
One follow-up. A FastAPI endpoint has def handler(items: list[str] = []). Is it affected, and what would you use instead?
Q2. After you added retrieval, the endpoint's response time doubled. How do you find out why?
What it assesses. Whether you measure before you guess, and whether you know that the stage you added is not always the stage that got slow.
Answer framework.
- Reproduce the slowness with a fixed request set.
- Time each stage of one request, with the same clock and the same names.
- Compare before and after, stage by stage.
- Fix the stage that grew, not the stage you suspect.
- Keep the timing in production, so the next regression is visible.
Strong answer sketch. A small timer, built with a fake clock in its test, adds up seconds per named stage.
Verified: capstone/fde-product-discovery-copilot/lessons/M8-L7/m8_l7_gotchas.py
class StageTimer:
"""Adds up the seconds spent in each named stage of one request."""
def __init__(self, clock: Callable[[], float] = time.perf_counter) -> None:
self._clock = clock
self.stages: dict[str, float] = {}
@contextmanager
def stage(self, name: str) -> Iterator[None]:
start = self._clock()
try:
yield
finally:
self.stages[name] = self.stages.get(name, 0.0) + (self._clock() - start)
I would wrap each stage in the timer and print the table for the same ten requests before and after. The
finallyrecords a stage even when it raises. Then I read the table, and I do not assume it is the retrieval code. The worked example shows why.
One common mistake. Profiling the new code because it is new, when the time went somewhere else.
One follow-up. Your timings come from your laptop. How do you trust them for production?
Q3. How would you choose a chunk size for the product documents?
What it assesses. Whether you treat chunk size as an experiment against a question set, bounded by the context budget, and not as a number from a blog post.
Answer framework.