First let us pin down the words and symbols this page reuses, so nothing is used before it is defined.
Two more clusters of symbols appear in the traps below — the ones behind the pass@k metric and the ones behind hybrid retrieval. Let us earn them before we use them.
Now walk the three figures — each one carries an idea you will be quizzed on.
Figure 1 draws one turn of the agent loop. Follow the arrows clockwise from the cyan State box: the state (Ct,Ht) feeds into building the prompt Pt, which the LLM turns into an action At (amber), which runs in the sandbox to produce ot,et, which updates the state — and the amber return arrow closes the loop into the next round. The trap "sandbox is only about security" dies here: the sandbox is the box that produces the feedback.
Figure 2 plots 1−(1−p)k as k grows, for p=0.4 (cyan) and p=0.7 (amber). Notice both curves climb toward the dashed line at 1 but never cross it — this is exactly why "3×0.4=1.2, guaranteed" is nonsense: probability is capped at 1. The annotated point confirms p=0.4,k=3 lands at 0.784, not 1.2.
Figure 3 shows why retrieval is hybrid. For the query "find login function", auth.py wins on the cyan BM25 bar (exact keyword hit) while login_view.py wins on the amber embedding bar (semantic match). Neither alone ranks both correctly; the white hybrid bar (with α=0.6) lifts both to the top. This is the trap "embeddings alone are enough" made visible.
TDD in an agent means the agent writes tests before it writes the implementation.
True — the agent generates tests first so the specification is made concrete and machine-checkable, then writes code aimed at making those tests pass. Tests-after would only confirm whatever the code already happens to do.
A code-generation agent is just a bigger code-completion model.
False — completion predicts the next tokens inside a file; an agent adds a loop that runs code, reads errors, and edits again. The defining difference is feedback with the environment, not model size.
If single-try success is p=0.4, three independent tries give 3×0.4=1.2, i.e. guaranteed success.
False — you cannot add probabilities like that; the sum 1.2 is bigger than 1, which is impossible for a probability. The correct rule multiplies failures: 1−(1−p)k=1−0.63=0.784, about 78.4%, never more than 1.
pass@k and 1−(1−p)k are the same formula.
False — 1−(1−p)k assumes every attempt has the same independent success rate p. pass@k estimates from a finite pool of n samples containing c correct ones using the hypergeometric count (kn−c)/(kn), i.e. drawing without replacement from what was actually generated.
Running generated code in a sandbox is only about security.
False — security (isolation) matters, but the engine of the agent loop is that execution produces the output ot and error et the agent needs to decide its next edit. Without execution there is no feedback.
Hybrid retrieval (BM25 + embeddings) is redundant because embeddings already capture meaning.
False — embeddings catch semantic similarity ("authenticate" ≈ "login") but can miss an exact token like a specific function name; BM25 nails exact keywords but is blind to synonyms. Each covers the other's blind spot.
More iterations always increase the chance of success.
Mostly true if attempts are genuinely independent — but real iterations aren't independent, so if the agent keeps re-reading the same misleading error it can loop on the same wrong fix and never improve. The formula's monotonic climb assumes fresh, uncorrelated tries.
Multi-agent code systems are better because more agents means more compute.
False — the benefit is specialization and parallelism (an architect, implementers, a tester each optimized for one job), not raw compute. Poorly coordinated agents can duplicate work or overwrite each other's files.
"The agent's action At can only ever be generate new code."
Wrong — At is a choice among several: generate new code, modify existing code, request clarification, or declare the task complete. Collapsing it to one option ignores the planning step.
"State update just replaces the code: Ct+1=At."
Wrong — the update is Ct+1=Apply(Ct,At), an edit applied to the existing code, and the history Ht+1=Ht∪{(At,ot,et)} also grows. The past is appended, not thrown away.
"For is_prime(n) we must test every divisor from 2 up to n−1."
Wrong — checking up to n suffices, because if n=a×b with a>n then b<n and would already have been caught. Testing to n−1 is correct but wastefully slow.
"An IndexError: list index out of range is fixed by adding a bounds check where it crashed."
Wrong in general — the crash site is often not the cause. The real bug is usually an off-by-one loop bound or a bad counter set earlier; a blind bounds check hides the symptom while the wrong logic remains.
"pass@1 measures whether the model ever solves the problem."
Wrong — pass@1 is the chance a single sample is correct; "ever solves it" is pass@k for larger k. Conflating them makes an iterating agent look worse than it is.
"The context prompt Pt should contain only the current code Ct."
Wrong — Pt=[R,Ct,Ht,system instructions]. Dropping the requirements R or the execution history Ht means the model forgets what was asked and what already failed.
Why do agents iterate at all instead of just generating once?
Because first-try success on real code is low (~30–70%); syntax slips, logic bugs, and edge cases only surface when the code runs, so a feedback loop is needed to catch and repair them.
Why keep the full execution history Ht in the prompt rather than just the latest error?
So the agent won't re-try a fix it already saw fail; the history encodes "what's been tried and what happened," preventing it from cycling through the same dead ends.
Why generate tests before the implementation in TDD?
Tests turn vague natural-language requirements into concrete, checkable assertions, exposing edge cases up front and giving the agent an automatic way to verify its own later code.
Why check divisors only up to n when testing primality?
Divisors come in pairs a×b=n; one of each pair is always ≤n, so if none below n divides n, none above it can either — checking the larger half is redundant.
Why is the naive "add defensive checks everywhere" a trap in error recovery?
It pattern-matches on error keywords instead of reasoning about data flow, so it silences the message while leaving the true cause (bad loop bounds, uninitialized counters) intact — the bug returns elsewhere.
Why blend keyword (BM25) and embedding retrieval with a balance parameter α?
To tune how much weight goes to exact-name matches versus meaning-based matches; small α leans on precise identifiers, large α leans on conceptual synonyms.
Why does the success-probability formula reward independence between attempts?
If attempts are independent, each failure is a separate coin flip, so failing all k is (1−p)k, which shrinks fast; correlated attempts share the same blind spot and don't multiply down like that.
What does 1−(1−p)k give when p=0 (the agent can never solve it)?
Zero for every k — (1−0)k=1, so no number of independent tries helps. Iteration cannot rescue a task the model is fundamentally unable to do.
What does the same formula give when p=1?
1−(1−1)k=1 for any k≥1 — a guaranteed solver succeeds on the first try, and extra iterations add nothing.
What does pass@k give at k=0 (you submit nothing)?
Exactly 0: by convention (0n−c)=(0n)=1, so 1−11=0. Drawing zero samples can never yield a correct one, which is why the metric is only meaningful for k≥1.
What is pass@k when k=n (you keep every sample you drew)?
If there is at least one correct sample (c≥1) it is 1, since (kn−c)=(nn−c)=0; the whole point of drawing everything is you never miss an existing correct answer.
What is pass@k when the pool has zero correct samples (c=0)?
Exactly 0, because (kn−c)=(kn) and the fraction equals 1, so 1−1=0. You cannot select a correct answer that was never generated.
What does pass@k mean when k>n — you ask for more attempts than samples exist?
It is not defined by the standard formula, because (kn)=0 when k>n (you cannot choose k items from fewer than k), giving a divide-by-zero. In practice you either cap k at n or must generate at least k samples first; asking for more draws than you have is meaningless.
How should the agent behave when execution produces no error and no output (a silent, empty run)?
Treat empty output as a signal too, not success — often it means the code ran but printed nothing or the test path wasn't reached. The agent should add a print/assert to confirm the logic actually executed before declaring completion.
What happens at the very first step t=0 when the history H0 is empty?
The context contains only R (requirements) and system instructions with no past attempts, so the first action is a pure one-shot generation — the loop's feedback only begins once the first execution fills H1.
Recall Two-line self-test
The agent loop's defining feature over plain completion? ::: A feedback loop with the environment — run, read output/error, edit, repeat.
pass@k with c=0 correct samples? ::: Exactly 0 — you cannot pick a correct sample that was never generated.