Generated protocol artifacts
Harn publishes downstream protocol artifacts under
spec/protocol-artifacts/. The directory is generated by:
make gen-protocol-artifacts
CI and make all verify drift with:
make check-protocol-artifacts
The generated contract includes:
manifest.json: protocol versions, schema provenance, ACP method names,sessionUpdatediscriminators, Harn extension fields, tool lifecycle metadata fields, A2A task states, MCP metadata vocabulary, and abindingsblock enumerating the published TypeScript, Swift, Python, and Go modules with their stability tier and (for Go) the canonical module path.schemas/*.schema.json: stable copies of the ACP, A2A, MCP, tool-receipt, collaborative plan-document, andharn-tools/2.0contracts covered by generated drift and protocol checks. The Harn tools artifact validates the catalog envelope; Harn's Rust parser validates embedded Draft 2020-12 schemas, reference closure, and cross-entry invariants. MCP publishes only the stable2026-07-28profile.harn-tools.ts: strict TypeScript types for the transport-neutral tool catalog. The generator derives this file andschemas/harn-tools-v2.schema.jsonfrom the same Rust contract types.harn-protocol.ts: TypeScript bindings for JSON-RPC messages, ACPsession/update, collaborative plan documents, Harn tool lifecycle metadata, A2A task events, and MCP tool/resource/prompt metadata.HarnProtocol.swift: SwiftCodabledefinitions for the same host-facing surface.HarnRunSessionView.swift: Swift run/session view records derived from native Rust schemas and deserialize defaults. Compile it alongsideHarnProtocol.swift. The correspondingschemas/run-session-view-v1.schema.jsonretains full native fields; reasoning and evaluation receipts remain opaque JSON arrays, preserving unreported versus measured-empty evidence. Hosts check the supported schema and version once before using a decoded view. Missing historical producer identity stays unknown; newly produced views identify the current runtime.HarnAgentsEventProjectionandHarnAgentsTaskStatus: stream identity, payload, and task-state bindings derived fromharn-serve/openapi.yaml. Asession.updateevent already carries canonical ACP params inpayload. Forward that object tosession/updatewithout rebuilding its content, tool fields, or metadata. Unknown event kinds can be ignored while retaining their cursor; unknown task states must not be treated as terminal. Generated terminal-state helpers come from the native task lifecycle, including its distinction between waiting for approval and finishing.python/harn_protocol.py: stdlib-only Python 3.9+ module withEnumclasses for every wire vocabulary, dataclasses for the JSON-RPC envelopes, ACP session updates, Harn tool lifecycle metadata, A2A task structures, and MCP tool/resource metadata, plusto_wire/from_wirehelpers that strip unset optional fields so envelopes stay byte-equivalent to the Rust adapter output. Field names match the wire JSON (camelCase).go/harnprotocol/: Go module (harnprotocolpackage) mirroring the same surface with typed string aliases andencoding/json-tagged structs. Thego.moddeclaresgithub.com/burin-labs/harn/spec/protocol-artifacts/go/harnprotocolas the canonical module path so consumers cango getdirectly from the repository.fixtures/round_trip.json: representative request/response/notification envelopes, including a collaborative plan update, plus an A2A task and an MCP tool entry.make check-bindingsdecodes and re-encodes these through the Python and Go bindings on every CI run, catching wire-vocabulary drift before downstream consumers see it.
MCP helpers include the stable 2026-07-28 identity, required request _meta
keys, standard Streamable HTTP
headers (MCP-Protocol-Version, Mcp-Method, Mcp-Name), server/discover,
ttlMs/cacheScope cache hints, input_required results, the stable tasks
extension, the -32022 unsupported-version error, and the JSON Schema 2020-12
dialect URL. Harn's runtime and generated bindings share this registry.
The generated MCPDiscoverResult follows the released SDK shape: ttlMs and
cacheScope are required, and server identity lives at
_meta["io.modelcontextprotocol/serverInfo"], not in a top-level
serverInfo field.
Harn's HTTP servers enforce those routing headers as well as authoring them.
Missing or mismatched required headers, malformed stable request metadata, and
missing required capabilities retain their JSON-RPC error body and use HTTP
400 Bad Request.
Stability#
The host-facing surface listed above is stable: existing wire values and
field names will not change without a Harn minor-version migration note plus a
regenerated artifact diff. Hosts can pin to the artifact directory for the
full surface or to the manifest.json bindings block when they only need to
detect generator/runtime mismatch.
This release publishes harn-tools/2.0 as the first pre-launch contract that
includes declared application errors. Its discriminator versions the tool
catalog independently of the Harn crate. Version 1 catalogs are intentionally
rejected; producers must regenerate the catalog and language bindings together.
After version 2 ships, additive optional fields keep the discriminator.
Removing a field, changing a field type, or tightening an owned closed record
requires a new catalog discriminator and a migration note.
JSON Schema documents, source.binding, and namespaced _meta values remain
intentional open extension points.
VM internals (the AST, code-index, scanner schemas under
crates/harn-hostlib/schemas/** aside from the published wire profiles) are
not part of this surface. They evolve with the runtime and should be
consumed via the Rust crates rather than vendored as bindings.
Versioning#
Artifacts follow the Harn crate version in manifest.json.
Additive changes are minor-version compatible:
- new
sessionUpdateor_harn/agentEventvalues; - new optional fields under
_meta.harn; - new
ToolKind,ToolCallStatus,ToolCallErrorCategory, A2A task state, or MCP metadata values that clients can ignore safely.
Breaking changes require a Harn minor-version migration note:
- removing or renaming a wire value;
- moving a field between canonical ACP locations and
_meta.harn; - changing a required field's type;
- tightening a schema so previously valid Harn adapter output is rejected.
Consumer migration#
Rust consumers of Harn's public error and terminal taxonomies must include a
wildcard fallback in matches. Their native enums are non_exhaustive, so adding
a reason does not invalidate a downstream match that already handles the
fallback.
Generated Rust open-vocabulary enums preserve unfamiliar wire strings in
Unrecognized(String). When vendored into the consumer's own crate, they still
require a _ match arm: Rust's non_exhaustive restriction applies only across
crate boundaries. Matching every current unit variant plus Unrecognized
does not cover a new unit variant after regenerating the bindings. Match the
known cases that affect behavior, and send every other case to a fallback.
Hosts should consume the generated bindings or schema artifacts instead of
mirroring Harn protocol enums by hand. Burin consumers can replace local
ACPSessionUpdate, ACPToolKind, and ACPToolCallStatus mirrors with
spec/protocol-artifacts/harn-protocol.ts, and can use
spec/protocol-artifacts/HarnProtocol.swift as the Swift contract source for
ACP session updates and tool-call metadata. Python and Go integrators can
import spec/protocol-artifacts/python/harn_protocol.py (e.g. by vendoring
the file or pinning the artifact directory) and the
harnprotocol Go module under spec/protocol-artifacts/go/harnprotocol
respectively.
TypeScript clients that consume a catalog should import ToolCatalog from
harn-tools.ts. Other language generators should consume
schemas/harn-tools-v2.schema.json; they should not infer catalog types from
MCP tools/list or an OpenAPI source document. See
Tool registry adapters for the runtime and
static catalog surfaces. The generated schema is a structural gate, not a
substitute for Harn's semantic catalog parser.
Cross-repo release jobs can run:
DOWNSTREAM_HOST_ROOT=/path/to/host-checkout make check-downstream-protocol-artifacts
to fail when a downstream host's vendored Swift or TypeScript protocol bindings drift from the Harn source artifacts.
For ACP, clients should still follow the wire namespacing rules in
Bridge protocol: canonical ACP fields remain at the
session-update root, while Harn vendor fields live under _meta.harn.