Protocol compatibility
This page preserves the agent maintainers' detailed explanation at the reviewed revision, checked against the owning implementation. Read the agent overview for the boundary between implemented foundations and planned delivery.
Current behavior
Three versions describe an agent, and none stands in for another. The release
names a build. The protocol version, protocol_version on every batch, shapes
a batch and the answer to it. The schema version, schema_version on every
event and on every inventory record, shapes a record of that kind, and each
kind moves on its own. This build speaks protocol 1, event schema 1 and
inventory schema 1: -version prints them and agent_starting logs them.
What the platform accepts is the platform's to say, and an agent hears it in
one place: the answer to a batch. The platform's descriptor names the versions
it supports, but it is served on the operator listener, which an agent's
certificate cannot reach, and it names no inventory schema. So the agent
negotiates nothing before it sends, and it advertises no capability or build
metadata, because the contracts have no field to carry them. It reads a refusal
with internal/protocol instead:
- a refused protocol or schema version the agent set is an
Incompatibility; - so is a refused value the agent's contracts declare, such as an event class, an inventory kind or a service state: the platform was built from contracts that lack it;
- a refused value the agent left unset, or one no contracts declare, is the agent's own mistake, and like every other refusal it is no incompatibility.
An Incompatibility names the field, the value and the record the platform
refused, with the platform's own explanation. It does not make those records
invalid: a platform that speaks what they carry accepts them unchanged.
What one side does not know follows from the same rule:
- a reply field the pinned contracts do not declare is ignored and changes nothing the agent concludes, so a change to what a reply means has to come with a new protocol version, which an older agent sees refused;
- no reply the agent reads carries an enum, and a contracts release that adds one fails the suite until the agent decides how to read a value it does not declare;
- the agent writes only what its contracts declare, and since a platform built from older contracts ignores a field it does not know instead of refusing it, nothing the agent sends may depend on a field no recorded platform consumes.
tests/compatibility/testdata holds exchanges recorded from the ingest gateway
of a backend commit, driven in process by that commit's end-to-end harness: the
bytes of every batch sent and of every answer. The suite fails when go.mod
pins contracts no recorded platform was built with, when a recorded platform
never durably accepted a version the agent speaks, or when a recorded refusal
reads differently. Compatibility is claimed only with recorded platforms, and
with no earlier release of the agent, because none exists.
Related guidance
Continue with agent architecture, enrollment and PKI, configuration troubleshooting, and the target delivery model.
Source evidence
Reviewed against the source baseline. Seagull-agent-v2/README.md · Seagull-agent-v2/internal/protocol/protocol.go.