Intuition The One Core Idea
A code-generation agent is a machine that writes code, runs it, reads what went wrong, and tries again — a loop, not a one-shot guess. Everything in the parent note is bookkeeping for that loop: symbols to track what code exists now , what happened when we ran it , and how likely we are to eventually get it right .
Before you can read the parent note, you must own every letter it throws at you. The parent assumes you already know what t , R , C t , H t , P t , A t , o t , e t , p , k , and ( c n ) mean. Below we earn each one from zero — plain words first, then a picture, then why the topic can't live without it .
Everything in this topic happens inside one repeating cycle. Look at it once now; every symbol below is just a label on some arrow or box in this picture.
Intuition Read the loop like a story
The agent stands in a state (what it knows and what code it has written). It perceives that state into a bundle of text called context . It plans and emits an action (usually "here is new code"). The environment executes the action and hands back output and possibly an error . That result becomes part of the new state , and the loop turns again.
Keep this figure in mind. Now we name each part.
t — which turn of the loop we are on
t is just a counting number for loop turns : t = 0 is the first attempt, t = 1 the second, and so on. It is the "frame number" of the movie.
Picture: in the loop figure, imagine a small odometer that clicks up by one every time the arrow completes a full circle.
Why the topic needs it: the whole point of an agent is that it changes over time . Without a clock we could not talk about "the code as it was on attempt 2 versus attempt 3." Every other symbol wears t as a subscript to say at which turn we mean it.
t is a turn, not a second
t does not measure real-world time in seconds. One loop turn might take the agent a fraction of a second or several minutes. t only counts iterations of the loop .
R — what the user asked for
R is the task description in plain English (or a spec), like "write a function that checks if a number is prime." It never changes during the loop, so it carries no t subscript.
Picture: the sticky note pinned to the top of the whiteboard in the figure — always visible, never rewritten.
Why the topic needs it: the agent must be reminded, on every single turn, what it is trying to do . If R were forgotten after turn 0, the agent would fix a bug but lose sight of the goal.
We meet the action before the code state, because the action is what changes the code, so we cannot describe how code updates until we know what an action is.
A t — what the agent decides to do this turn
A t is the ==action chosen at turn t ==: write new code, edit an existing line, ask a question, or declare "done." It is a proposal , like a diff or a snippet the agent hands over. The parent writes how it is chosen as:
A t ∼ LLM ( P t )
∼ means "is drawn at random from"
LLM ( P t ) is not one fixed answer — the model gives a distribution over possible next actions, and A t ∼ LLM ( P t ) means "A t is sampled from that distribution." Run it twice, you might get two different actions. That randomness is exactly why multiple attempts help (Symbol 10).
Picture: the "Planning → Action" arrow in the loop figure; think of a bag of possible next moves, and A t is the one we pull out.
Common mistake An action is not yet a program
A t is only the instruction to change the code ("replace length with len"). It is not the finished program you run. Turning A t into runnable code is the job of Apply in the next symbol.
C t — the code as it exists right now
C t is the ==current draft of the whole program at turn t ==. C 0 might be empty; C 1 has the first attempt; C 2 has the corrected version.
Picture: the text file on the screen inside the "State" box. Each turn it may be edited.
C t evolves by a rule the parent writes as:
C t + 1 = Apply ( C t , A t )
Intuition What "Apply" means in words
Apply takes the old code C t and the action A t (the edit from Symbol 3) and produces the new code C t + 1 . Think of it as "make the edit and save the file." If A t says "replace length with len", then Apply returns the whole program with that one word swapped. It is the reason C needs a subscript at all: the code is different before and after each action.
c t — the code actually run this turn
After applying the edit we have a full program. The code we hand to the sandbox on turn t is exactly that fresh program:
c t = C t + 1 = Apply ( C t , A t )
So the lowercase c t ("the code that got run on turn t ") is just the current program after this turn's edit. Lowercase c marks "a specific snapshot that was executed" ; uppercase C marks "the evolving program state." They are the same text at that moment.
Why the topic needs it: an agent that solves whole problems must hold a growing artifact — the program — separate from any single message A t . C t is that artifact; c t is the photograph we take of it right before running.
This is three symbols that always travel together, so we meet them as a family.
c i , o i , e i — one run, recorded
For a past attempt numbered i :
c i = the code that was run on attempt i (the snapshot from Symbol 4)
o i = the output it printed (what you'd see in the terminal, e.g. 3.0)
e i = the error it threw, if any (e.g. NameError: name 'length' is not defined)
Picture: below shows one such triple as three coloured cards — the code card, the output card, and the error card — clipped together.
Intuition Why record the error, not just the output?
A human debugger reads the error message to know what to fix. The agent is the same: e i is the feedback that turns a blind guess into a targeted correction. Without e i there is no learning between turns.
The subscript i vs t : we use i to walk over past attempts ("for each earlier run i "), and t for the current turn. They are the same kind of counter; i just ranges over history.
H t — the logbook of everything tried so far
H t is the collection of all past execution triples up to (but not including) turn t . The parent writes it as:
H t = {( c i , o i , e i ) } i < t
Let's decode that notation piece by piece, because it packs three ideas into little marks.
{ ⋯ } i < t
The curly braces { } mean "the set of."
Inside, ( c i , o i , e i ) is the one item shape — a triple.
The subscript i < t is the rule for which items to include : every i that is less than t .
Read aloud: "the set of all triples ( c i , o i , e i ) for every attempt i that came before now."
Picture: in the figure, the logbook is a stack of the clipped cards from Symbol 5 — one card-stack per past attempt.
Intuition The update rule adds the
code that ran , not the raw action
Each turn we drop the fresh triple onto the stack:
H t + 1 = H t ∪ {( c t , o t , e t )}
Notice we store c t — the actual executed code from Symbol 4 — not the action A t . Why? Because the history must match its own item shape ( c i , o i , e i ) : it is a log of runs , and a run needs the code that was executed. The raw edit A t has already done its job (it produced c t via Apply ), so it does not need re-storing. The ∪ is the union symbol — "add this to the pile." This memory is what separates an agent from a stateless LLM that forgets after each call.
P t — the single block of text handed to the model
P t is the ==assembled prompt at turn t ==: everything the model is allowed to see this turn, glued into one string. The parent builds it as:
P t = [ R , C t , H t , system instructions ]
Intuition The square brackets mean "stack these together"
Here [ … ] is concatenation — laying pieces of text end to end, like taping four pages into one long scroll. We include the goal R , the current code C t , the memory H t , and the standing rules. This is exactly prompt engineering : deciding what to put in the scroll .
Definition "system instructions" — the standing rules that never change
This slot holds the fixed policy text that is prepended on every turn, independent of the task. Concretely it is things like: "You are a coding assistant. Only output runnable Python. Never delete tests. If unsure, ask a question instead of guessing." It differs from R : R is the specific job ("make a prime checker"), while system instructions are the house rules that apply to all jobs. Together with safety guardrails, they shape how the agent may act.
Picture: the "Perception → Context" arrow in the loop figure is the machine that packs these four things into the scroll P t .
Why the topic needs it: the model can only react to what is in its prompt. P t is the formal answer to "what does the agent know this turn?" — and building it well (which of H t to keep when it grows huge) connects directly to retrieval .
o t , e t = Execute ( c t )
Execute runs the current program in a sandbox and returns two things: the output o t and the error e t . A sandbox is a walled-off playground where running unknown code cannot damage anything real — the safety idea from AI safety .
Intuition The sandbox runs the whole program
c t , not the bare edit A t
This is the subtle part. The action A t ("swap length for len") is not itself runnable — you cannot execute a diff. So the pipeline is:
A t is applied to the old code: c t = Apply ( C t , A t ) (Symbol 4)
The full resulting program c t is what enters the sandbox: o t , e t = Execute ( c t )
The parent's shorthand "Execute ( A t ) " really means "execute the program that A t produced." We run the whole c t because a bug in line 2 can only be caught by running the entire file, not the one edited line in isolation.
Picture: the "Action → Execution → State" arrow, drawn as a fenced box (the sandbox) that swallows the program c t and spits out o t (green) and e t (red).
Why the topic needs it: this is the act half of sense–decide–act. It is what makes the loop grounded in reality instead of the model hallucinating success. It is the concrete use of tool use .
Now we reach the counting. The parent claims:
P ( success in ≤ k attempts ) = 1 − ( 1 − p ) k
Let's earn every letter.
p , k , and what "P ( ⋯ ) " means
p = the chance one single attempt works , a number between 0 and 1 (e.g. 0.4 means 40%).
k = the number of tries the agent is allowed.
P ( event ) = "the probability of that event."
The figure shows this curve climbing toward 1 as k grows. This one picture is the whole reason agents iterate : even a mediocre single-shot rate becomes near-certain with a few tries.
Worked example The parent's numbers, checked
With p = 0.4 :
k = 1 : 1 − 0. 6 1 = 0.40 = 40%
k = 3 : 1 − 0. 6 3 = 1 − 0.216 = 0.784 = 78.4%
k = 5 : 1 − 0. 6 5 = 1 − 0.07776 = 0.92224 ≈ 92.2%
Common mistake "Independent" is a hidden assumption
The multiply-the-failures trick only works if attempts don't influence each other. Real agents do learn from e t , so later attempts are usually better than p — meaning the true curve rises even faster than the formula. Treat 1 − ( 1 − p ) k as a pessimistic floor.
The performance metric uses a new mark:
pass@ k = E [ 1 − ( k n ) ( k n − c ) ] ( valid for k ≤ n )
( k n ) — "n choose k"
( k n ) counts the ==number of ways to pick k items from n ==, order not mattering. Read "n choose k." Example: ( 2 4 ) = 6 ways to pick 2 things from 4.
n , c , and E [ ⋅ ]
n = total code samples generated for one problem.
c = how many of them are correct .
E [ ⋅ ] = the expected value , i.e. the average over all problems in the benchmark.
Intuition Why the fraction of "choose" counts?
To fail pass@k, you must pick k samples that are all wrong . Wrong samples number n − c , so ways-to-pick-all-wrong is ( k n − c ) , out of ( k n ) total ways. That ratio is the fail chance; 1 minus it is the success chance.
Common mistake You must sample at least
k times: k ≤ n
The formula only makes sense when k ≤ n — you cannot choose k items out of n if k > n . In that case ( k n ) = 0 and the fraction is undefined, so the metric is simply not defined there; in practice you always generate n ≥ k samples before computing pass@k . Also, if c ≥ n − k + 1 there are too few wrong samples to fill k slots, ( k n − c ) = 0 , and the success term correctly becomes exactly 1 .
E [ ⋅ ] average over, concretely?
The benchmark (say HumanEval) has many problems. For each problem j you compute its own inside-the-brackets score s j = 1 − ( k n − c j ) / ( k n ) using that problem's count of correct samples c j . Then E [ ⋅ ] is just the plain average:
pass@ k = N 1 ∑ j = 1 N s j
where N is the number of problems. In words: "score every problem, then take the mean." That is all the expectation operator asks you to do here.
Why the topic needs it: pass@k is how benchmarks like HumanEval report agent skill — it rewards exactly the try-several-times behaviour that defines an agent. It links straight to program synthesis evaluation.
P_t assembled prompt plus system rules
Apply gives c_t full program
1 minus one minus p power k
Read top to bottom: the four state pieces feed the prompt, the prompt is sampled into an action A t , the action is applied into a full program c t , that program is executed into output and error, both flow back into history — and repeating this loop is what the probability and pass@k formulas measure.
Test yourself — reveal only after answering aloud.
What does the subscript t count? The number of turns of the agent loop (turn 0, 1, 2, ...), not real seconds.
Why does R carry no subscript? The requirements never change during the loop, so there is no "before/after" version to distinguish.
How is the action A t chosen, and why the tilde ∼ ? It is sampled from the model's distribution LLM ( P t ) ; the tilde says the result is random, so repeated calls can differ.
What does Apply ( C t , A t ) produce, and what is c t ? It applies the edit A t to the old code to give the new full program C t + 1 ; c t is that same program — the snapshot actually run this turn.
Does the sandbox run A t or c t ? It runs the full program c t , not the bare edit A t (you cannot execute a diff).
In H t + 1 = H t ∪ {( c t , o t , e t )} , why store c t and not A t ? History items have the shape (code, output, error); a run must record the executed code c t , and A t has already done its job by producing c t .
What goes in the "system instructions" slot of P t ? Fixed house rules applied every turn, e.g. "You are a coding assistant, output only runnable Python, ask if unsure" — separate from the task R .
Why is ( 1 − p ) k raised to the power k ? All k independent attempts must fail; multiplying k equal failure chances gives an exponent.
Compute 1 − ( 1 − p ) k for p = 0.4 , k = 3 . 1 − 0. 6 3 = 1 − 0.216 = 0.784 , i.e. 78.4%.
What is the valid range of k in pass@k, and what happens outside it? You need k ≤ n ; if k > n then ( k n ) = 0 and the metric is undefined, so you always generate n ≥ k samples first.
What does E [ ⋅ ] average over in pass@k, and how do you compute it? Over all problems in the benchmark; score each problem separately, then take the plain mean N 1 ∑ j s j .