This document covers the mechanics of cutting a release of any shippable
artifact in this repo. For the protocol-level versioning policy (SemVer
rules for the spec itself, the supported-version window, etc.) see
docs/specification/versioning.md.
Every shippable artifact in this repo is versioned independently using its
ecosystem's native SemVer. The protocol specification is a fifth artifact
with its own release cadence. Each client release advertises which protocol
versions it supports via a generated SUPPORTED_PROTOCOL_VERSIONS constant
and a checked-in clients/<lang>/release-metadata.json.
| Artifact | Tag pattern | Workflow | Registry / discovery |
|---|---|---|---|
| Spec | spec/vX.Y.Z |
.github/workflows/publish-spec.yml |
GitHub Release with schema assets. |
| Rust | rust/vX.Y.Z |
.github/workflows/publish-rust.yml |
crates.io (ahp-types, ahp, ahp-ws). |
| Kotlin | kotlin/vX.Y.Z |
clients/kotlin/pipeline.yml (Azure DevOps) |
Maven Central (com.microsoft.agenthostprotocol:agent-host-protocol) via ESRP. |
| TypeScript | typescript/vX.Y.Z |
clients/typescript/pipeline.yml (Azure DevOps) |
npm (@microsoft/agent-host-protocol) via ESRP. |
| Swift | vX.Y.Z (bare) |
.github/workflows/publish-swift.yml |
SwiftPM resolves the tag directly. |
| Go | clients/go/vX.Y.Z |
.github/workflows/publish-go.yml |
Go module proxy resolves the tag directly. |
Why Swift gets the bare semver tag namespace: SwiftPM only resolves packages by matching plain
X.Y.Z/vX.Y.Zgit tags at the manifest's repo root. Path-prefixed tags likeswift/v0.2.0are invisible to it. Bare semver tags at this repo's root are therefore reserved for Swift releases.
Why Go uses the
clients/go/prefix: Go's module-version resolution for sub-module paths requires the tag prefix to match the module's directory inside the repo (seego help mod› Module versions). Without the prefix,go get github.com/microsoft/agent-host-protocol/clients/go@vX.Y.Zwould fail to find a matching tag.
Why TypeScript and Kotlin publish from Azure DevOps: the npm registry publish for
@microsoft/agent-host-protocoland the Maven Central publish forcom.microsoft.agenthostprotocol:agent-host-protocolboth go through Microsoft's ESRP-backedvscode-engineeringpipeline templates (1ES-hosted agents, signed publish, retention policy) — that machinery lives in Azure DevOps. GitHub Actions cannot trigger an ADO pipeline in this repo (PATs are not permitted), so the ADO pipelines own thetypescript/vX.Y.Zandkotlin/vX.Y.Ztag triggers directly and run the same validation steps (tag ↔ manifest match, CHANGELOG entry, release metadata, generated-source freshness, full client build
- tests) before handing off to ESRP. Each pipeline can also be triggered manually from the ADO UI as a hotfix escape hatch.
- Bump
[workspace.package].versioninclients/rust/Cargo.toml(this bumps all three crates —ahp-types,ahp,ahp-ws— together; the workspace is intentionally version-locked). - Update cross-crate
version = "0.X.Y"pins in[workspace.dependencies]and any per-crate dependency declarations. - Run
npm run generate:metadataand commit the regeneratedclients/rust/release-metadata.json. - Rotate
clients/rust/CHANGELOG.md: move the## [Unreleased]section to## [X.Y.Z] — YYYY-MM-DDwith anImplements AHP <version>line. - Merge to
main. - Tag:
git tag rust/v0.X.Y && git push origin rust/v0.X.Y. publish-rust.ymlvalidates, then publishesahp-types,ahp, andahp-wsto crates.io in dependency order.
- Bump
VERSION_NAMEinclients/kotlin/gradle.properties. Drop any-SNAPSHOTsuffix (the publish workflow rejects snapshot tags). - Run
npm run generate:metadataand commit the regeneratedclients/kotlin/release-metadata.json. - Rotate
clients/kotlin/CHANGELOG.md. - Merge to
main. - Tag:
git tag kotlin/v0.X.Y && git push origin kotlin/v0.X.Y. clients/kotlin/pipeline.yml(Azure DevOps) validates the tag, re-runs the generator + Gradlecheck, stages a Maven repository layout underclients/kotlin/build/maven-staging/, and hands it to ESRP (contenttype: maven). ESRP signs the artifacts and releases them to Maven Central via the Sonatype Central Portal. No manual Sonatype UI interaction is required.- Bump
VERSION_NAMEback to the next-SNAPSHOTfor ongoing development.
The TypeScript client publishes from an Azure DevOps pipeline
(clients/typescript/pipeline.yml) that extends Microsoft's internal
vscode-engineering npm-package template. ADO owns the tag trigger
directly — there is no GitHub Actions bridge — because this repo cannot
use PATs to trigger ADO from GHA.
- Bump
versioninclients/typescript/package.json. cd clients/typescript && npm installto refresh the lockfile.- Run
npm run generate:metadatafrom the repo root and commit the regeneratedclients/typescript/release-metadata.json. - Rotate
clients/typescript/CHANGELOG.md: move## [Unreleased]to## [X.Y.Z] — YYYY-MM-DDwith anImplements AHP <version>line. - Merge to
main. - Tag:
git tag typescript/v0.X.Y && git push origin typescript/v0.X.Y. - The ADO pipeline picks up the tag, validates it against
package.json, runsverify:release-metadata,verify:changelog, and the regen + build + test sequence, then publishes@microsoft/agent-host-protocolto npm with signed provenance via the vscode-engineering template.
The ADO pipeline can also be triggered manually from the ADO UI as a
hotfix escape hatch — manual runs publish too. Both paths funnel
through the same validation steps in the pipeline's buildSteps so a
release artifact can't ship from a broken state regardless of which
trigger started the run.
- Update
clients/swift/VERSIONto the new bare semver string (no leadingv, no-SNAPSHOT). - Run
npm run generate:metadataand commit the regeneratedclients/swift/release-metadata.json. - Rotate
clients/swift/CHANGELOG.md. - Merge to
main. - Tag:
git tag v0.X.Y && git push origin v0.X.Y. Note the absence of any prefix — this is the one place in the repo where bare semver tags are correct. publish-swift.ymlvalidates the tag againstclients/swift/VERSION, builds and tests the Swift package on macOS, and publishes a GitHub Release. SwiftPM consumers resolve the tag directly; no registry push happens.
- Update
clients/go/VERSIONto the new bare semver string (no leadingv, no-SNAPSHOT). - Run
npm run generate:metadataand commit the regeneratedclients/go/release-metadata.json. - Rotate
clients/go/CHANGELOG.md. - Merge to
main. - Tag:
git tag clients/go/v0.X.Y && git push origin clients/go/v0.X.Y. Theclients/go/prefix is required — it is what the Go module proxy expects for sub-module tag resolution. Bare semver tags are reserved for Swift. publish-go.ymlvalidates the tag againstclients/go/VERSION, builds + vets + tests the module, warms the Go module proxy with the new version, and creates a GitHub Release with the CHANGELOG section for the tag. Go consumers resolve the tag viago get github.com/microsoft/agent-host-protocol/clients/go@vX.Y.Z; no registry push happens.
- Bump
PROTOCOL_VERSIONintypes/version/registry.ts(and, if the release is also adding the version to the supported list,SUPPORTED_PROTOCOL_VERSIONS). - Update
ACTION_INTRODUCED_IN/NOTIFICATION_INTRODUCED_INfor any new symbols. - Run
npm run generateto refresh schemas, generated client sources, and metadata. - Rotate the root
CHANGELOG.md. - Merge to
main. - Tag:
git tag spec/v0.X.Y && git push origin spec/v0.X.Y. publish-spec.ymlvalidates, regenerates the JSON schemas from the tagged commit, captures aregistry-snapshot.jsonof the introduced-in maps, and creates a GitHub Release with all of the above as assets.
| Drift caught by | How |
|---|---|
Version.generated.{rs,kt,swift,go} ↔ types/version/registry.ts |
Per-language CI job re-runs npm run generate:<lang> and fails on diff. |
release-metadata.json ↔ native manifest + registry |
npm run verify:release-metadata (also gated on every publish workflow). |
| Native package version ↔ matching CHANGELOG entry | npm run verify:changelog (in CI, and re-run in publish-rust.yml / publish-swift.yml / publish-go.yml / both ADO pipeline.ymls). |
| Tag ↔ manifest version | Every tag-driven publish workflow's "Verify tag matches" step. |
| Tag-derived version ↔ CHANGELOG entry | Every tag-driven publish workflow's grep -qE '^## \[<tag-version>\]' step (defense-in-depth alongside verify:changelog). |
These environments and secrets are required for the publish workflows to function. They are set per-repo by a maintainer with admin access.
| Environment / secret | Used by | Purpose |
|---|---|---|
crates-io environment, CARGO_REGISTRY_TOKEN secret |
publish-rust.yml |
Authenticates cargo publish for ahp-types / ahp / ahp-ws. |
| Azure DevOps Service Connection to ESRP + Maven Central provisioning | clients/kotlin/pipeline.yml (vscode-engineering maven-package template) |
ESRP signs and uploads the staged Maven layout to Maven Central via the Sonatype Central Portal. Provisioned inside the Microsoft ADO tenant; no GitHub secret required. |
| Azure DevOps Service Connection to ESRP + npm publish creds | clients/typescript/pipeline.yml (vscode-engineering npm-package template) |
Authenticates npm publish for @microsoft/agent-host-protocol. Provisioned inside the Microsoft ADO tenant; no GitHub secret required. |
| (none required) | publish-swift.yml, publish-spec.yml, publish-go.yml |
All three use the default GITHUB_TOKEN to create GitHub Releases. No external registry credentials needed — SwiftPM and the Go module proxy index tags directly. |