The internals of coding agents
Week 1 · Agentic Software Engineering
Generate a proposal.
Verify the effect.
LO1: explain the loop · LO9: keep evidence bounded
A coding agent is a loop
flowchart LR
M[Model proposes] --> C[Controller checks]
C --> T[Tool acts]
T --> O[Observation]
O --> M
C --> S[Stop or continue]
Each arrow carries a different claim.
Start with a contract
ok → passed
fail → failed
Anything else → unknown
Ignore surrounding whitespace and ASCII letter case.
Generate a plausible candidate
def status_label(raw):
return {"ok": "passed", "fail": "failed"}.get(raw.lower(), "unknown")
What does it return for " OK "?
Predict before reading the check.
Verify the missing case
The contract requires " OK " → passed.
The candidate returns unknown.
Add .strip() before .lower(), then keep the original and unknown cases.
A patch is a proposal until the regression runs.
The fixture has three tools
| Name | Accepted action | Observation |
|---|---|---|
read |
result.txt |
file text |
write |
at most 32 characters | written |
bash |
verify only |
verified / check_failed |
Other names, paths and arguments are refused.
The five-step controller
- Start history with the task.
- Send history; check the reply and call IDs.
- Append the reply; no calls means
final. - Answer every call with its own tool message.
- Exhausted budget means
step_limit.
The public starter leaves run() for you to complete.
Generate a successful path
c1 read result.txt → 5\n
c2 write result.txt 4\n → written
c3 bash verify → verified
final → no more calls
Left: generated actions.
Right: observed results.
Verify the controller
mkdir week01-loop
cp lectures/week-02/fixture/*.py week01-loop/
PYTHONPATH="$PWD/scripts" python3 week01-loop/verify_loop.py
Before run() is complete, the check explains what is missing.
Afterwards, read the named checks and retain the output.
A write is not a check
Candidate writes 5\n and receives written.
The fixed check returns check_failed.
Which claim is supported?
Stop reasons are evidence fields
| Field | Means | Does not mean |
|---|---|---|
final |
no calls in a reply | code is correct |
step_limit |
turn budget ended | task is complete |
check_failed |
current check failed | model is useless |
A later write also makes an earlier check stale.
Practise reading the supplied request
python3 lectures/week-02/session/show_session.py \
lectures/week-02/session/sample-session.jsonl --request 4
Predict first: request count, first tool, failure recovery and stop evidence.
Mark observed and inferred
Observed: a request contains a call, a result or an instruction at a cited index.
Inferred: an explanation of why the agent acted or what it might do next.
The supplied record is hand-authored. Your studio capture supports claims about your agent.
Prompt text is not always enforcement
A system instruction can ask for a plan.
A schema can require an argument.
A tool can reject a path.
Name the component that enforces each rule—or say it only asks.
Count requests, not calls
One response can contain several calls.
Each call gets a tool result under its own ID, in response order.
The viewer's Request N blocks are the unit to count.
Studio: force a failure, then verify
- Copy a synthetic status task to a draft directory.
- Predict before generation.
- Capture the failing check and the repair.
- Run the check on the current candidate.
- Label each claim observed or inferred.
Keep the original failure and revise one explanation.
Evidence-bounded decisions
Accept only the revision and cases the check covered.
Otherwise narrow the claim, re-check the current revision or stop.
A1 is due this week.