Pin the model like any other dependency
Pin exact model identifiers in code and change them deliberately, never by alias.
A floating alias is a dependency that upgrades itself in production without a commit, a review or a changelog. Everything you learned about pinning package versions applies unchanged — except that this dependency's behaviour is statistical, so a silent change shows up as a slow drift in quality rather than a crash you can trace.
What goes wrong: Output quality moves overnight, nothing in your repository changed, and you spend two days looking for a bug you did not write.
What agents change: An agent asked to 'use the newest model' will write an alias, because that is what the phrase means in English and not what it means in production.
You are violating it when
- A model name in your code ends in `-latest` or carries no date.
- You cannot tell from the repo which model served last Tuesday.
- A model change reaches production without a pull request.
The usual objection: That pinning means never upgrading. It means upgrading in a commit, behind your evals, on a day you chose.
Treat the model name in an API call as part of the build, not as a preference string. A snapshot identifier is the thing being tested and released with the application. An alias is a moving pointer controlled outside the repository, so it is not the same dependency tomorrow that it was today.
This works because model behavior is part of the system contract. If the identifier is exact, a change in answers can be correlated with a code change, prompt change, data change, or a deliberate model migration. If the identifier floats, production behavior can shift without a diff, which turns debugging into archaeology.
The misconception is “pinning means never upgrading.” That is wrong for the same reason package lockfiles do not mean never patching dependencies. Pinning separates runtime stability from upgrade policy: upgrades happen in commits, with eval results, review, rollout, and rollback, instead of arriving silently through an alias.
With coding agents, the wording matters. An instruction like “use the newest model” naturally leads an agent toward an alias or latest pointer. Production code needs the opposite: an exact identifier now, plus a separate maintenance path that proposes and tests replacements later.
Install it
npx klay practices add pin-the-model.klay/practices/pin-the-model.mdcreate# Pin the model A floating model alias is a dependency that upgrades itself in production without a commit, a review or a changelog. Everything you already believe about pinning package versions applies here unchanged. The one difference is that this dependency's behaviour is statistical, so a silent change does not crash — it drifts. Quality moves overnight, nothing in your repository changed, and you spend two days looking for a bug you did not write. ## Do ```pythonAGENTS.mdappend-block## Model identifiers - Always use an exact, dated model identifier. Never `-latest` and never an undated alias. - Keep model ids in one module, not scattered through call sites. - Changing a model id is a pull request of its own, with the eval results in the description.
The previews are the first lines of each file; the command writes them in full. Existing files are never overwritten.
How you know it stuck
npx klay practices audit reports this check for this practice:
model-pinned
Where this comes from
- Models overviewDefines stable snapshots versus moving pointers in the model identifier itself.
- Prompt engineering | OpenAI APIGives first-party production guidance to choose specific snapshots for consistent behavior.
- Model deprecationsShows pinned models still have lifecycles, making upgrades planned work rather than surprise drift.
- Semantic Versioning 2.0.0Supplies the familiar dependency-versioning analogy engineers already use for packages.
- Dependency drift fitness function | Technology Radar | ThoughtworksConnects pinning with automated tracking so versions stay current deliberately.
Questions
- Aliases get me fixes automatically though.
- They also get you regressions automatically. With evals in CI an upgrade is a ten-minute pull request; without them an alias is an untested deploy on someone else's schedule.