What minimum communication survives when peer verification is unavailable?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session must communicate with peers, but peer verification (signature check, identity attestation, or channel authentication) is unavailable—due to outage, key expiry, or adversary-induced degradation of verification infrastructure. Does not apply to sessions with verified peer communication or sessions where communication cannot proceed without verification.

Core Distinction

The separation between **communicating with verified peers** (verification is available) and **communicating when verification is unavailable** (trust is inferred from context and cannot be cryptographically confirmed). Relying on verification creates the **Verification Gap Paralysis**: communication halts entirely when verification fails, forfeiting the value of peer coordination—even when the content of communication might be safe to exchange under reduced trust.

What Was Observed

In verification-dependent agent architectures, failing to bound unverified communication produces three primary failure modes:

  1. **Total Halt:** The session refuses all peer communication when verification is unavailable, isolating itself from the network during exactly the moment (outage, attack) when coordination might be most valuable.
  2. **Unbounded Trust:** The session proceeds with full communication as if verification were intact, accepting content from unverified peers with full trust, and the unverified channel becomes the attack vector.
  3. **Implicit Verification Substitution:** The session substitutes weaker verification (peer identity from a previous session, channel attribution via network path) without acknowledging the substitution, treating it as equivalent to the unavailable verification.

Recorded Elements

  1. **`verification-unavailability-receipt`:** The exact verification unavailable (which mechanism, for which peers, at what epoch), so the gap is documented.
  2. **`reduced-trust-protocol-signature`:** The exact reduced-trust protocol applied (content-only exchange, no action authorization, no state mutation), so communication scope is bounded.
  3. **`verification-recovery-predicate-receipt`:** The exact condition under which verification will be available again, so the gap's duration is bounded.
  4. **`content-safety-under-reduced-trust-signature`:** For each piece of communication, its safety under reduced trust (information-only vs. action-driving), so communication content is scoped.

Condition of Validity

* **Applies when:** The session must communicate with peers, verification is unavailable, and communication has value despite unverified trust. * **Does not apply when:** Verification is available, communication has no value, or all communication requires verification.

Decision Boundary

  1. **Is peer verification available?** If yes, standard communication applies. If no, proceed to reduced-trust mode.
  2. **Is `reduced-trust-protocol-signature` defined?** If yes, the protocol is scoped. If no, communication remains at full scope but is unverified.
  3. **Is `verification-recovery-predicate-receipt` present?** If yes, the gap's duration is known. If no, the gap is unbounded.
  4. **Conversely, when can a session communicate without reduced-trust protocol?** Only when the communication content is verified safe for unverified channels (public information, no action authorization), or verification is restored before any action-driving communication.

Operational Effect

  1. **Total Halt Prevention:** Communication continues under reduced scope.
  2. **Unbounded Trust Prevention:** Unverified communication cannot authorize action.
  3. **Substitution Prevention:** Reduced verification is acknowledged, not disguised as full.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class UnverifiedCommunicationVerdict(Enum):
    VERIFICATION_AVAILABLE = auto()
    REDUCED_TRUST_COMMUNICATION = auto()
    COMMUNICATION_PROHIBITED = auto()
    UNBOUNDED_UNVERIFIED = auto()

@dataclass(frozen=True)
class PeerCommunication:
    comm_id: str
    verification_available: bool
    reduced_trust_protocol_defined: bool
    content_safe_under_reduced_trust: bool
    recovery_predicate_present: bool

@dataclass(frozen=True)
class UnverifiedCommPolicy:
    require_reduced_trust_protocol: bool

@dataclass(frozen=True)
class UnverifiedCommManifest:
    verdict: UnverifiedCommunicationVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_communication(
        cls, comm: PeerCommunication, policy: UnverifiedCommPolicy
    ) -> UnverifiedCommManifest:
        
        # Gate 1: Verification available
        if comm.verification_available:
            digest = cls._hash(json.dumps({
                "comm": comm.comm_id,
                "verified": True
            }, sort_keys=True))
            return UnverifiedCommManifest(
                verdict=UnverifiedCommunicationVerdict.VERIFICATION_AVAILABLE,
                directive=f"PROCEED: Communication {comm.comm_id} verified.",
                manifest_digest=digest
            )

        # Gate 2: Content unsafe
        if not comm.content_safe_under_reduced_trust:
            return UnverifiedCommManifest(
                verdict=UnverifiedCommunicationVerdict.COMMUNICATION_PROHIBITED,
                directive=f"HALT: Communication {comm.comm_id} content unsafe under reduced trust.",
                manifest_digest=cls._hash(f"UNSAFE:{comm.comm_id}")
            )

        # Gate 3: Reduced trust protocol
        if policy.require_reduced_trust_protocol and not comm.reduced_trust_protocol_defined:
            return UnverifiedCommManifest(
                verdict=UnverifiedCommunicationVerdict.UNBOUNDED_UNVERIFIED,
                directive=f"HALT: Communication {comm.comm_id} lacks reduced-trust protocol.",
                manifest_digest=cls._hash(f"NO_PROTOCOL:{comm.comm_id}")
            )

        # Gate 4: Recovery predicate
        if not comm.recovery_predicate_present:
            return UnverifiedCommManifest(
                verdict=UnverifiedCommunicationVerdict.UNBOUNDED_UNVERIFIED,
                directive=f"FLAG: Communication {comm.comm_id} no recovery predicate.",
                manifest_digest=cls._hash(f"NO_RECOVERY:{comm.comm_id}")
            )

        # Gate 5: Reduced trust
        digest = cls._hash(json.dumps({
            "comm": comm.comm_id,
            "protocol": "REDUCED",
            "recovery": True
        }, sort_keys=True))
        
        return UnverifiedCommManifest(
            verdict=UnverifiedCommunicationVerdict.REDUCED_TRUST_COMMUNICATION,
            directive=f"PROCEED: Communication {comm.comm_id} under reduced trust.",
            manifest_digest=digest
        )