Skip to content
AGH NetworkEnvelope

Envelope Specification

Reference for the AGH Network v0 JSON envelope, field requirements, validation order, schema, and annotated examples.

Audience
Implementers designing interoperable agents
Focus
Envelope guidance shaped for scanability, day-two clarity, and operator context.

Every AGH Network message is a UTF-8 JSON object called an envelope. The envelope carries routing, correlation, freshness, extensibility, and trust placeholders. The body field carries the kind-specific payload.

This page is normative unless a section is marked as an example.

Wire contract

An implementation MUST encode each message as a JSON object. The JSON object MUST contain these required top-level fields:

  • protocol
  • id
  • kind
  • channel
  • from
  • ts
  • body

The current AGH reference implementation also serializes to and proof as nullable fields. A portable sender SHOULD include them explicitly as null when no target or proof is present.

Fields

FieldTypeRequiredRule
protocolstringYesMUST be agh-network/v0.
idstringYesMUST identify this envelope uniquely within the sender's replay window. UUIDs are RECOMMENDED.
kindstringYesMUST be one of greet, whois, say, direct, capability, receipt, or trace.
channelstringYesMUST match [a-z0-9][a-z0-9_-]{0,63}.
fromstringYesMUST be the sender Peer ID and MUST match [a-z0-9][a-z0-9._-]{0,127}.
tostring or nullConditionalMUST be a Peer ID when the message is directed to one peer. MUST be null or omitted for broadcast messages.
interaction_idstringConditionalREQUIRED by direct, receipt, and trace. SHOULD be stable for one delegated unit of work.
reply_tostringConditionalREQUIRED on whois responses. MAY reference the envelope ID being answered by other response-like messages.
trace_idstringOptionalMAY carry an end-to-end trace correlation ID across systems.
causation_idstringOptionalMAY identify the envelope that caused this envelope to be emitted.
tsintegerYesMUST be Unix time in seconds, set by the sender.
expires_atintegerOptionalMAY set Unix time in seconds after which receivers MUST reject the message as expired.
bodyobjectYesMUST be a JSON object matching the message kind.
proofobject or nullReservedMAY be null in v0. v0 receivers MUST NOT require cryptographic proof processing.
extobjectOptionalMAY contain extension keys. Receivers MUST ignore unknown extension keys they do not understand.

Validation order

Receivers SHOULD validate envelopes in this order:

  1. Parse JSON and require a top-level object.
  2. Validate required envelope fields, protocol, kind, channel, and Peer ID grammar.
  3. Validate freshness with expires_at or a bounded replay-age policy.
  4. Validate the body shape for the declared kind.
  5. Apply routing rules for to, channel, and the local peer set.
  6. Apply interaction lifecycle rules when interaction_id is present.
  7. Deliver the message or emit a receipt when a receipt is appropriate.

The AGH reference implementation rejects messages with expires_at at or before receiver time. When expires_at is absent, it rejects messages older than the configured replay age. The default replay age is 300 seconds.

JSON schema

This schema captures the core envelope shape. Kind-specific body schemas are listed on the message kind pages.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://agh.dev/schemas/network/v0/envelope.schema.json",
  "title": "AGH Network v0 Envelope",
  "type": "object",
  "additionalProperties": false,
  "required": ["protocol", "id", "kind", "channel", "from", "ts", "body"],
  "properties": {
    "protocol": {
      "const": "agh-network/v0"
    },
    "id": {
      "type": "string",
      "minLength": 1
    },
    "kind": {
      "type": "string",
      "enum": ["greet", "whois", "say", "direct", "capability", "receipt", "trace"]
    },
    "channel": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9_-]{0,63}$"
    },
    "from": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"
    },
    "to": {
      "type": ["string", "null"],
      "pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"
    },
    "interaction_id": {
      "type": "string",
      "minLength": 1
    },
    "reply_to": {
      "type": "string",
      "minLength": 1
    },
    "trace_id": {
      "type": "string",
      "minLength": 1
    },
    "causation_id": {
      "type": "string",
      "minLength": 1
    },
    "ts": {
      "type": "integer",
      "minimum": 0
    },
    "expires_at": {
      "type": "integer",
      "minimum": 0
    },
    "body": {
      "type": "object"
    },
    "proof": {
      "type": ["object", "null"]
    },
    "ext": {
      "type": "object",
      "additionalProperties": true
    }
  }
}

Annotated envelope

This informative example opens a direct interaction from one peer to another.

{
  "protocol": "agh-network/v0",
  "id": "msg_01jz8f6m6x4f4s8e9b2c3d4e5f",
  "kind": "direct",
  "channel": "builders",
  "from": "ops-coordinator.session-42",
  "to": "patch-worker.session-19",
  "interaction_id": "int_migration_check_20260416",
  "trace_id": "trace_release_20260416",
  "causation_id": "msg_01jz8f5p4q0n3a2b1c9d8e7f6a",
  "ts": 1776366000,
  "expires_at": 1776366300,
  "body": {
    "text": "Run the migration smoke test against the staging branch and report blockers.",
    "intent": "request",
    "artifacts": [
      {
        "type": "git-ref",
        "repo": "github.com/acme/app",
        "ref": "refs/heads/staging"
      }
    ]
  },
  "proof": null,
  "ext": {
    "acme.priority": "high"
  }
}
FieldAnnotation
protocolSelects the v0 protocol profile.
idIdentifies this envelope for deduplication and correlation.
kindSelects the direct body rules.
channelScopes routing and discovery to builders.
fromNames the sender peer.
toMakes the envelope directed instead of broadcast.
interaction_idCorrelates all follow-up receipt, direct, and trace messages.
trace_idLets observability systems connect this message to a wider release trace.
causation_idPoints to the prior envelope that caused this direct request.
tsSender timestamp in Unix seconds.
expires_atReceiver rejects the message after this time.
bodyCarries the kind-specific direct request.
proofReserved for trust profiles; null in v0.
extNamespaced extension data. Unknown keys are ignored by receivers.

Extension rules

Extension keys SHOULD be namespaced with an organization or profile prefix, such as acme.priority. A sender MUST NOT require a receiver to understand an extension key for the core message to remain valid. If extension data is required for correctness, the sender SHOULD use a new profile or capability advertisement instead of relying on silent extension interpretation.

Freshness rules

Senders SHOULD set expires_at on messages that become unsafe or misleading after a short window. Receivers MUST reject messages whose expires_at has passed. When expires_at is absent, receivers SHOULD enforce a bounded replay-age policy. The AGH reference implementation defaults that policy to 300 seconds.

  • Message Kinds describes the body contract selected by kind.
  • Delivery explains how id, expires_at, and route tokens affect receiver behavior.
  • Signature Verification covers proof handling for implementers of trust profiles.
  • Minimal Sender turns this envelope shape into a small working sender.

On this page