You swap the model behind your coding agent and change nothing else. Same tools, same prompts, same repository. The pass rate drops, and the traces show something odd: the agent reads one page of a long file, treats those forty lines as the whole file, and rewrites it confidently on top of the gap. Your first thought is that the new model is worse at reading code. Look again at the page it was handed. Nothing in it said there was more. The old model happened to guess; this one believed you.

A tailor reads the pull, not the person

Two people order the same jacket from the same pattern. On one it hangs clean. On the other the cloth pulls at the shoulder every time he reaches forward. The tailor does not conclude that the second customer has a defective body. He watches where the fabric strains, puts a chalk mark there, and lets the sleeve out by half an inch. The pattern is the thing that changes. Nobody is asked to have different shoulders.

A harness profile is that alteration, and the weights are the body: fixed for the length of the fitting. What you calibrate is the prompts, the tool descriptions, and the middleware sitting between the loop and the model — the parts that decide which signals arrive and where. Placement does most of the work. A warning inside the result of a file read can change behaviour where the identical sentence in the system prompt is skipped, because one arrives at the moment of the decision and the other arrived hours ago among thousands of lines. Middleware can also hold an invariant outright, a ceiling on retries, so a habit becomes an impossibility rather than a request.

Naming the failure picks the component

The alteration only works if you know where the cloth pulled. So before choosing a fix, name the failure. A trace of tool calls, decisions and state transitions usually lets you sort it into one of four kinds. A context failure: the information was absent, or was there and got lost. A constraint failure: the agent acted outside its limits. A verification failure: the output was plausible, wrong, and nothing caught it. A planning failure: the strategy itself was bad.

Each name points at a different part of the machine — retrieval and memory, the rules attached to tools, the validators and tests, or how work gets split and delegated. Say an agent edits a file outside its scope. That is not a gap in its knowledge of the codebase; it is a constraint failure, and the repair is a rule on the path plus the case written into the eval suite, not another paragraph of instructions. Absorbing every failure into a longer prompt is the move that feels productive and buries the cause. Do it for a month and you have a very long prompt and no idea which sentence is holding anything up.

The flat curve is an answer too

Do this for two models and you no longer have one harness. A coding assistant can offer the same experience inside the editor while running different scaffolding underneath: one model gets a string-replacement edit tool, another gets a patch tool, both get the same workspace, and each gets instructions shaped the way it takes them. Switching provider is not a dropdown. Without the adaptation the model spends its effort fighting the tools instead of the bug.

Evaluations keep the whole thing honest, and they are the training data of the harness the way examples are training data for the model — which means they have to run in the real editing environment, not as the generic scores a launch post quotes. One winning run is noise. You promote a change from a cheap screen to the wider suite only when the gain repeats and nothing else regresses. And sometimes you make every alteration well and the curve stays flat. That is a result. It says the limit is in the weights this time, and the fitting was never the problem. Blaming the model is a conclusion you earn by classifying failures, never the one you start from.