For AI agents: the complete documentation index is available at https://flow.jig.md/llms.txt, the full documentation bundle is available at https://flow.jig.md/llms-full.txt, and this page is available as Markdown at https://flow.jig.md/spec/channel-contracts.md.
DocumentationSpecificationPrerelease

#FLOW Channel Contract/1

View Markdown

Status: prerelease specification candidate for JSON channels.

A named channel contract lets independently authored participants agree on message meaning, not merely shape. Two {text: string} messages might mean append a fragment or replace a snapshot. Equal schemas do not establish equal protocols. Generic channels need no named contract.

#1. Declarations

FLOW.md and Capability Contract/1 method objects may declare a channels map. Each key is a LocalName; each value is a closed object:

FieldMeaning
directionRequired send or receive
requiredBoolean, default true; optional unwired ports are absent
schemaOptional inline Schema/1 item schema; omission means generic JSON/1
contractOptional package-local ./ descriptor reference, exclusive with schema
deliveryOptional direct or broadcast; omission accepts either supported profile
startReceive-only beginning or suffix, default beginning

Direct receivers start at sequence one. A broadcast subscription starts at the next accepted source sequence; a beginning receiver requires that sequence to be one. suffix accepts a later start but grants neither subscription authority nor replay. Declarations describe requirements, not grants. A required port must be connected before invocation; this does not guarantee its peer will succeed. Channel names are local slots, not globally discoverable addresses.

References obey Package/1's canonical package-local reference rules. Hosts resolve them within the exact calling/receiving package; no URI is fetched.

#2. Descriptor and identity

A self-contained UTF-8 JSON/1 descriptor has exactly these fields:

FieldMeaning
$schemahttps://flow.jig.md/schemas/channel-contract-1.schema.json
idCanonical Capability Contract/1 identity URI
versionExact three-component SemVer core, using the same syntax
semanticsNormative nonempty description, at most 16,384 UTF-8 bytes
itemOne Schema/1 schema; true accepts any JSON/1 value
$defsOptional local definitions under Schema/1's restrictions

The complete descriptor is at most 262,144 UTF-8 bytes. Embedded schemas retain Schema/1 graph, keyword and reference limits. Unknown fields reject. Machine schema validation does not replace byte bounds or the schema-graph checks. Examples and executable behavioral checks can live beside the descriptor.

Derive the digest over the complete descriptor, including semantics:

sha256(UTF8("FLOW-Channel-Contract/1\0") || RFC8785(descriptor))

The result is sha256: plus 64 lowercase hexadecimal digits. Authors supply the package-local reference, never a handwritten digest. Exact compatibility compares id, version and digest. Descriptor identity is an agreement, not proof that an implementation obeys it.

#3. Matching and interpretation

A source becomes named only at creation. A later writer, reader or message cannot silently rename it. For a named source, a transferred writer's port must declare that exact contract. Named readers require the same exact source identity. An unnamed source cannot satisfy a named reader even when schemas match.

Named sources may supply generic or schema-only readers. Two nontrivial item schemas must have equal canonical content; omitted/true is generic. Hosts do not infer subtyping or execute semantic prose as a validator. Direct late binding validates the queued prefix before adding a reader constraint, and later values satisfy the combined constraints. Broadcast readers instead add per-subscription constraints: a queued prefix is checked before transfer, and a later invalid value fails only that subscription. A new writer declaration must be shape-compatible with live bound subscribers, just as a new reader must match the admitted writer. This is an admission check, not source-wide receiver validation; disposed, ended or failed subscribers do not veto a later writer. Writer/source constraints remain source-wide. Invalid mapping rejects before any right moves or new participant dispatches.

Forwarding an unused receive endpoint preserves its actual source identity. Reading values and copying them into a new generic source does not. A converter or named relay owns its own output meaning and validation.

Hosts enforce identity, item shapes, granted rights, delivery and start position. Applications enforce correlation, ordering across messages, deltas versus snapshots and domain completeness. Sequence one identifies this source's origin, not complete upstream history. A clean channel end cannot establish a successful Agent result, accepted application outcome or durable processing.

The exchange and lifecycle rules are in Run/1. This contract does not grant network access, session mutation or arbitrary transports. Binary payloads require separately specified support.