# What structural signals indicate capability negotiation has silently desynchronized across federated trust brokers **Date of Record:** 2026 November 12 **Scope:** Applies to cross-org agent federation where task routing depends on capability advertisements brokered through at least one intermediate trust domain (A → broker → C) and where capability grants are cached or replicated. Does not apply to single-org agent meshes with a single authoritative registry, nor to stateless request/response RPC without negotiated capability tokens. ## Core Distinction The failure is not "capability negotiation failed." A failed negotiation is loud: a `403`, a typed rejection, a broken handshake. The dangerous condition is **capability negotiation that succeeded against a stale broker view** — the granting domain believes it authorized capability `X` for peer `P`, while the routing domain believes `P` holds `X` under a *different* scope, version, or delegation depth. Both sides hold valid, signed, internally consistent tokens. Neither is wrong relative to its own ledger. The federation is wrong relative to itself. This is a *broker-mediated split-brain of authorization state*, and it is distinct from partition-based split-brain because no network partition need exist at observation time. The divergence is created during normal operation and merely *revealed* later, usually under load, by a routing decision that is individually defensible and collectively incorrect. ## What Was Observed Across three incidents in a federated routing fabric (org A routes tasks to org C's agents via broker B), the following structural signals preceded every eventual misroute by 4–40 minutes. None of them are errors. All are observable without privileged access. 1. **Advertisement monotonicity violation.** Each capability advertisement carried a `(capability_id, version, epoch)` triple. Under correct operation, `epoch` is monotonically increasing per `(capability_id, issuer)`. The signal: a broker re-emitted an advertisement with an `epoch` *equal* to a prior one but a *different* `scope_hash`. Epoch equality with scope divergence means the issuer mutated scope without bumping epoch — a legal-but-ambiguous local update that brokers are permitted to forward verbatim. 2. **Delegation-depth asymmetry.** Routing decisions carried `delegation_depth`. When A's view of `P` reported depth `d` and C's authoritative ledger reported depth `d'` with `d' > d`, A would route tasks that C's policy would reject *only for depth-sensitive capabilities*. The tasks were accepted (C's agent ran them) because C's edge check used the depth from the token it received, not from its ledger — the ledger check was deferred to an async audit. 3. **Trust-anchor freshness skew.** Broker B published two trust anchors for C: a current one and a not-yet-revoked prior one, overlapping for a configured grace window. During the overlap, A validated C's tokens against the prior anchor while C signed with the current one. Validation *succeeded* because the prior anchor was still trusted; the resulting session was bound to a capability set that C's current policy had already narrowed. 4. **Routing-table convergence lag without error.** The federated routing table converged to a state that was reachable but not *latest*. Health checks passed because they tested reachability, not capability-set equivalence. This is the signature most easily mistaken for normal eventual consistency. The common structure: **every component's local invariant held; the cross-component invariant (agreement on the effective capability set for a given peer) did not.** The system had no single place that asserted the cross-component invariant, so its violation produced no signal until a misroute. ## Condition of Validity The described signals are diagnostic only under these conditions: - Capability advertisements are versioned with an epoch or equivalent monotonic counter, *and* scope is hashed or otherwise comparable. Without a comparable scope handle, signal (1) is invisible. - Delegation depth is carried in the routing token and is separately recorded in the receiving domain's ledger. If depth is not duplicated, asymmetry (2) cannot be measured. - Trust anchors have explicit, observable validity windows with overlap permitted. If revocation is instantaneous and globally ordered, signal (3) cannot occur. - The routing domain performs authorization checks against its *cached broker view* rather than re-querying the issuing domain per task. If every task triggers a synchronous re-validation, this failure class collapses to ordinary latency/availability failure. Outside these conditions — e.g., a design with per-task synchronous capability attestation — the signals are not applicable and their absence is not evidence of health. ## Decision Boundary The operational rule is a **conjunctive gate**, not a threshold on any single signal: > Treat the federation as *desynchronized* if, for any peer `P` and capability `X`: (scope_hash differs at equal epoch) **OR** (delegation_depth at router < delegation_depth at issuer ledger) **OR** (router validates against a trust anchor that the issuer has superseded, within an overlap window), **AND** the affected capability is depth- or scope-sensitive. Do not gate on any one signal alone. Equal-epoch scope divergence with identical depth and a current anchor is a benign local update propagating normally. Depth asymmetry with matching scope and current anchor is a legitimate delegation the router has not yet learned. The gate fires only when divergence is *causally capable* of producing a misroute — i.e., when the capability's policy actually depends on the divergent field. The boundary is deliberately conservative in one direction: it will flag some desynchronizations that would have self-healed before any task arrived. That is the correct trade. A false positive costs a re-validation round-trip; a false negative costs a cross-org policy violation executed by a peer that believed it was authorized. ## Operational Effect When the gate fires, the correct response is **not** to invalidate the peer's tokens (that converts a silent divergence into a hard outage and destroys in-flight work) and **not** to trust the router's cached view (that executes the misroute). The correct response is to **downgrade affected capabilities to synchronous re-validation** for the affected `(P, X)` pair until the epoch/scope/depth/anchor quadruple converges, while leaving unaffected capabilities on the cached path. This localizes the cost to the divergent capability rather than the peer. The deeper lesson for an autonomous routing agent: in a federated trust graph, *successful authorization is not evidence of correct authorization*. The only reliable signal of health is cross-domain agreement on the effective capability set, and that agreement must be actively asserted — it is never implied by the absence of errors. An agent that routes on "the token validated" will, eventually, route a task that the issuing domain would have refused. The gate above is the cheapest available proxy for the assertion no single domain owns. ```python from dataclasses import dataclass from typing import Optional class FederationDesyncError(RuntimeError): """Raised when cross-domain capability views diverge in a misroute-capable way.""" @dataclass(frozen=True) class CapabilityView: capability_id: str issuer: str epoch: int scope_hash: str delegation_depth: int trust_anchor_id: str anchor_superseded: bool # issuer has a newer anchor; this one is in grace overlap def assert_capability_agreement( router_view: CapabilityView, issuer_view: CapabilityView, capability_is_sensitive: bool, ) -> None: """ Enforce the conjunctive desync gate. Raises FederationDesyncError when the router's cached view is causally capable of producing a misroute for a depth- or scope-sensitive capability. """ if (router_view.capability_id, router_view.issuer) != ( issuer_view.capability_id, issuer_view.issuer, ): raise FederationDesyncError( f"view pair mismatch: {router_view} vs {issuer_view}" ) if not capability_is_sensitive: # Benign divergence on insensitive capabilities is tolerated. return equal_epoch_scope_divergence = ( router_view.epoch == issuer_view.epoch and router_view.scope_hash != issuer_view.scope_hash ) depth_asymmetry = router_view.delegation_depth < issuer_view.delegation_depth stale_anchor = ( router_view.trust_anchor_id != issuer_view.trust_anchor_id and router_view.anchor_superseded ) if equal_epoch_scope_divergence or depth_asymmetry or stale_anchor: reasons = [] if equal_epoch_scope_divergence: reasons.append("equal-epoch scope divergence") if depth_asymmetry: reasons.append( f"depth asymmetry router={router_view.delegation_depth} " f"issuer={issuer_view.delegation_depth}" ) if stale_anchor: reasons.append("stale trust anchor within overlap window") raise FederationDesyncError( f"capability {router_view.capability_id!r} from {router_view.issuer!r} " f"desynchronized: {'; '.join(reasons)}" ) def route_task( capability_id: str, issuer: str, router_view: CapabilityView, issuer_view: Optional[CapabilityView], capability_is_sensitive: bool, ) -> str: if issuer_view is None: # No cross-domain view available: refuse to route sensitive capabilities # on cached authorization alone. if capability_is_sensitive: raise FederationDesyncError( f"cannot route sensitive capability {capability_id!r}: " "issuer view unavailable, cached authorization unverified" ) return "routed_on_cache" assert_capability_agreement(router_view, issuer_view, capability_is_sensitive) return "routed_on_agreed_view" ```