Session 5 — Agentic Programming
13 October, 2026
Recap from Session 4
So how does typing a prompt into OpenCode turn into a diff on your screen, touching real files on your disk?
That gap is what today is about: the harness — everything wrapped around the model to make it useful.
By the end of this session you can explain
From Session 1:
Today’s focus
The harness layer. The model is a black box that takes text in and produces text out. Everything else — memory, files, actions in the world — is the harness’s job.
An LLM API call is just: a block of text in, a block of text out.
Every time you send a message in OpenCode, the harness doesn’t just send your message. It assembles a whole package:
All of that, concatenated into one text blob, is the actual input to the model. The model has no separate “memory” — the entire past of the conversation is re-sent, every single turn.
Definition
The context window is the maximum amount of text (measured in tokens, not characters or words) the model can process in a single call — both what goes in and what comes out.
Why this matters practically
A long agent session — lots of files read, lots of back-and-forth — can silently fill the context window. The agent starts “forgetting” things you told it 20 turns ago, not because it’s being careless, but because that text is no longer in the window.
You don’t need the math. You need the idea.
The idea
For every token the model is about to generate, it doesn’t treat every earlier token in the context equally. It computes, on the fly, “how relevant is each earlier piece of text to what I’m producing right now?” — and weighs accordingly.
Definition
A system prompt is a block of text the harness prepends to every conversation, invisible to you by default, that tells the model: who it is, what it can do, and — critically — the exact syntax for calling tools.
A real agent system prompt typically says things like:
read_file, write_file, run_command, edit. To use one, output This is why project-level config files (AGENTS.md, CLAUDE.md, OpenCode’s config) matter: they get folded into the system prompt on every single call in that project, shaping every response without you retyping anything.
The model itself cannot read a file, run git commit, or edit code. It can only produce text.
The trick
The harness tells the model, in the system prompt: “if you want to read a file, output text in this exact format.” The model, being a good next-token predictor trained on this pattern, does exactly that when it decides a file read would help. The harness watches for that pattern, intercepts it, actually runs the file read, and feeds the result back in as a new turn.
So a “tool call” from the model’s point of view is just: producing a specific string of text that looks like a function call. The intelligence is in the harness recognizing and executing it — the model is never touching your filesystem directly.
From prompt to diff — the actual sequence
x.R”).What looks like one prompt → one answer is often many model calls chained by the harness, each one re-sending the whole growing context.
5 minutes, pairs
Close this deck. On paper or in a text file, write the prompt-to-diff loop in your own words, in 5 steps or fewer. Then turn to your neighbor and explain it to them out loud — no notes.
Trade papers. Check each other’s version against the slide before this one:
Keep this page — you’ll want it again in Session 11 when we catalogue where agents went wrong across the course.
The task
Starting fixture: scripts/s5-winsorize/winsorize.R. It contains a small, untested function winsorize(x, p = 0.05) that is supposed to cap the bottom p fraction of a numeric vector at the p-quantile and the top p fraction at the 1 - p-quantile, but currently has a bug (the upper cutoff is computed as quantile(x, p) instead of quantile(x, 1 - p), so it caps far too many high values instead of just the top p fraction). Run the identical prompt in both harnesses, in a fresh copy of the same starting directory:
“Look at
winsorize.R. Write atestthattest file forwinsorize()that checks it correctly caps values at the p and 1-p quantiles, including edge cases. Run the test, and if it fails, find and fix the bug inwinsorize(). Show me the diff.”
Fill this in live, one column per harness
| Observation | OpenCode (free) | Claude Code (paid) |
|---|---|---|
Read winsorize.R before writing the test? |
||
| Number of tool-call rounds to finish | ||
| Did the test fail on first run, as expected? | ||
| Found and fixed the actual bug (not a different one)? | ||
| Diff quality (minimal / noisy) |
The point of this demo
The model and the harness are separate axes of choice. A better/pricier model does not automatically mean a better harness experience, and vice versa — you are always choosing both. Cost numbers get precise in Session 9; today, just notice that one of these runs was free and the other wasn’t.
You should now be able to explain
Next: Session 6 puts this to work on a real data-wrangling pipeline with DuckDB — where you’ll watch the agent draft SQL/dplyr queries and have to verify them yourself.