Programming has always climbed a ladder of abstraction: bits, assembly, C, the high-level languages we use now. Each rung let us say more while writing less, so it is tempting to file AI as the next rung up. You describe what you want, the machine writes the code. Nothing new.
But every rung before this one kept a promise: same input, same output. The function you wrote last year still does what it did last year. Where randomness crept in, it was yours, a seed you set and could set again to replay the run. The ground was reversible, and that is what made it trustworthy.
AI is the first rung that breaks the promise. It breaks it at both ends.
On the output side, the same prompt does not return the same code. Not even at temperature zero, the setting meant to force the model to repeat itself exactly.
The reason is mechanical. A model picks each token by summing huge stacks of floating-point numbers, and floating-point sums change with the order you add them in. That order depends on how your request is batched with everyone else's on the GPU, so it shifts run to run. A hair of difference is enough to flip which token wins. No setting on your end turns it off.
The input side is just as loose. There is no syntax. You prompt in sentences, paste a screenshot, sketch a diagram, sometimes in another language. Ask for the same thing twice and you will word it two different ways.
So this is not a new layer on solid ground. The ground stopped being deterministic. Everything that works from here is a response to that one fact.
Two dials: range and distance
You cannot remove the non-determinism. You set how much of it to let in. That runs on two dials, and you set them fresh for every task.
Range is how wide you let the model wander. Wide range leaves the solution space open and invites answers you would not have reached. Narrow range fences it in, so the model can only move toward the one answer that fits.
Distance is how far the model runs before you look. Short distance breaks the work into small steps and checks after each. Long distance hands over the whole goal and looks much later.
Set both dials and you have placed the task as one point on a plane. How big and blurry that point grows is the part of the result that rides on ground you cannot pin down. Narrow and short hands over the least. Wide and long hands over the most.
The four corners are worth naming, so you can talk about them:
| Corner | Dials | When you reach for it |
|---|---|---|
do what I said | narrow + short | You know the answer and want it built exactly. Tuning an animation by eye. |
run with it | narrow + long | A tight spec, left running until the tests go green. A scoped migration. |
riff with me | wide + short | You want options fast. Three layouts for a page, you reacting to each. |
surprise me | wide + long | A problem you have not framed yet, handed over for a direction you react to. |
The two dials are independent, but you have to set them together. The longer the distance, the harder range is to control: the further the model runs before you look, the more a wide range has room to drift.
Range
Range comes down to one question: do I already know what I want?
When the answer is yes, go narrow. The target is clear, or the work has to slot into a system that already exists. Most engineering is this. You are not chasing an idea you have never had. You are looking for the one answer that fits the code around it, and a wide range is bad at that. It also blurs your authorship. When the model offers ten directions and you take one, the call stops looking like yours.
There is a real knob under range. Temperature spreads the model's output as you raise it and tightens it as you lower it. In agentic coding you rarely touch that knob. You shape range through context engineering — what the model sees, and what you let it ship:
- Gates. Tests, types, and lint, wired into pre-commit hooks so the agent cannot commit past them unless they are green.
- Rules. An
AGENTS.mdor.cursor/rulesfile that carries your house style, so you are not retyping it every session. - Skills. A
SKILL.mdthat packages a workflow once and loads it on demand. - Context. Above all, what you load into the window: the right reference, the file beside it, the example that shows the shape of the answer.
Prompt engineering gets you the first good output. Context engineering keeps the thousandth one good.
In practice this plays out as a context lottery. When the right thing exists, a sibling implementation, a tight spec, a clean example, you hand it over and the model lands fast and close. When it does not, I do the work by hand, slower, and it is never quite as sharp.
Go wide only when surprise is the point. Early, open work where you want a direction you would not have reached alone. There, generating a spread of options and taking the best earns its keep. Everywhere else it is noise dressed up as choice.
The default is narrow.
Distance
Distance comes down to one question: can success be checked without me?
When the answer is yes, you can go long. The tests pass or they do not. The number is hit or missed. The eval scores or it does not. You hand over the goal and let the model run.
The bluntest version is a loop. Geoffrey Huntley's Ralph:
while :; do cat PROMPT.md | agent; doneEach pass starts in fresh context. The repository and its git history are the only memory. The agent reads the evidence, does one atomic task, and runs again until the checks come back green. No orchestration framework. A while loop and a green checkmark.
The freedom to look away is borrowed.
You can look away only because the rails are up. The tests and types that fence the model in are the same ones that catch it while you are gone. But they never catch everything, and a long run lets the misses pile up for an hour before you look.
Short distance is not the fallback for fuzzy goals. Most of the time it is the deliberate choice.
It does not mean one careful session. It means cutting the work into slices small enough to check, then running them back to back: one slice, look, confirm, the next. Each pass starts fresh, so the model never drifts and you never review a wall of code you did not watch get written.
The rate of feedback is your speed limit.
You go short by necessity when the bar lives only in your head, a feel you cannot write down or an exact piece of UX. There are no rails to catch the model, so you are the rail. You go short by choice when you can already picture the result and want it built that way.
Necessity or choice, the move is the same: the smallest steps you can check, a look after each. You look because it ships its slop as confidently as its wins.
Long distance is not trust in the model. It is trust in the rails you put up before you walked away. Short distance is not distrust of the model. It is keeping your hand on the result.
Place it on purpose.
The ground does not set. The same prompt will keep coming back with a different answer, and there is no version of this where you make it hold still. But non-deterministic was never the same as uncontrollable. No two tasks arrive the same, and you will not reproduce any of them exactly. You can still be the one who shaped it, by choosing, task after task, how wide and how far.