Skip to main content

Module wire

Module wire 

Source
Expand description

The CGP wire envelope and its framing (SPEC.md §Transport bindings).

§This is not JSON-RPC

Earlier revisions of this module claimed CGP “rides MCP’s transport and lifecycle conventions (JSON-RPC 2.0, …)”. That was not true of the wire it described, and the claim has been withdrawn — see ADR 0002. CGP’s envelope is a bespoke type-tagged JSON object: there is no jsonrpc member, no method/params split. Its lifecycle is informed by MCP (a handshake that negotiates version and capabilities before any payload moves), but the framing is its own.

A JSON-RPC binding — an alternate encoding of this same semantic layer — may be specified later without touching frame or query semantics and without a new protocol family. Keeping the semantic layer and the transport binding separate is what makes that possible.

§Framing

Every message is newline-delimited JSON (NDJSON): exactly one serde_json value per line — the simplest thing that is unambiguous over a pipe and trivially reimplementable in a provider kit in any language. HTTP providers receive the same envelope as a JSON request body and reply with one as the response body.

The envelope is versioned: the handshake negotiates the protocol family up front, and a mismatch is a named error, never a hang (SPEC.md §H3).

§Correlation

query, frames, and error carry an optional id. A provider MUST echo the id of the request it is answering. An envelope with no id is a notification: it expects no reply, which is the shape a future push-invalidation extension needs (docs/sketches/push-invalidation.md).

id is optional so that a provider written against an earlier revision stays conformant: it is queried in lock-step and is fully conformant.

Correlation is negotiated explicitly, via Capabilities::correlation — a host MUST NOT send an id to a provider that did not declare it (SPEC.md §3.2). This paragraph previously said the opposite (“negotiated by observation, not by a capability flag”), which predates the capability and inverts a MUST NOT: a reply carrying no id is ambiguous between “does not implement correlation” and “implements it incorrectly”, and a guarantee whose violation is indistinguishable from legitimate behaviour cannot be checked.

Note that verify/verified carry no id at all: a verdict echoes the frame identity it answers in full, so those exchanges correlate by matching rather than by envelope id (SPEC.md §9).

Structs§

AttesterKey
A public key a provider publishes at the handshake, so a verifier can check the attestations it goes on to serve (SPEC.md §6.5.4).

Enums§

Envelope
One Context Graph Protocol message. Every variant is a small, versioned, type-tagged JSON object; the host writes exactly one per line (NDJSON) over stdio and one per HTTP body (SPEC.md §2).

Functions§

decode_line
Parse one NDJSON line into an envelope. A garbage line is a clean HostError::Wire, never a panic — the crash-consistency contract (task deliverable 5).
encode_line
Serialize an envelope to a single NDJSON line (trailing \n included).
envelope_kind
The human name of an envelope variant, for error messages that report “expected X, got Y”.
next_correlation_id
Mint a fresh correlation id.
verify_correlation
Check that a reply carries the correlation id of the request it answers (SPEC.md §H4).
versions_compatible
Two protocol version strings interoperate when they share a major family — the substring up to the first .. So contextgraph/1.0-draft and contextgraph/1.0 interoperate (both contextgraph/1), while contextgraph/2.0 does not. This is what allowed the public v1.0 freeze to drop the -draft suffix without a flag day (SPEC.md).