What a version even is for an agent

Lesson 2 of 5 in Deploying and Versioning Agents: Ship It Like Software.

In ordinary software, a version is a commit. Everything that determines behaviour is in the repository, so hashing the repository hashes the behaviour.

That is not true for an agent. An agent's behaviour is determined by a tuple:

prompt + toolset + model + parameters + framework

Change any single element and you have a different agent — one that may pick different tools, take a different number of turns, produce differently shaped output, and fail differently. Your git history sees maybe two of the five.

Prompt — the instructions, and everything assembled around them

Not just the system prompt: the tool descriptions, the few-shot examples, the retrieved context template, the compaction summary format. All of it is input the model conditions on.

What a change breaks: trajectories. A reworded sentence can move tool-selection rates by double digits.

How you catch it: hash the rendered prompt template, store the hash with the version, and re-run the regression suite. "It was only wording" is the most expensive sentence in agent operations.

Toolset — names, schemas, descriptions, and permissions

A tool is a contract and a piece of prompt. Adding one changes what the model reaches for; renaming a parameter changes what it emits; rewriting a description changes when it fires.

What a change breaks: argument shape and tool choice — and, if the new tool writes, your blast radius.

How you catch it: version the tool schemas (hash them), gate new write-capable tools on a least privilege review, and re-run evals that assert on tool trajectories, not just final answers.

Model — the snapshot, not the family

some-model-latest is not a version. A family alias is a promise that the provider may keep pointing somewhere new. Pin the dated snapshot and upgrade deliberately (next lesson).

What a change breaks: everything, subtly — verbosity, refusal behaviour, tool-call formatting, latency, cost per run.

How you catch it: the pinned id is part of the version tuple, and the eval suite runs whenever it changes. A model swap is a code change; treat it exactly that way.

Parameters — temperature, top-p, max output, thinking budget, seeds

The most-forgotten element, because it usually lives in a config file or an environment variable rather than in code review.

What a change breaks: variance. Raising temperature widens the trajectory distribution, so a pass rate measured at 0.0 no longer describes the deployed agent. Reasoning/thinking budgets change both quality and cost.

How you catch it: put parameters in the versioned manifest — never in an unversioned environment variable someone can edit in a console at 6 p.m.

Framework — the harness that runs the loop

The SDK or platform runtime decides how context is assembled, how tool results are serialised, how many retries a failed call gets, when compaction fires, and what the stopping condition actually is. Two frameworks running the same prompt, tools, and model are two different agents.

What a change breaks: loop mechanics — usually visible as changed turn counts, token spend, or truncated context long before it is visible as wrong answers.

How you catch it: pin the SDK version and the container image by digest, and re-run the suite on framework bumps. A minor version bump in an agent framework is not a minor change.

The practical answer is a version manifest: one artifact that names all five elements and travels with every run, every log line, and every eval result. It does not have to be elaborate. It has to be complete and immutable.

agent: refund-triage
version: 7
model:
  id: <provider>/<model>@2026-07-15   # a dated snapshot, never a "-latest" alias
  temperature: 0.2
  max_output_tokens: 2048
prompt:
  template: prompts/refund-triage.md
  rendered_sha256: 3f9c...            # hash what the model sees, not what you typed
tools:
  - name: lookup_order
    schema_sha256: a11b...
  - name: issue_refund
    schema_sha256: 7c02...
    max_amount_eur: 500               # a runtime cap, not a prompt request
framework:
  sdk: agent-sdk 2.4.1
  image: registry/refund-triage@sha256:9ab...
memory_schema: v3                     # see the rollback lesson
eval_gate:
  suite: refund-triage-golden@2026-09
  requires: pass_rate >= 0.92 over n = 50 runs

Two habits make this pay off. First, stamp the version id on every trace and every result record — attribution after the fact is impossible otherwise. Second, make the manifest the only way to deploy, so a change that is not in the manifest cannot reach production. That is what turns "we think it was the prompt edit" into a diff.

Interactive sorting exercise: Nine changes land this sprint. Which ones produce a new agent version (and therefore an eval gate), which are pure operations, and which need a state migration on top?

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.