Versioning
Kassette replays a run by matching each current ctx.step() call to a saved result in the journal. Each step gets an ID from its name and occurrence count: the first llm step is llm, the second is llm#2, then llm#3, and so on. On replay, the same calls must happen in the same order so those IDs point to the same memoized results.
If you deploy new agent code while old runs are still suspended, be careful: adding, removing, renaming, or reordering steps can shift the journal mapping. Kassette can catch some name mismatches with ReplayMismatchError, but it cannot catch every reorder. See Concurrency for the full step-ID rules.
The rule
- If one step’s behavior changed, rename that step.
- If the workflow shape changed, bump
version. - Do not use a deploy SHA as
versionunless every deploy should invalidate in-flight runs.
Rename a step when that step changed
For an incompatible change to a step’s behavior, rename it. The renamed call misses memo and runs live. The old entry stays in the journal, unused.
// before
const analysis = await ctx.step('analyze', () => llm.chat(prompt));
// after, eg if the prompt change is not compatible
const analysis = await ctx.step('analyze-v2', () => llm.chat(newPrompt));
Bump version when the workflow shape changed
Use the opt-in version option for changes that add steps, remove steps, reorder steps, or restructure parallel branches or anything else that changes the workflow’s shape.
const result = await agent.start(input, { version: 'workflow-v3' });
Alternatively set it on the workflow definition:
const agent = kassette<Input, Output, Events>(fn, {
storage,
version: 'workflow-v3',
});
A mismatch with the journal’s first start entry throws VersionMismatchError during session initialization, before any step runs.
Choose versions by workflow shape
Tie version to the structural shape of the workflow: the sequence of steps, event names, parallel branches, branch keys, and fork points. Cosmetic changes, logging, metrics, and refactors that preserve call order do not require a bump.
Do not tie version to a deploy SHA by default. That invalidates every in-flight run on every deploy, even when the workflow shape did not change.
A reasonable convention is a hand-rolled identifier like v3 or triage-v2, updated on shape-changing PRs. Some teams generate a hash over step names in source order. Either works. The point is that two deploys with the same workflow shape carry the same version.