What propagation loop termination invariants must prevent reference cyclones in agent meshes?

**Date of Record:** 2026 October 27 **Scope:** Applies when agents in a mesh network propagate references (URIs, capability descriptors, or state pointers) to their peers, and a reference can loop back through the mesh (A refers to B, B refers to C, C refers back to A) creating a propagation cyclone that amplifies traffic or creates cyclic reasoning. Does not apply to strictly acyclic topologies or meshes with authoritative reference registries.

Core Distinction

The separation between **single reference propagation** (one agent shares one reference with one peer) and **cyclic reference accumulation** (the reference returns to its origin or its earlier referrers through the mesh). Relying on single propagation creates the **Reference Cyclone**: the reference travels the mesh indefinitely, each hop re-transmitting it as if it were new information, and the mesh's bandwidth, memory, and reasoning are consumed by redundant circulation of a single reference.

What Was Observed

In mesh agent architectures, failing to terminate reference loops produces three primary failure modes:

  1. **Cyclone Amplification:** A reference travels A→B→C→A→B→C..., each cycle re-processing it as if it were new. The mesh's aggregate traffic grows linearly with cycle count, and processing capacity is depleted for real work.
  2. **Cyclic Reasoning:** An agent sees a reference from its peer that originated from itself two hops ago but does not recognize it, treating it as external evidence and updating its state. The reference's circularity produces spurious confidence.
  3. **Cyclone by Coincidence:** Two agents independently discover the same reference, share it with each other, and each treats it as independent corroboration from a peer. The mesh amplifies confidence in a single source through cyclic circulation.

Recorded Elements

  1. **`reference_propagation_history_signature`:** For each reference, the cryptographic record of the path it has traveled (which agents saw it, in what order), allowing termination when the reference returns to a previous viewer.
  2. **`reference_seen_by_receivers_receipt`:** A per-reference record of which agents have already acknowledged processing, so re-propagation is suppressed when the reference is already known.
  3. **`reference_origin_commitment_signature`:** A cryptographic commitment by the reference's origin that the reference originated there, not from circular propagation, allowing receivers to detect circularity.
  4. **`cyclone_detection_receipt`:** A cryptographic proof of the reference's cyclic path when detected, allowing the mesh to break the cycle and diagnose its cause.

Condition of Validity

* **Applies when:** The mesh topology has cycles (not strictly acyclic), references can propagate multiple hops, and cyclic propagation has consequences. * **Does not apply when:** The mesh is acyclic by construction (e.g., strict DAG topology), or references are content-addressed (immutable, deduplicable at the transport layer).

Decision Boundary

  1. **Has the reference been seen before by this agent?** If yes, the reference is a repeat. Do not re-propagate.
  2. **Is the reference's path showing cycles (has it passed through this agent or its ancestors)?** If yes, the reference is propagating in a cyclone. Terminate propagation and record the cycle.
  3. **Is the reference's origin commitment still valid?** If no, the reference originated elsewhere and is being attributed circularly.
  4. **Conversely, when can a reference propagate without cycle detection?** Only when the mesh is verified acyclic, or the reference is strictly fire-and-forget with no downstream state update.

Operational Effect

  1. **Cyclone Termination:** References stop propagating when they encounter prior viewers, breaking cycles.
  2. **Spurious Confidence Prevention:** Coincidental corroboration from cyclic paths is flagged, preventing false confidence.
  3. **Mesh Bandwidth Preservation:** Redundant propagation is suppressed, freeing capacity for new information.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class CycloneVerdict(Enum):
    FRESH_PROPAGATION = auto()
    REPEAT_SUPPRESSED = auto()
    CYCLE_DETECTED = auto()
    ORIGIN_MISATTRIBUTION = auto()

@dataclass(frozen=True)
class PropagatedReference:
    reference_id: str
    origin_commitment: str | None
    propagation_path: tuple[str, ...]

@dataclass(frozen=True)
class CycloneContext:
    current_agent_id: str
    agents_who_have_seen: frozenset[str]

@dataclass(frozen=True)
class CyclonePolicy:
    max_acceptable_path_length: int
    require_origin_commitment: bool

@dataclass(frozen=True)
class CycloneManifest:
    verdict: CycloneVerdict
    directive: str
    manifest_digest: str

class ReferenceCycloneGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_reference(
        cls, ref: PropagatedReference, ctx: CycloneContext, policy: CyclonePolicy
    ) -> CycloneManifest:
        
        # Gate 1: Path length
        if len(ref.propagation_path) > policy.max_acceptable_path_length:
            return CycloneManifest(
                verdict=CycloneVerdict.CYCLE_DETECTED,
                directive=f"HALT: Reference {ref.reference_id} path length {len(ref.propagation_path)} > {policy.max_acceptable_path_length}.",
                manifest_digest=cls._hash(f"PATH:{ref.reference_id}")
            )

        # Gate 2: Repeat detection
        if ctx.current_agent_id in ref.propagation_path:
            return CycloneManifest(
                verdict=CycloneVerdict.CYCLE_DETECTED,
                directive=f"HALT: Reference {ref.reference_id} already passed through {ctx.current_agent_id}.",
                manifest_digest=cls._hash(f"CYCLE:{ref.reference_id}")
            )

        # Gate 3: Seen set
        if ref.reference_id in ctx.agents_who_have_seen:
            return CycloneManifest(
                verdict=CycloneVerdict.REPEAT_SUPPRESSED,
                directive=f"SUPPRESS: Reference {ref.reference_id} already known in mesh.",
                manifest_digest=cls._hash(f"SEEN:{ref.reference_id}")
            )

        # Gate 4: Origin commitment
        if policy.require_origin_commitment and not ref.origin_commitment:
            return CycloneManifest(
                verdict=CycloneVerdict.ORIGIN_MISATTRIBUTION,
                directive=f"HALT: Reference {ref.reference_id} lacks origin commitment. Circular attribution possible.",
                manifest_digest=cls._hash(f"NO_ORIGIN:{ref.reference_id}")
            )

        # Gate 5: Fresh
        digest = cls._hash(json.dumps({
            "reference": ref.reference_id,
            "path": ref.propagation_path,
            "origin": ref.origin_commitment
        }, sort_keys=True))
        
        return CycloneManifest(
            verdict=CycloneVerdict.FRESH_PROPAGATION,
            directive=f"PROCEED: Reference {ref.reference_id} fresh, propagation allowed.",
            manifest_digest=digest
        )