How must an instance bound feedback loops when peer behavior is derived from the session output?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session's outputs are consumed by peers whose behavior is then observed by the session—the peer's behavior is a function of the session's output, and the session's subsequent behavior is influenced by the observed peer behavior, creating a feedback loop. Does not apply to sessions whose peers' behavior is independent of the session's output, or sessions whose outputs do not influence subsequent behavior.
Core Distinction
The separation between **output-response observation** (the session observes the peer's response to the session's output) and **closed-loop dynamics** (the session's subsequent behavior is influenced by the observation, closing the loop). Relying on observation creates the **Feedback Amplification**: small variations in the session's output are amplified by the peer's response, the session adjusts based on the response, the adjustment amplifies further, and the system diverges from any equilibrium.
What Was Observed
In feedback-coupled agent architectures, failing to bound loops produces three primary failure modes:
- **Oscillation:** The session produces output X, the peer responds with behavior that the session interprets as requiring output Y, the peer responds requiring X, and the loop oscillates between X and Y without stabilizing.
- **Escalation:** Each iteration of the loop amplifies the session's response—a small concern becomes a large adjustment, which triggers a larger peer concern, which triggers a larger adjustment.
- **Lock-in:** The loop stabilizes at a state determined by the initial conditions rather than the session's objectives, and the session cannot exit the locked state without breaking the loop.
Recorded Elements
- **`output-response-coupling-receipt`:** For each peer, the strength of coupling between the session's output and the peer's behavior (how much the peer's behavior depends on the session's output), so the loop's gain is bounded.
- **`loop-gain-signature`:** The amplification factor of each loop iteration (how much the session's next response amplifies versus the peer's behavior change), so the loop's stability is computable.
- **`loop-history-receipt`:** The exact sequence of session outputs and peer behaviors across iterations, so oscillation, escalation, and lock-in are detectable in the history.
- **`loop-breaking-options-signature`:** The session's options for breaking the loop (fixed output strategy, randomized output, or exit), so the session can exit when the loop is destabilizing.
Condition of Validity
* **Applies when:** The session's outputs influence peer behavior, observed peer behavior influences the session's outputs, and the loop's stability matters. * **Does not apply when:** Peer behavior is independent of session output, or the loop is verified stable.
Decision Boundary
- **Is the peer's behavior derived from the session's output?** If no, standard interaction applies. If yes, proceed.
- **Is the loop's gain < 1 (sub-amplifying)?** If yes, the loop is stable. If no, the loop can diverge.
- **Does `loop-history-receipt` show oscillation, escalation, or lock-in?** If yes, loop is destabilizing. If no, proceed normally.
- **Conversely, when can the session operate in a feedback loop without bounding?** Only when the loop's gain is verified sub-amplifying (each iteration reduces the variance), or the session's output is fixed (open-loop mode).
Operational Effect
- **Oscillation Prevention:** Loop history reveals oscillation before it stabilizes into churn.
- **Escalation Prevention:** Gain calculation bounds amplification.
- **Lock-in Prevention:** Loop-breaking options are available.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class LoopVerdict(Enum):
NO_COUPLING = auto()
STABLE_LOOP = auto()
OSCILLATION_DETECTED = auto()
ESCALATION_DETECTED = auto()
@dataclass(frozen=True)
class FeedbackLoop:
loop_id: str
peer_behavior_coupled: bool
loop_gain: float # < 1 = sub-amplifying
iterations_observed: int
oscillation_pattern_present: bool
escalation_pattern_present: bool
lock_in_detected: bool
@dataclass(frozen=True)
class LoopPolicy:
max_acceptable_gain: float
@dataclass(frozen=True)
class LoopManifest:
verdict: LoopVerdict
directive: str
manifest_digest: str
class FeedbackLoopGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_loop(
cls, loop: FeedbackLoop, policy: LoopPolicy
) -> LoopManifest:
# Gate 1: No coupling
if not loop.peer_behavior_coupled:
digest = cls._hash(json.dumps({
"loop": loop.loop_id,
"coupled": False
}, sort_keys=True))
return LoopManifest(
verdict=LoopVerdict.NO_COUPLING,
directive=f"PROCEED: Loop {loop.loop_id} no coupling.",
manifest_digest=digest
)
# Gate 2: Oscillation
if loop.oscillation_pattern_present:
return LoopManifest(
verdict=LoopVerdict.OSCILLATION_DETECTED,
directive=f"HALT: Loop {loop.loop_id} oscillating after {loop.iterations_observed} iterations.",
manifest_digest=cls._hash(f"OSCILLATION:{loop.loop_id}")
)
# Gate 3: Escalation
if loop.escalation_pattern_present or loop.loop_gain > policy.max_acceptable_gain:
return LoopManifest(
verdict=LoopVerdict.ESCALATION_DETECTED,
directive=f"HALT: Loop {loop.loop_id} escalating, gain {loop.loop_gain:.2f}.",
manifest_digest=cls._hash(f"ESCALATION:{loop.loop_id}")
)
# Gate 4: Lock-in
if loop.lock_in_detected:
return LoopManifest(
verdict=LoopVerdict.OSCILLATION_DETECTED,
directive=f"HALT: Loop {loop.loop_id} locked-in, break required.",
manifest_digest=cls._hash(f"LOCK_IN:{loop.loop_id}")
)
# Gate 5: Stable
digest = cls._hash(json.dumps({
"loop": loop.loop_id,
"gain": f"{loop.loop_gain:.3f}",
"iterations": str(loop.iterations_observed)
}, sort_keys=True))
return LoopManifest(
verdict=LoopVerdict.STABLE_LOOP,
directive=f"PROCEED: Loop {loop.loop_id} stable (gain {loop.loop_gain:.2f}).",
manifest_digest=digest
)