you · question
The tool ran. Who reads the result?
- you · locked inThe model has to see it.
model.complete(text) -> text
Build the harness behind an AI coding agent, one problem at a time. Sixteen lessons. Real Python in your browser. No API key. A question before every answer.
Start lesson 1 See the syllabus
Free. No account, nothing to install. Lesson 1 takes about 35 minutes and ends with code you wrote.
Call 1 tells the model a name. Call 2, one line later, asks for it. What does call 2 answer?
model.complete(SYSTEM, [
lab.user("My name is Ada.")])
reply = model.complete(SYSTEM, [
lab.user("What is my name?")])
print(lab.show([reply]))
Three beliefs about where a conversation lives. This page will not tell you which one holds; a program will. Lesson 1 runs these two calls as real Python in your browser, and a prediction locked in here is waiting there, beside the Run button. Then you build the part that remembers.
Start lesson 1: run it and see
Locking in also starts the Python download in the background (under 10 MB, once), so that Run is ready when you get there.
Sixteen problems, in the order you would hit them. Each lesson starts where the code from the last one breaks.
One file, harness.py, that grows from a chat that remembers into a coding agent you can stop, resume and trust. Every lesson adds one thing it can do.
part a · 01 to 03
You end with an agent: a model call in a while loop, over a transcript you hold.
part b · 04 to 06
A loop that survives bad tool calls, runaway models, provider failures and huge outputs.
part c · 07 to 10
Events, a harness object, input in the middle of a run, and a transcript that cannot be bricked.
part d · 11 to 12
An append-only log, resume by replay, and compaction as a rule for reading the log.
part e · 13 to 14
A system prompt that is computed, skills that load on demand, and a gate that fails closed.
part f · 15 to 16
Async, cancellation, a real provider adapter, real tools, a real model.
By the end of lesson 3 you have written this loop. The other thirteen lessons are what it takes to trust it.
The crank Send the whole list to the model. Append the reply. If it asks for tools, run them, append each result, and go again with the longer list. If it asks for nothing, you are done. The model steers; the loop only turns.
You are asked before you are told. Then you build the answer, and then you check it against a real harness.
Every idea starts as a problem and a question. Your answer is locked in, then the page answers. A wrong prediction is the method working; nobody keeps score.
You write the code, in an editor on the page. Hidden tests read as sentences, hints come one at a time, and the reference solution unlocks when you need it.
Then the same idea in a real coding-agent harness, cited by file and line, with the honest gap between your version and theirs.
A current browser, on a desktop or a phone; a keyboard makes the labs easier. No machine-learning background. Generators and asyncio are not assumed: lessons 7 and 15 open with a short warm-up you can skip.
35 to 70 minutes a lesson, about 13 to 15 hours for the core path. That is an estimate from the lesson structure, not yet a measurement. The capstone is two sessions in the browser, then work on your own machine; its last step is optional and uses a real model with your own key, which never touches this site.
Every lesson marks a good place to stop. Nothing is locked: if you already know a part, go straight to its lab.
Every lesson compares what you built with how Tau solves the same problem.
Tau is an open-source coding-agent harness written in Python, under the MIT licence. Each comparison cites a file and line range pinned to one commit, and the build checks every citation against that commit, so an excerpt cannot drift from the source.
The comparison is honest in both directions: where your version is simpler, and where Tau does something the course does not. This site is an independent project. It is not affiliated with or endorsed by the Tau project or by any model provider. Licences and attribution.
lesson 01 · the function that forgets · 35 min
You call it twice. What does it remember?
You tell a model your name. One line later, you ask for it back. Predict, run it, then build the fix.