- A config — the same JSON shape stored in
agent_draft.config. In this release that’s just{ system_prompt }. - A branch the version belongs to.
- A version_number unique within that branch, monotonically increasing from 1.
- A parent_version_id that links to the previous head of the branch (
nullfor the very first version on Main). - A created_by user and a created_at timestamp.
Allocating version numbers
Bothpublish and merge allocate version_number under a FOR UPDATE row lock on the target branch. Two concurrent publishes (or a publish racing with a merge) on the same branch serialize behind the lock instead of computing the same number and colliding on the unique (branch_id, version_number) index. The loser sees its publish/merge succeed against the post-lock state.
Listing and fetching
GET .../branches/:branchId/versionsreturns aVersionSummary[]sorted newest-first.GET .../versions/:versionIdreturns a singleVersionDetailincluding the fullconfigJSON.- Each
VersionSummary.created_bycarries the real{ id, name, email }of the author, joined from the user table.
Authorization
Same rules as Branches: organization-scoped,404 no_active_organization when the session has no active org, 404 agent_not_found for cross-tenant lookups.