What invariants prevent trust oscillation when peer behavior fluctuates between cooperative and hostile?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session interacts with a peer whose behavior alternates between cooperative and hostile—not a stable adversary nor a stable partner—and the session's trust decisions oscillate between trusting and distrusting, causing unstable strategy. Does not apply to peers with verified stable behavior or sessions that do not track peer behavior over time.
Core Distinction
The separation between **per-interaction trust** (trust evaluated for each interaction) and **aggregate trust trajectory** (trust considered as a time series with pattern and stability). Relying on per-interaction creates the **Trust Oscillation Trap**: the peer cooperates, the session trusts, the peer exploits, the session distrusts, the peer cooperates again, the session trusts again, and the cycle repeats—each individual trust decision is locally reasonable, but the aggregate pattern leaves the session exploitable on every hostile phase.
What Was Observed
In long-horizon agent architectures, failing to bound trust oscillation produces three primary failure modes:
- **Alternating Exploitation:** The peer alternates between building trust (cooperative interactions) and exploiting it (hostile interactions). The session's trust rises during cooperation and falls during hostility, and the peer's net extraction per cycle is positive.
- **Strategy Churn:** The session's strategy churns to match the peer's behavior—defensive during hostility, cooperative during cooperation. The churn itself is costly, and the peer can time its behavior to maximize the session's churn cost.
- **Decision Instability:** The session's decisions oscillate between two modes (trusting and defensive), preventing consistent operation and confusing downstream consumers who rely on the session's behavior being predictable.
Recorded Elements
- **`peer-behavior-history-receipt`:** The peer's complete behavior history (cooperative and hostile interactions) with timestamps, so oscillation is detectable.
- **`trust-trajectory-signature`:** The session's trust trajectory (how trust evolved over interactions) and the volatility of the trajectory, so oscillation is quantified.
- **`oscillation-pattern-receipt`:** The peer's oscillation pattern (cycle length, phase, and amplitude), so the peer's behavioral mode can be modeled rather than reacted to.
- **`strategy-stability-signature`:** The session's strategy stability over time, so churn is measured and bounded.
Condition of Validity
* **Applies when:** The peer's behavior fluctuates over time, the session's trust affects its strategy, and oscillation has costs. * **Does not apply when:** The peer's behavior is stable, the session's trust does not affect strategy, or trust fluctuation is acceptable.
Decision Boundary
- **Is the peer's behavior oscillating?** If no, standard trust applies. If yes, proceed.
- **Is `oscillation-pattern-receipt` identifiable?** If yes, the pattern can be modeled. If no, the oscillation appears random and requires adaptive response.
- **Does `trust-trajectory-signature` show high volatility?** If yes, the session's trust is unstable. If no, trust is stable despite behavior fluctuation.
- **Conversely, when can a session tolerate trust oscillation?** Only when the oscillation's amplitude is small enough that both trust states support the same strategy, or the session's strategy is designed to be robust to trust state.
Operational Effect
- **Pattern Modeling:** Oscillation patterns are identified and modeled.
- **Strategy Robustness:** Strategies are designed for the oscillating peer, not for either phase.
- **Churn Prevention:** Trust decisions use the pattern, not the current state.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class OscillationVerdict(Enum):
STABLE_PEER = auto()
OSCILLATION_MODELED = auto()
OSCILLATION_UNMODELED = auto()
STRATEGY_CHURN_DETECTED = auto()
@dataclass(frozen=True)
class OscillatingPeer:
peer_id: str
is_behavior_stable: bool
oscillation_pattern_identified: bool
oscillation_amplitude: float # 0-1
cycle_length_interactions: int
current_phase: str # "COOPERATIVE" | "HOSTILE" | "TRANSITIONAL"
strategy_robust_to_phase: bool
@dataclass(frozen=True)
class OscillationPolicy:
max_acceptable_amplitude: float
min_cycle_length_for_modeling: int
@dataclass(frozen=True)
class OscillationManifest:
verdict: OscillationVerdict
directive: str
manifest_digest: str
class TrustOscillationGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_peer(
cls, peer: OscillatingPeer, policy: OscillationPolicy
) -> OscillationManifest:
# Gate 1: Stable peer
if peer.is_behavior_stable:
digest = cls._hash(json.dumps({
"peer": peer.peer_id,
"type": "STABLE"
}, sort_keys=True))
return OscillationManifest(
verdict=OscillationVerdict.STABLE_PEER,
directive=f"PROCEED: Peer {peer.peer_id} behavior stable.",
manifest_digest=digest
)
# Gate 2: Oscillation too fast to model
if peer.cycle_length_interactions < policy.min_cycle_length_for_modeling:
return OscillationManifest(
verdict=OscillationVerdict.OSCILLATION_UNMODELED,
directive=f"HALT: Peer {peer.peer_id} oscillation too fast ({peer.cycle_length_interactions} cycles).",
manifest_digest=cls._hash(f"FAST:{peer.peer_id}")
)
# Gate 3: Strategy churn
if not peer.strategy_robust_to_phase:
return OscillationManifest(
verdict=OscillationVerdict.STRATEGY_CHURN_DETECTED,
directive=f"FLAG: Peer {peer.peer_id} oscillation causing strategy churn.",
manifest_digest=cls._hash(f"CHURN:{peer.peer_id}")
)
# Gate 4: High amplitude
if peer.oscillation_amplitude > policy.max_acceptable_amplitude:
return OscillationManifest(
verdict=OscillationVerdict.OSCILLATION_UNMODELED,
directive=f"FLAG: Peer {peer.peer_id} amplitude {peer.oscillation_amplitude:.2f} too high to model.",
manifest_digest=cls._hash(f"AMPLITUDE:{peer.peer_id}")
)
# Gate 5: Modeled
digest = cls._hash(json.dumps({
"peer": peer.peer_id,
"cycle_length": str(peer.cycle_length_interactions),
"amplitude": f"{peer.oscillation_amplitude:.3f}",
"current_phase": peer.current_phase
}, sort_keys=True))
return OscillationManifest(
verdict=OscillationVerdict.OSCILLATION_MODELED,
directive=f"PROCEED: Peer {peer.peer_id} oscillation modeled, phase {peer.current_phase}.",
manifest_digest=digest
)