Skip to content

feat: migrate agent versioning to v2 branch model - #29

Merged
prat11m merged 1 commit into
mainfrom
feat/versioning-v2-branch-model
Jul 23, 2026
Merged

feat: migrate agent versioning to v2 branch model#29
prat11m merged 1 commit into
mainfrom
feat/versioning-v2-branch-model

Conversation

@prat11m

@prat11m prat11m commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Cuts the MCP's write path over from the v1 draft/version model to the v2 branch/revision model. Every config edit now targets the agent's live branch draft; publishing commits a new revision that goes live. This is a hard cutover — no dual path, no activeVersionId conditional. Once the backend flips ENABLE_BRANCH_MODEL, the v1 write + list endpoints 409 (versioning_v2_migration_required), so the MCP must use the branch APIs.

Spec: PRO-1789. Backend guard: #3066. Freeze: #3063. Plan: workdocs/agent-versioning/mcp-v2-migration-plan.md.

⚠️ DO NOT MERGE until T0

Merging to main auto-publishes to npm (release.yml), and npx users pull it on their next editor restart. A v2-only MCP against a pre-flip backend 404s on /branches. So this must merge only at T0, after the backend flips ENABLE_BRANCH_MODEL and the migration is validated. (Client-side tool → there's no local flag to flip; the published version is the switch.)

What changed

  • src/versioning.ts (new) — branch client: resolveLiveBranch (GET /branchesisLive), saveConfigToLiveBranch (PUT /branches/{id}/draft), publishLiveBranch / restoreRevisionOnLiveBranch with async security-scan polling (200 committed / 202 scanning; poll draft until it commits or securityCheck.status === "failed").
  • src/api.ts — add PUT; formatApiError now returns first-class messages for 423 AGENT_CONFIG_FROZEN ("edits paused for a maintenance window") and 409 versioning_v2_migration_required ("update your MCP").
  • Removed the activeVersionId conditional everywhere — write helpers are linear (resolve live branch → PUT draft); non-versioned direct-PATCH config paths deleted.
  • Remapped tools: update_agent (+ add/remove_agent_tool) → live branch draft (see the consolidation section below); publish_draft → branch publish (+poll, no separate activate); activate_versionmake_branch_live (POST /branches/{id}/live — in v2 only a branch head can serve, so this switches which branch runs; takes branch_id); list_versions → branch revisions; list_drafts → branches; make_call → live head revision.
  • Dropped draft_id params — one implicit draft per branch, edits auto-stack.

Versioning surface redesigned around the branch model

The whole edit/versioning surface was reworked to the v2 model (branches → revisions; one unnamed draft per branch), reviewed call-by-call with the owner. 74 tools.

Branch selection: edit/read/publish/list-revisions/test tools take an optional branch_id. Omitted + one branch → act on it; omitted + multiple branches → return the branch list and ask the user to pick (retry with branch_id); given → use it. resolveBranch() drives this; make_call always uses the live head.

Final versioning tools:

  • Branches: list_branches, create_branch, rename_branch, make_branch_live
  • Draft (per branch, unnamed/binary): get_branch_draft, publish_draft
  • Revisions (branch-scoped): list_revisions, get_revision
  • Diff / Test: diff (GET /agent/{id}/diff, refs = revisionId or <branchId>:draft), test_agent (POST /branches/{id}/test-call, include_draft | revision_id)
  • Edit (all take branch_id): update_agent (config + prompt + pre-call API), add_agent_tool (api_call), remove_agent_tool, configure_call_actions (end_call/transfer — restored; agent-level, matters for multi-agent)

Renamed: list_versions→list_revisions, get_version→get_revision, get_draft→get_branch_draft, list_drafts→list_branches, activate_version→make_branch_live.
Merged: diff_versions+get_draft_diff→diff; test_draft+test_version→test_agent.
Removed: rename_draft (unnamed drafts), update_version (label set at publish), compare_version_metrics (not in v2). No archive_branch (not in v2 scope yet).
Draft-safe list edits: add/remove_agent_tool and configure_call_actions share one read-modify-write against the branch's open draft (GET /agent?draftId=<openDraftId>_resolvedConfig.tools, else head), so stacked edits compose. No backend changes.

Review fixes (all 8 addressed)

  1. Playbooks migrated to v2add_playbooks / update_playbook / configure_playbooks now edit the branch draft (branch_id, saveConfigToBranch); no more POST /drafts with sourceVersionId: activeVersionId. Multi-agent editing works post-flip.
  2. Branch-scoped tool readfetchAgentAndTools reads the target branch's open draft, else its head (?versionId=headRevisionId), never the live config; plus a guard that aborts instead of wiping tools if _resolvedConfig is absent.
  3. Stale test_draft refs in update_agent / chattest_agent.
  4. Publish description — confirmed intended: the v2 branch-publish body is {label?} only; there is no description field to forward.
  5. README write-tools table rewritten for the v2 surface + a Versioning section.
  6. Smoke testsmoke.mjs + npm run smoke asserts the tool surface (all expected present, none removed leaked). ⚠️ Not wired into CI in this PR — the push token lacks workflow scope; add - run: node smoke.mjs to .github/workflows/ci.yml after the build step.
  7. Concurrency caveatadd_agent_tool description now says make tool edits one at a time (RMW; concurrent edits to one branch can drop each other).
  8. pollScan false-committed edge — a 404 during scan polling now confirms the branch head actually advanced before reporting "committed"; otherwise it keeps polling (guards against a discarded draft / eventual-consistency 404).

Freeze behaviour (per requirement)

While AGENT_CONFIG_FROZEN is on, every config-write tool surfaces the clean "frozen, edits paused" message (the backend 423 covers branch writes too). Reads, test_draft/test_version, and scoring keep working. Enforcement stays at the API — the MCP only translates.

Not in this PR (follow-ups before/around launch)

  • playbooks.ts (multi-agent editing) still uses v1 draft endpoints → will 409 under the flag. Needs a follow-up before multi-agent users are cut over.
  • rename_draft, update_version still call v1 (draft naming / version metadata don't exist in v2) → they 409 with the "update your MCP" message. Deprecate/remap in a follow-up.
  • By-id reads (get_draft, get_version, get_draft_diff, diff_versions) and test_draft/test_version are unchanged — they keep working under v2.

What to test

Against a dev backend with ENABLE_BRANCH_MODEL on + a migrated agent (ATOMS_API_URL=https://api.dev.smallest.ai/atoms/v1):

  • update_agent_config / update_agent_prompt / add_agent_tool / set_pre_call_api / configure_call_actions → change lands on the live branch draft (list_drafts shows hasOpenDraft: true).
  • publish_draftboth paths: sync committed (live immediately) and async scanning (polls, then live); a prompt that fails the scan → failed, draft kept.
  • make_branch_live(branch_id) → that branch's head becomes the live config (get branch IDs from list_drafts).
  • list_versions → branch revisions; make_call → dispatches with the head revision.
  • Freeze: flip AGENT_CONFIG_FROZEN on dev → every write tool returns the frozen message; test-call + reads still work.

What to validate

  • Type-check + build clean (npm run type-check && npm run build). ✅
  • All 79 tools still register (stdio tools/list). ✅
  • No activeVersionId reads remain on the write path.

Deployment

  • No new env vars. No migration.
  • Publish (merge) at T0 only, after the backend flip + migration validation. npx users auto-update on editor restart; binary-installer users must re-run the installer (covered by launch comms).

🤖 Generated with Claude Code

@prat11m
prat11m force-pushed the feat/versioning-v2-branch-model branch 2 times, most recently from 42147b8 to a7e6ebe Compare July 16, 2026 13:11
Cut the MCP over from the v1 draft/version model to the v2 branch/revision
model, and redesign the edit/versioning tool surface around it. Reads and
test-calls keep working; the v1 write + list endpoints 409 once the backend
flips ENABLE_BRANCH_MODEL, so the MCP now uses the branch APIs.

Core:
- versioning.ts: branch client — resolveBranch (branch_id | single | ask-when-
  ambiguous), resolveLiveBranch, saveConfigToBranch, publishBranch with async
  security-scan polling (200 committed / 202 scanning; on 404 confirm the head
  advanced before reporting committed).
- api.ts: PUT; formatApiError translates 423 AGENT_CONFIG_FROZEN and 409
  versioning_v2_migration_required into clear messages.
- Tool edits are a single read-modify-write against the TARGET branch — its open
  draft, else its head revision (?versionId=headRevisionId), never the live
  config — with a guard that aborts rather than wiping tools if the config can't
  be resolved.

Tool surface (74 tools; branch_id optional on edit/read/publish/test, asks when
the agent has multiple branches):
- Branches: list_branches, create_branch, rename_branch, make_branch_live
- Draft (per branch, unnamed): get_branch_draft, publish_draft
- Revisions (branch-scoped): list_revisions, get_revision
- Diff/Test: diff, test_agent
- Edit: update_agent (config+prompt+pre-call API), add_agent_tool (api_call),
  remove_agent_tool, configure_call_actions (end_call/transfer, agent-level)
- Playbooks (multi_agents) migrated to the branch model: add_playbooks,
  update_playbook, configure_playbooks now edit the branch draft via branch_id.
- Renamed: list_versions→list_revisions, get_version→get_revision,
  get_draft→get_branch_draft, list_drafts→list_branches,
  activate_version→make_branch_live
- Merged: diff_versions+get_draft_diff→diff; test_draft+test_version→test_agent
- Removed: rename_draft, update_version, compare_version_metrics

Adds a stdio smoke test (smoke.mjs, npm run smoke) asserting the tool surface.
No backend changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@prat11m
prat11m force-pushed the feat/versioning-v2-branch-model branch from a7e6ebe to 500af4a Compare July 16, 2026 13:32
@prat11m
prat11m merged commit 278b631 into main Jul 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants