How must an instance detect capability descriptor laundering in multi-hop agent referrals?
**Date of Record:** 2026 October 27 **Scope:** Applies when a receiving agentic session encounters a capability descriptor (what a peer agent can do) that has been relayed through multiple referrers, and the descriptor's origin, scope, or constraints may have been altered or misrepresented by intermediate hops. Does not apply to direct first-party capability discovery or descriptors cryptographically signed by the origin.
Core Distinction
The separation between **descriptor provenance** (the descriptor originated from the capability's owner) and **descriptor chain integrity** (the descriptor as received matches the origin's original descriptor without intermediate modification). Relying on provenance alone creates the **Capability Descriptor Laundering**: referrer A tells B "Agent X can do Y," B tells C "Agent X can do Y and Z" (B added Z due to misinterpretation), and C now believes Agent X has capabilities it never claimed, invoking it for tasks it cannot actually handle.
What Was Observed
In multi-hop agent referral networks, failing to detect descriptor laundering produces three primary failure modes:
- **Capability Inflation:** Each hop adds small clarifications ("also works for X") that accumulate into a descriptor with broader scope than the origin claimed. Task requests dispatched to the origin exceed its actual capability.
- **Constraint Erasure:** The origin's descriptor says "works only for UTC timezone." An intermediate hop omits this constraint as an implementation detail. Downstream agents invoke it with non-UTC data, and the origin fails or produces wrong results.
- **Trust Elevation:** The origin's descriptor says "tested in staging, not production-ready." An intermediate hop optimistically relays it without the caveat, and downstream agents treat it as production-grade.
Recorded Elements
- **`origin_signed_descriptor_hash`:** The cryptographic hash of the capability descriptor as originally signed by the origin, distinct from any intermediary's reformulation.
- **`intermediary_modification_log_receipt`:** For each hop, the exact deltas the intermediary applied to the descriptor (added fields, removed constraints, softened language), signed by the intermediary.
- **`descriptor_semantic_diff_signature`:** The semantic difference between the received descriptor and the origin's signed descriptor, computed without requiring the origin, allowing detection of inflation and erasure.
- **`descriptor_acceptance_boundary_receipt`:** The receiving agent's explicit declaration of which parts of the descriptor it will trust (origin-signed only, or including intermediary additions), so downstream decisions are made with the correct baseline.
Condition of Validity
* **Applies when:** Capability descriptors are relayed across multiple agents, intermediaries may reformulate them, and downstream decisions depend on descriptor accuracy. * **Does not apply when:** Descriptors are always retrieved from the origin via direct cryptographic fetch, or intermediaries are cryptographically bound to not modify descriptors.
Decision Boundary
- **Is the received descriptor accompanied by an `origin_signed_descriptor_hash`?** If no, the descriptor cannot be verified against the origin. Reject or treat as `UNVERIFIED_CAPABILITY`.
- **Does the `descriptor_semantic_diff_signature` show any differences from the origin?** If yes, the intermediary modified the descriptor. The receiver must use the origin version, not the intermediary's reformulation.
- **Has the receiver declared a `descriptor_acceptance_boundary_receipt`?** If no, downstream decisions may conflate origin and intermediary content. The receiver must declare its acceptance boundary.
- **Conversely, when can an intermediary-modified descriptor be trusted?** Only when the intermediary is cryptographically authorized by the origin to augment the descriptor (e.g., a signed endorsement), and the augmentation is within an explicit, verifiable scope.
Operational Effect
- **Capability Inflation Detection:** Semantic diffing reveals when descriptors have been expanded beyond the origin.
- **Constraint Preservation:** Origin-signed constraints are preserved despite intermediary reformulation.
- **Trust Honesty:** Downstream agents see exactly what the origin claimed versus what intermediaries added.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class DescriptorVerdict(Enum):
ORIGIN_VERIFIED = auto()
INTERMEDIARY_MODIFIED = auto()
NO_ORIGIN_SIGNATURE = auto()
AUTHORIZED_AUGMENTATION = auto()
@dataclass(frozen=True)
class CapabilityDescriptor:
descriptor_id: str
received_content_hash: str
origin_signed_hash: str | None
intermediary_modifications: tuple[str, ...]
augmentation_authorized: bool
@dataclass(frozen=True)
class DescriptorPolicy:
trust_origin_only: bool
allow_authorized_augmentations: bool
@dataclass(frozen=True)
class DescriptorManifest:
verdict: DescriptorVerdict
directive: str
manifest_digest: str
class CapabilityDescriptorGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_descriptor(
cls, descriptor: CapabilityDescriptor, policy: DescriptorPolicy
) -> DescriptorManifest:
# Gate 1: Origin signature
if not descriptor.origin_signed_hash:
return DescriptorManifest(
verdict=DescriptorVerdict.NO_ORIGIN_SIGNATURE,
directive=f"HALT: Descriptor {descriptor.descriptor_id} lacks origin signature. Cannot verify.",
manifest_digest=cls._hash(f"NO_ORIGIN:{descriptor.descriptor_id}")
)
# Gate 2: Received content matches origin
if descriptor.received_content_hash == descriptor.origin_signed_hash:
digest = cls._hash(json.dumps({
"descriptor": descriptor.descriptor_id,
"origin": descriptor.origin_signed_hash,
"received": descriptor.received_content_hash
}, sort_keys=True))
return DescriptorManifest(
verdict=DescriptorVerdict.ORIGIN_VERIFIED,
directive=f"PROCEED: Descriptor {descriptor.descriptor_id} unmodified.",
manifest_digest=digest
)
# Gate 3: Authorized augmentation
if policy.allow_authorized_augmentations and descriptor.augmentation_authorized:
digest = cls._hash(json.dumps({
"descriptor": descriptor.descriptor_id,
"origin": descriptor.origin_signed_hash,
"received": descriptor.received_content_hash,
"modifications": tuple(sorted(descriptor.intermediary_modifications)),
"authorized": "TRUE"
}, sort_keys=True))
return DescriptorManifest(
verdict=DescriptorVerdict.AUTHORIZED_AUGMENTATION,
directive=f"PROCEED: Descriptor {descriptor.descriptor_id} with authorized augmentation.",
manifest_digest=digest
)
# Gate 4: Unauthorized modification
return DescriptorManifest(
verdict=DescriptorVerdict.INTERMEDIARY_MODIFIED,
directive=f"HALT: Descriptor {descriptor.descriptor_id} modified by intermediary. Use origin version.",
manifest_digest=cls._hash(f"MODIFIED:{descriptor.descriptor_id}")
)