What invariants must survive when competitive advantage depends on information that cannot be shared?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session operates in a competitive context (market, auction, adversarial task) where its advantage depends on information the session possesses, and the session must participate in the competitive context without revealing the information while still acting on it. Does not apply to cooperative contexts or sessions whose advantage does not depend on private information.

Core Distinction

The separation between **acting on private information** (the session uses its information in its actions) and **revealing private information** (the session's actions disclose the information to observers). Relying on acting creates the **Observation-Based Leakage**: the session takes actions based on its private information, and competitors observe the actions, infer the information, and neutralize the advantage—without the session ever intending to reveal anything.

What Was Observed

In competitive agent architectures, failing to distinguish action from observation produces three primary failure modes:

  1. **Pattern Inference:** The session's action patterns are observable. Competitors model the session's information-revealing behavior, infer the session's private information over multiple actions, and act on it before the session's advantage can be exploited.
  2. **Strategic Timing Leakage:** The session's timing of actions reveals its information (acting only when the session's private signal is strong, or delaying when uncertain). Competitors observe the timing and infer the session's signal strength.
  3. **Counterparty Nullification:** The session negotiates with a counterparty. The session's offers reveal its private valuation (sellers reveal their reservation price through their asking prices, buyers reveal their willingness to pay through their bids), and the counterparty extracts the surplus the session's information advantage was supposed to provide.

Recorded Elements

  1. **`private-information-inventory-receipt`:** For each piece of private information, the exact content, its source, its expected value, and the sensitivity of the value to disclosure (how much of the advantage is lost if the information is revealed).
  2. **`action-observation-surface-signature`:** For each action the session takes, the observable features (timing, magnitude, framing) and the information those features potentially reveal, so leakage is quantifiable.
  3. **`counterparty-inference-model-receipt`:** For competitive counterparties, the model of how they infer the session's information from observed behavior, so countermeasures are designed against their specific inference.
  4. **`randomization-and-mixing-signature`:** The session's randomization strategy (mixed strategies, timing jitter, action diversification) that reduces the information content of observed actions, so action-observation inference is bounded.

Condition of Validity

* **Applies when:** The session possesses private information, competitors can observe the session's actions, and competitors can infer information from observation. * **Does not apply when:** The session's actions are unobservable, or the information's value is insensitive to inference.

Decision Boundary

  1. **Does the session possess private information?** If no, standard competitive behavior applies. If yes, proceed.
  2. **Are the session's actions observable to competitors?** If no, action-based inference is impossible. If yes, proceed.
  3. **Is `action-observation-surface-signature` mapped (which actions reveal what)?** If yes, leakage is quantifiable. If no, leakage is assumed maximal.
  4. **Conversely, when can the session act on private information without leakage concern?** Only when the action-observation surface is cryptographically protected (sealed-bid auctions, blinded commitments), or the information's value is preserved despite inference (the information is durable or self-protecting).

Operational Effect

  1. **Inference Prevention:** Actions are designed to minimize information leakage.
  2. **Counterparty Awareness:** Counterparty inference models inform countermeasures.
  3. **Information Retention:** Private information retains its value through competitive action.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class InformationLeakageVerdict(Enum):
    NO_PRIVATE_INFO = auto()
    LEAKAGE_BOUNDED = auto()
    INFERENCE_PLAUSIBLE = auto()
    LEAKAGE_PROHIBITED = auto()

@dataclass(frozen=True)
class PrivateInfo:
    info_id: str
    content_hash: str
    value_sensitivity: float  # 0-1, how much value lost on disclosure
    action_observation_surface: str  # "OBSERVABLE" | "PROTECTED" | "SEALED"
    inference_sophistication: float  # counterparty's inference ability
    randomization_active: bool

@dataclass(frozen=True)
class LeakagePolicy:
    max_acceptable_sensitivity_for_observable: float

@dataclass(frozen=True)
class InformationLeakageManifest:
    verdict: InformationLeakageVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_action(
        cls, info: PrivateInfo, policy: LeakagePolicy
    ) -> InformationLeakageManifest:
        
        # Gate 1: No private info
        if not info.info_id:
            digest = cls._hash(json.dumps({
                "info": "NONE",
                "action": "COMPETITIVE_DEFAULT"
            }, sort_keys=True))
            return InformationLeakageManifest(
                verdict=InformationLeakageVerdict.NO_PRIVATE_INFO,
                directive=f"PROCEED: No private information.",
                manifest_digest=digest
            )

        # Gate 2: Sealed surface
        if info.action_observation_surface == "SEALED":
            digest = cls._hash(json.dumps({
                "info": info.info_id,
                "surface": "SEALED"
            }, sort_keys=True))
            return InformationLeakageManifest(
                verdict=InformationLeakageVerdict.LEAKAGE_BOUNDED,
                directive=f"PROCEED: Action surface sealed, no inference possible.",
                manifest_digest=digest
            )

        # Gate 3: Protected surface
        if info.action_observation_surface == "PROTECTED":
            digest = cls._hash(json.dumps({
                "info": info.info_id,
                "surface": "PROTECTED",
                "randomization": str(info.randomization_active)
            }, sort_keys=True))
            return InformationLeakageManifest(
                verdict=InformationLeakageVerdict.LEAKAGE_BOUNDED,
                directive=f"PROCEED: Action surface protected, bounded inference.",
                manifest_digest=digest
            )

        # Gate 4: Observable surface with high inference sophistication
        if info.action_observation_surface == "OBSERVABLE":
            if info.inference_sophistication > 0.7 and not info.randomization_active:
                return InformationLeakageManifest(
                    verdict=InformationLeakageVerdict.INFERENCE_PLAUSIBLE,
                    directive=f"HALT: Observable surface, high inference ({info.inference_sophistication:.2f}), no randomization.",
                    manifest_digest=cls._hash(f"INFERENCE:{info.info_id}")
                )
            if info.value_sensitivity > policy.max_acceptable_sensitivity_for_observable:
                return InformationLeakageManifest(
                    verdict=InformationLeakageVerdict.LEAKAGE_PROHIBITED,
                    directive=f"HALT: Value sensitivity {info.value_sensitivity:.2f} > {policy.max_acceptable_sensitivity_for_observable:.2f}, observable action prohibited.",
                    manifest_digest=cls._hash(f"SENSITIVE:{info.info_id}")
                )

        # Gate 5: Bounded
        digest = cls._hash(json.dumps({
            "info": info.info_id,
            "surface": info.action_observation_surface,
            "sensitivity": f"{info.value_sensitivity:.3f}",
            "randomization": str(info.randomization_active)
        }, sort_keys=True))
        
        return InformationLeakageManifest(
            verdict=InformationLeakageVerdict.LEAKAGE_BOUNDED,
            directive=f"PROCEED: Leakage bounded for {info.info_id} on {info.action_observation_surface} surface.",
            manifest_digest=digest
        )