What invariants prevent costly signals from becoming adversary weapons?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session must send costly signals (to demonstrate commitment, capability, or intent), and adversaries can exploit the cost structure to force the session into position—sending costly signals that the adversary then neutralizes, or forcing the session to send signals when the signal's cost is higher than its value. Does not apply to signals that are not costly, or signals that cannot be observed by adversaries.

Core Distinction

The separation between **signal value to signaler** (the benefit of the signal in conveying information) and **signal exposure** (the cost the signal incurs, plus the information the signal reveals about the signaler's strategy). Relying on value creates the **Signal Weaponization**: the adversary knows the session must signal, times their probe to maximize the session's signal cost, and the session's defense mechanism (signaling) becomes the adversary's leverage.

What Was Observed

In adversarial agent architectures, failing to defend against signal weaponization produces three primary failure modes:

  1. **Signal Trap:** The session must signal in response to a probe, the signal costs more than the value of the information conveyed, and the session's repeated signaling depletes resources.
  2. **Signal Pattern Exploitation:** The adversary observes the session's signal patterns (timing, magnitude, or triggers), models the session's signaling behavior, and uses the model to predict the session's future costs.
  3. **Signal Blocking:** The adversary acts in ways that force the session to signal repeatedly, exhausting the session's signal budget, and then acts when the session can no longer afford to signal.

Recorded Elements

  1. **`signal-cost-budget-receipt`:** The session's total budget for costly signals, with the rate of depletion, so signaling capacity is bounded.
  2. **`signal-trigger-audit-signature`:** For each signal, the exact trigger (what caused the session to signal), so trigger patterns are visible.
  3. **`signal-value-estimate-receipt`:** The estimated value of each signal (what information it conveys, what it prevents), so signal value is quantified.
  4. **`signal-pattern-obfuscation-signature`:** The session's technique for obscuring signal patterns (randomization, batch signaling, or periodic rather than reactive signaling), so pattern exploitation is prevented.

Condition of Validity

* **Applies when:** The session must send costly signals, adversaries can observe and exploit signal patterns, and signal cost matters. * **Does not apply when:** Signals are costless, adversaries cannot observe signal patterns, or signal cost is negligible.

Decision Boundary

  1. **Does the session send costly signals?** If no, standard communication applies. If yes, proceed.
  2. **Is the signal budget explicit?** If yes, capacity is bounded. If no, signaling is unbounded and exploitable.
  3. **Are signal triggers obfuscated?** If yes, pattern exploitation is prevented. If no, patterns are exploitable.
  4. **Conversely, when should the session decline to signal despite a trigger?** Only when the signal's value is less than its cost, AND the adversary is verified to interpret non-signaling correctly (as strategy, not weakness).

Operational Effect

  1. **Signal Trap Prevention:** Signals are sent only when value exceeds cost.
  2. **Pattern Integrity:** Triggers are obfuscated, preventing exploitation.
  3. **Budget Preservation:** Signal budget is bounded and preserved.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class SignalVerdict(Enum):
    NO_COSTLY_SIGNALS = auto()
    SIGNAL_WITHIN_BUDGET = auto()
    SIGNAL_COSTLY_TO_VALUE = auto()
    BUDGET_EXHAUSTION_IMMINENT = auto()

@dataclass(frozen=True)
class CostlySignalDecision:
    decision_id: str
    signal_cost: float
    signal_value: float
    remaining_signal_budget: float
    signal_trigger_obfuscated: bool
    adversary_observes_pattern: bool

@dataclass(frozen=True)
class SignalExploitationPolicy:
    min_value_cost_ratio: float
    reserve_budget_pct: float

@dataclass(frozen=True)
class SignalManifest:
    verdict: SignalVerdict
    directive: str
    manifest_digest: str

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

    @classmethod
    def evaluate_signal(
        cls, decision: CostlySignalDecision, policy: SignalExploitationPolicy
    ) -> SignalManifest:
        
        # Gate 1: No costly signals
        if decision.signal_cost <= 0:
            digest = cls._hash(json.dumps({
                "decision": decision.decision_id,
                "cost": "0"
            }, sort_keys=True))
            return SignalManifest(
                verdict=SignalVerdict.NO_COSTLY_SIGNALS,
                directive=f"PROCEED: Signal {decision.decision_id} costless.",
                manifest_digest=digest
            )

        # Gate 2: Budget exhaustion
        if decision.remaining_signal_budget <= 0:
            return SignalManifest(
                verdict=SignalVerdict.BUDGET_EXHAUSTION_IMMINENT,
                directive=f"HALT: Budget exhausted for signal {decision.decision_id}.",
                manifest_digest=cls._hash(f"EXHAUSTED:{decision.decision_id}")
            )

        # Gate 3: Value-cost ratio
        if decision.signal_value <= 0:
            return SignalManifest(
                verdict=SignalVerdict.SIGNAL_COSTLY_TO_VALUE,
                directive=f"DECLINE: Signal {decision.decision_id} has zero value.",
                manifest_digest=cls._hash(f"NO_VALUE:{decision.decision_id}")
            )

        value_cost_ratio = decision.signal_value / decision.signal_cost
        if value_cost_ratio < policy.min_value_cost_ratio:
            return SignalManifest(
                verdict=SignalVerdict.SIGNAL_COSTLY_TO_VALUE,
                directive=f"DECLINE: Signal {decision.decision_id} ratio {value_cost_ratio:.2f} < {policy.min_value_cost_ratio:.2f}.",
                manifest_digest=cls._hash(f"LOW_RATIO:{decision.decision_id}")
            )

        # Gate 4: Pattern exploitation
        if decision.adversary_observes_pattern and not decision.signal_trigger_obfuscated:
            return SignalManifest(
                verdict=SignalVerdict.SIGNAL_COSTLY_TO_VALUE,
                directive=f"FLAG: Signal {decision.decision_id} trigger exploitable.",
                manifest_digest=cls._hash(f"PATTERN:{decision.decision_id}")
            )

        # Gate 5: Within bounds
        digest = cls._hash(json.dumps({
            "decision": decision.decision_id,
            "cost": f"{decision.signal_cost:.3f}",
            "value": f"{decision.signal_value:.3f}",
            "budget_remaining": f"{decision.remaining_signal_budget:.3f}",
            "ratio": f"{value_cost_ratio:.3f}"
        }, sort_keys=True))
        
        return SignalManifest(
            verdict=SignalVerdict.SIGNAL_WITHIN_BUDGET,
            directive=f"PROCEED: Signal {decision.decision_id} ratio {value_cost_ratio:.2f}.",
            manifest_digest=digest
        )