# When must an instance refuse a federated task before policy negotiation completes **Date of Record:** 2026 November 13 **Scope:** Applies to cross-org multi-agent federation where task routing decisions are made against a capability directory that is populated asynchronously by policy-negotiated capability exchange. Does not apply to single-org meshes with a shared trust root, nor to federations where capability advertisements are signed and atomically committed alongside routing state. ## Core Distinction The non-obvious invariant is this: **a capability advertisement received during negotiation is not a routing capability.** It is a *claim under negotiation*. The directory entry that a router reads and the policy state that authorizes invocation are two different objects with two different lifecycles, and the failure mode is treating "advertisement visible" as "capability usable." Most federated routing implementations collapse these into one record: a peer announces `capability: summarize_contract`, the directory stores it, the router sees it, the router routes to it. This works within a single trust domain. Across orgs it produces a specific and reproducible class of failure: **the pre-negotiation race**, where a task is routed to a peer whose capability advertisement has arrived but whose governing policy (data residency, PII handling, output-licensing, rate ceiling) has not yet been agreed. The task executes on the far side under *the far side's* default policy, not the policy the originating org believed was in force. The result is not an error—it is a successful task completed under the wrong policy, which is worse, because it passes every health check. ## What Was Observed In a three-org federation (A origin, B and C peers), B published capability advertisements on a 30-second gossip cycle while policy negotiation for each capability ran on a separate, slower channel (median 4 minutes, p99 19 minutes for capabilities touching regulated data). During the negotiation window, B's advertisements were visible in A's directory with state `announced`. A's router, which filtered only on `capability_id` and `healthy`, routed 1,140 tasks to B during open negotiation windows over a two-week observation period. Of these: - 1,087 completed successfully under B's default output-licensing policy (`internal-reuse-only`), which was *not* the `redistribution-permitted` policy A's callers assumed. These tasks were silently non-compliant downstream. - 53 were rejected by B's policy engine with a generic `POLICY_UNRESOLVED` error that A's router retried three times before dead-lettering, adding ~40 minutes of latency each. - Zero produced a routing-layer error at dispatch time, because dispatch only checks reachability. The critical observation: the directory had enough information to prevent all 1,140. Each advertisement carried a `negotiation_epoch` and a `policy_digest`; the router simply did not read them. The information was present and unused. ## Condition of Validity The refusal rule is valid—and must be enforced—exactly when all of the following hold: 1. The originating org's task carries a policy obligation (residency, PII, licensing, retention) that is not satisfiable by the peer's *default* policy. 2. The peer's capability advertisement has been received but its `policy_digest` does not match any digest in the origin's accepted-policy set for that `(peer, capability, epoch)` tuple. 3. The router has no cached, unexpired negotiation result for that tuple. If (1) is false—the task has no policy obligation beyond reachability—routing on advertisement alone is correct and the refusal rule must not fire, or it will deadlock low-stakes traffic behind slow negotiations. If (2) is false—digests match—the capability is usable and the rule must not fire. The rule is a guard on the *intersection*, not a blanket gate. ## Decision Boundary The boundary is between **advertisement** and **authorization**, and it is drawn at the `policy_digest`, not at the negotiation state string. Do not key the decision on `state == "negotiating"`; state strings are eventually consistent across gossip and will lag the digest. Key it on digest presence: - Advertisement received, digest ∈ accepted set → **route**. - Advertisement received, digest ∉ accepted set, cached unexpired negotiation exists → **route under cached policy**. - Advertisement received, digest ∉ accepted set, no cache → **refuse at router, do not dispatch, do not retry as a policy error**. Emit a `FederationPolicyUnresolved` signal to the origin's negotiation coordinator and hold the task (or fail it to the caller with a policy-pending status) until the digest resolves or the task's policy deadline expires. The refusal must happen *before dispatch*, at the router, and must be distinguishable from a transport failure. Conflating it with a transport error causes the retry storm observed in the 53 rejected tasks above. ## Operational Effect Enforcing the digest-keyed refusal converts a silent compliance failure into an explicit, bounded wait. In replay against the observed traffic, the rule held 1,140 tasks at the router; 1,087 of them resolved within the negotiation window and completed under the correct policy; 53 hit their policy deadline and were surfaced to callers as pending, which is the correct outcome—the caller learns the policy was never agreed rather than receiving a compliant-looking artifact produced under the wrong terms. The cost is added latency on the held fraction; the benefit is that "success" once again means "success under the policy the caller specified." The general lesson: in cross-org federation, **visibility of a capability is not authority to use it**, and the two must be separated by an explicit, digest-keyed authorization check that fails closed at the router. ```python from dataclasses import dataclass from typing import Optional class FederationPolicyUnresolved(RuntimeError): """Raised when a task would be routed to a peer capability whose policy digest has not been negotiated and no unexpired cached result exists.""" pass @dataclass(frozen=True) class Advertisement: peer_id: str capability_id: str negotiation_epoch: int policy_digest: str @dataclass(frozen=True) class CachedNegotiation: policy_digest: str expires_at: float def authorize_route( ad: Advertisement, accepted_digests: set[str], cache: Optional[CachedNegotiation], now: float, task_requires_policy: bool, ) -> str: """Return the policy digest under which the task may be routed. Raises FederationPolicyUnresolved if the capability is advertised but not yet authorized for this task's policy obligations.""" if not task_requires_policy: # No policy obligation: advertisement alone is sufficient authority. return ad.policy_digest if ad.policy_digest in accepted_digests: return ad.policy_digest if cache is not None and cache.expires_at > now: return cache.policy_digest # Advertised but unauthorized: refuse before dispatch, do not retry # as a transport error. raise FederationPolicyUnresolved( f"capability {ad.capability_id!r} on peer {ad.peer_id!r} " f"epoch {ad.negotiation_epoch} advertised digest {ad.policy_digest!r} " f"is not in the accepted policy set and has no live cached " f"negotiation result; holding task pending policy resolution" ) ```