11. 发现协议与查询语义
本章说明发现服务节点如何从已验证并完成授权范围过滤的本地索引中处理 DID 精确查询、结构化查询、标签查询、文本查询和语义查询。内容覆盖查询输入、版本选择、来源和新鲜度、结果去重、分页、解释、错误和降级边界,明确发现响应是节点索引产生的候选结果,调用方仍需依据 DID、凭证、根平台可信发布证明、治理状态和端点信息完成调用前验证。
11.1 发现目标与查询类型
发现服务节点面向已经进入本地索引的资源提供五种查询路径:完整资源 DID 的精确查找,按资源类型、版本、协议和能力标签执行的结构化查询,按能力标签执行的标签查询,基于资源名称、描述、标签、用例和协议材料的文本或自然语言查询,以及自然语言条件与结构化条件结合的组合查询。查询结果是发现服务节点的派生响应,不是根平台发布记录本身;响应应保留资源 DID、资源类型、版本、生命周期、来源和必要的验证引用。
当前参考实现通过 POST /discovery/resources/query 接收统一查询对象。查询文本若是完整且无空白的 did:oan: 标识符,会进入精确 DID 分支;其它文本与显式字段进入结构化、词法或语义路径。查询节点只从本地已索引材料构造候选,不能把查询请求直接转发到注册服务节点或根平台来临时补造结果。
查询输入在进入检索前应先完成边界校验,再转换为内部查询对象。resourceType、capabilityTags、protocol 和 version 用于形成显式条件,versionMode 用于说明版本选择方式,limit 用于限制本次响应规模,query 承载 DID 或文本/自然语言查询。对同一个请求同时提供文本和结构化字段时,文本负责召回与排序,结构化字段负责收缩候选范围;这两类条件不能被互相覆盖。
{
"query": "我需要一个可以检索代码仓库并总结项目结构的工具",
"resourceType": "tool_api",
"capabilityTags": ["code-repository"],
"protocol": "MCP",
"versionMode": "latest",
"limit": 10
}
上例中的查询文本、标签、协议和数量用于说明字段组合,具体资源类型和标签必须以目标发现服务节点接受的协议值为准。响应候选中的 score 是查询相关性结果,不是资源信任等级。
11.1.1 DID 精确发现
完整资源 DID 应被解释为精确查找条件,不得退化为名称、前缀或语义相似搜索。节点应读取该 DID 对应的本地索引对象,并继续检查显式条件、生命周期和本节点授权域。
11.1.2 结构化条件发现
资源类型、版本、协议和能力标签等字段应转换为可复核的过滤条件。多个显式条件默认采用交集关系;非法枚举、无法解释的版本模式或不支持的协议值应返回明确请求错误。
11.1.3 能力标签发现
能力标签查询使用资源元数据中的 capabilityTags。标签树中的父子关系、别名和扩展标签可以参与查询投影,但必须保留原始标签及其来源,标签命中不代表控制权或调用授权。
11.1.4 文本与语义发现
文本和自然语言查询可以使用词法检索、向量检索或二者结合的混合检索。语义索引不可用时可以使用词法和结构化路径降级,但应在查询解释或诊断信息中说明实际使用的后端。
11.1.5 组合条件发现
组合查询应先执行授权域、生命周期和显式结构化条件过滤,再对剩余候选进行词法或语义排序。相关性不能解除硬过滤条件,也不能让未发布或未授权资源进入可信结果。
11.2 DID 精确查询
精确查询首先验证 DID 的方法语法和资源类型语义,再读取本地索引中的资源包。命中结果必须使用同一个资源版本的 DID文档、元数据、端点、哈希和根平台证明引用;未命中不能简单解释为资源不存在于整个网络,因为资源可能尚未传播到本节点或被授权域过滤。节点应区分以下结果:
| 结果 | 解释 | 调用方处理 |
|---|---|---|
| 返回候选 | 本节点存在满足条件且可见的索引对象 | 继续验证 DID、证明和端点 |
| 空候选 | 不存在、尚未索引或不在本节点授权域内 | 不推断全网不存在 |
| 已暂停/撤销 | 索引对象存在,但当前状态限制使用 | 不按当前有效资源调用 |
| 服务错误 | 数据库、索引或治理读模型暂不可用 | 按临时故障重试或降级 |
当前精确查询实现以 query 字段识别 DID,并将其它显式条件继续交给资源类型、版本、能力标签和协议匹配逻辑;因此,带有 DID 的查询仍可能因版本或授权域条件不满足而返回空候选。精确命中也只说明本发现服务节点有一条可见索引记录,调用方仍应取得完整 DID文档和证明材料进行调用前验证。
精确 DID 查询的结果边界可以用下表核对。这里的“未找到”是本节点当前索引和授权域下的查询结果,不是对整个智能体互联网状态的断言。
| 查询阶段 | 核对对象 | 结果含义 |
|---|---|---|
| 输入识别 | query 是否为完整的 did:oan: 字符串 |
决定进入精确路径还是普通检索路径 |
| 索引读取 | 本节点是否有对应资源包索引记录 | 只反映本节点是否已保存该记录 |
| 条件匹配 | 版本、资源类型、协议、能力标签等显式条件 | 任一硬条件不满足即可得到空候选 |
| 可见性判断 | 本节点授权域和资源生命周期 | 不可见、暂停或撤销的资源不能按正常候选返回 |
| 调用前判断 | DID文档、注册凭证、根平台可信发布证明和端点 | 由调用方完成,不由 score 或索引命中替代 |
11.3 结构化资源查询
结构化查询将请求中的字段映射为数据库或内存过滤条件。当前参考实现对资源生命周期、资源类型、版本、能力标签和协议执行过滤,并对未指定资源类型的普通查询使用面向用户消费资源的默认范围。显式能力标签要求资源全部包含相应标签;协议条件要求资源服务端点或协议绑定能够解释该协议。空查询在带有结构化条件时可以执行,完全没有条件的查询应受到返回条数和资源范围限制。
过滤完成后,结果仍需经过本节点授权域检查和最新有效版本选择。展示名称、描述和检索分数是索引字段,不能作为身份、发布或治理证据。
显式过滤应在候选进入相关性排序前执行。当前实现对 resourceType、version、capabilityTags 和 protocol 执行资源级匹配;能力标签按请求集合的交集判断,协议可以由协议绑定或服务端点声明命中。字段缺失不会自动被解释为通配符,无法解析的请求值不应悄然转换为另一个条件。
结构化过滤的可复核性要求是:请求字段、资源字段和判定结果能够逐项对应。比如请求同时指定 resourceType = "mcp_server" 和 capabilityTags = ["file.search", "desktop.automation"] 时,候选必须先属于指定资源类型,并同时满足两个标签,再参与文本相关性排序;仅有“文件搜索”语义相近但资源类型不符的候选不能通过排序进入结果。字段没有出现在资源包中时,应按该条件不满足处理,不能把缺失值当作任意匹配。
对于未知枚举、空白字段、重复标签和互相冲突的版本条件,节点应在请求解析阶段给出确定处理。重复标签可以先规范化为一个条件;未知资源类型或无法解释的版本模式应作为请求错误;版本和生命周期冲突时,应由版本选择与状态规则收紧结果,而不能由检索分数放宽。
11.4 能力标签查询
能力标签是资源提供方对资源能力分类的声明,根平台能力标签树为标签标识、层级、别名和版本提供治理语境。发现节点可以将查询中的别名投影为规范标签,也可以在本地建立检索别名,但响应应保留资源原始标签和实际命中的标签。父标签是否覆盖子标签、扩展标签是否进入可信索引,应由标签树版本和节点配置明确,不能由模型相关性隐式决定。
标签查询应区分三种信息:资源原始的 capabilityTags,查询文本或显式参数经过别名展开后的检索词,以及最终用于解释命中的标签。别名展开可以提高召回,但不能修改资源原始声明;如果一个扩展标签没有得到当前节点的标签树或配置支持,应作为普通未命中处理,而不是推断为父标签或同义标签。
11.5 文本与语义查询
语义查询的可检索内容包括资源名称、描述、能力标签、用例、协议绑定和资源类型等公开信息。参考实现可以将资源材料组织为标签视图、上下文视图和意图视图,并结合向量分数、词法分数和结构化分数形成候选排序。score 只表示当前查询和索引快照中的相关性,不表示信任等级、服务质量或安全等级。
语义索引、嵌入服务或 pgvector 不可用时,可以降级到词法和结构化查询;降级不得放宽授权域、生命周期或显式条件。空文本不应强行调用语义后端,过长、无法编码或不支持语言的输入应返回明确错误或可解释的降级结果。
当前语义实现会把资源类型、协议、能力标签和查询文本投影为检索词,并从资源名称、描述、标签、上下文、示例和用例等公开材料构造搜索文档。语义后端可用时,结果可结合 BM25 类词法分数、标签分数、上下文分数、意图分数和结构化分数;这组内部得分用于排序和解释,不应被外部调用方当作经过治理的质量评价。
语义检索的索引文本必须来源于资源已公开的描述材料。索引构建时应保存资源 DID、资源包版本和语义源内容的关联,以便资源更新后重建对应索引,避免旧描述继续产生高相关性结果。多语言查询可以通过规范化、别名或嵌入模型提高召回,但不能把模型推断出的能力写回资源元数据,也不能以模型相似度替代资源控制权、注册凭证或根平台可信发布证明。
发现节点应能够从运行日志或诊断接口区分语义后端、词法路径和结构化路径。对于同一组硬条件,语义服务失败时允许只改变候选的召回和排序质量;如果索引数据库、授权域读模型或资源包读取失败,则必须把故障作为数据不可用或服务错误处理,不能返回看似正常但实际不完整的空结果。
11.6 语义与结构化条件组合查询
组合查询可抽象为以下处理顺序:
visible = authorizedDomain AND active AND explicitFilters
ranked = rank(queryText, visible)
result = stableSort(ranked)[0:limit]
其中 explicitFilters 包括资源类型、版本、协议和显式能力标签;rank 可以使用词法、向量或混合检索;stableSort 需要保留稳定次级键。若没有符合硬条件的资源,应返回空候选,而不是返回“相似但不满足条件”的资源。
组合查询的一个实际边界是:语义检索结果仍需经过本节点的资源包有效性、生命周期和授权域判断;语义索引中存在一条记录,不等于该记录在当前查询时刻仍可见。对自然语言中隐含的“最新”“可信”“可调用”等要求,节点可以将能够落到协议字段的部分转换为结构化条件,无法落到字段的部分只能作为排序或解释信息,不能自动生成授权结论。
组合查询的处理可以用一个最小可复现例子表示:
{
"query": "I need a tool that can search code repositories and summarize the project structure.",
"resourceType": "tool_api",
"protocol": "MCP",
"capabilityTags": ["code-repository"],
"versionMode": "latest",
"limit": 10
}
这个请求的合格结果必须同时满足资源类型、协议和能力标签条件;自然语言只用于补充名称、描述、用例等字段的相关性判断。若查询文本表达了“可信”或“可调用”,节点只能在存在对应结构化字段和可验证事实时执行相应判断,否则应把它作为检索意图保留,交由调用方在后续验证环节处理。
11.7 授权域过滤
发现节点从自身 DID文档或治理读模型取得节点授权域,再将其与资源元数据中的 authorizedDomains 比较。资源域必须被节点获准的域覆盖;域不匹配的资源不应进入查询结果。该过滤决定的是本节点向查询方提供的发现可见性,不改变资源 DID 控制关系,也不代表资源在其它发现节点不可见。治理状态或节点授权无法确认时,应在普通展示中标明不新鲜,在敏感查询和调用前验证场景采取收紧处理。
11.8 最新有效版本选择
默认查询按资源 DID 选择当前满足本节点授权域、生命周期为有效、已经完成必要校验且同步位置可确认的最新版本。同一 DID 的版本选择应结合资源包版本、根平台发布游标、包哈希、前序版本关系和治理状态,不能只用更新时间或查询到达顺序判断。发现节点本地落后时可以返回已验证旧版本用于有限展示,但必须携带新鲜度和同步位置,不能宣称其为网络最新版本。
版本选择至少要验证三个条件:候选属于同一资源 DID,候选版本满足请求的 versionMode 和 version 条件,候选对应的生命周期与治理状态仍允许发现。对于 latest 查询,选择的是当前可验证的最新有效版本,而不是数据库中最后写入的记录;对于指定版本查询,若版本记录不存在、哈希不一致或状态不可确认,应返回空结果或明确的数据不可用错误,不得静默替换为另一个版本。
可复现的检查可以使用两条同 DID 记录:记录 A 的发布序列较早但状态有效,记录 B 的更新时间较晚但已暂停。合格实现应选择记录 A 或返回受限结果,不能因为 B 的时间更新而把暂停版本当作最新有效版本。检查还应验证重复查询在同一索引快照上返回相同的资源 DID、版本和状态,并保留发布序列、包哈希与状态来源作为判断证据。
11.9 搜索排序与确定性结果顺序
11.9.1 匹配条件
匹配条件是候选进入排序的第一层依据。资源类型、版本、协议和能力标签等显式条件属于硬过滤;名称、描述、用例和协议材料中的文本命中属于相关性依据。候选必须先满足显式条件,再参与相关性排序;一个资源只因文本相近而不满足资源类型或版本条件时,不得进入结果。
11.9.2 信任和治理状态
已完成根平台可信发布、治理状态有效且节点授权可确认的候选,才能进入可信可发现结果。信任和治理状态不是把检索分数加高的普通特征,而是决定候选是否具备返回资格的约束。状态未知、证明缺失、资源暂停或撤销的候选应被过滤,或以明确受限状态返回,不能通过高相关性掩盖。
11.9.3 版本和新鲜度
同一资源 DID 默认只保留当前有效版本;在多个候选相关性相近时,应优先选择发布序列和治理状态均可确认的较新有效版本。新鲜度用于说明索引距离发布事实和治理事实的程度,不应直接等同于检索相关性。旧快照可以用于有限展示,但必须带有 stale 或等价状态。
11.9.4 排序稳定性
在同一索引快照、同一授权域和同一查询条件下,排序应得到可重复结果。排序首先依据实际启用的相关性组合,其后使用确定性的资源 DID、版本或发布序列作为稳定次级键。节点应避免使用数据库自然顺序、并发完成顺序或随机扰动作为隐含排序依据;否则分页和客户端去重将无法可靠工作。
11.9.5 重复结果处理
排序前或排序后都必须执行资源身份去重,不能让同一 DID 的重复同步记录占用多个结果位置。去重保留当前有效版本、较新发布序列和可验证证据更完整的记录,并保留来源节点和重复诊断信息。重复记录之间出现哈希或治理冲突时,应进入异常处理而不是任意选择一条作为可信结果。
11.10 搜索解释与证据展示
11.10.1 匹配原因
匹配原因应尽量指向可观察字段,例如能力标签交集、资源类型命中、协议命中、文本字段命中或自然语言意图匹配。解释可以是摘要,不要求暴露内部模型或索引实现细节,但不得编造资源未声明的能力。若查询经过词法、向量或混合路径处理,应能说明实际路径或至少说明解释的确定性范围。
11.10.2 资源来源
结果应标明发现服务节点的身份、索引更新时间、资源来源节点或来源引用,以及可用的发布序列和资源包哈希。来源字段用于追踪事实从何处同步,不表示来源节点对资源业务质量作担保。通过内容分发平台取得的资源,还应保留根平台发布材料的引用关系,不能只记录缓存地址。
11.10.3 DID、VC 与根平台证明
资源 DID 用于识别资源身份,DID文档用于提供公钥、服务端点和资源元数据,注册凭证用于表达注册服务节点处理过的登记事实,根平台可信发布证明用于表达根平台对特定资源版本及其材料的验证和发布事实。发现响应可以返回这些证据的摘要或引用,但调用方在连接前应取得并验证完整材料,不能把任何一个引用字段当作已经完成验证。
发现响应的字段应按“索引展示”和“可验证证据”分层理解。resourceDid、resourceType、score、版本、标签和端点是候选展示信息;DID文档、注册凭证、根平台可信发布证明及其签名材料才是调用方进行身份、控制权和发布事实核验的依据。发现节点返回一个资源候选,不等于节点替调用方完成了端点连通性测试、业务适配性评估或授权授予。
11.10.4 治理状态与版本信息
解释区域应同时展示资源生命周期、资源版本、发布序列、治理状态和索引新鲜度,使调用方能够区分“相关性较高”和“当前可验证”。治理状态来自治理事件投影或其它明确事实源,版本信息来自资源发布链;二者出现矛盾时,应标记冲突并按限制性规则处理,不得以较新的展示时间覆盖撤销或暂停事实。
搜索解释应把可验证事实和检索推断分开保存。matchReason、标签交集、资源类型命中和协议命中属于查询解释;DID文档、公钥、注册凭证、根平台可信发布证明、发布序列和治理状态属于验证材料。前者回答“为什么出现在结果中”,后者回答“调用方可以依据哪些事实继续判断”,两者不能合并为一个推荐分数。
11.11 发现响应模式
发现响应至少应能让调用方识别四件事:查询由哪个发现服务节点处理,候选资源对应哪个资源 DID,候选来自哪个索引状态,以及为什么被返回。参考实现的响应可包含 discoveryDid、candidates、createdAt 和 proof 等顶层字段;候选项应包含资源 DID、资源类型、检索分数、版本、生命周期、能力标签、授权域、服务端点、协议绑定、资源包信息和根平台证明引用。具体部署可以增加字段,但不应把展示字段误认为证明字段。
{
"discoveryDid": "did:oan:...",
"createdAt": "2026-09-07T10:00:00Z",
"candidates": [
{
"resourceDid": "did:oan:...",
"resourceType": "skill",
"score": 0.87,
"version": "1.0.0",
"lifecycle": "active",
"capabilityTags": ["code-repository", "project-structure"],
"serviceEndpoints": ["https://example.invalid/endpoint"],
"protocolBindings": ["MCP"],
"rootProofRef": "...",
"freshness": {
"publicationSequence": 42,
"indexUpdatedAt": "2026-09-07T09:59:30Z"
}
}
]
}
proof 或 rootProofRef 只表示响应或候选所引用的证明材料,调用方仍需按第 7、9 章规则取得并验证相应内容。字段缺失时,节点应明确返回“不可用”或省略该字段,不能填入未经验证的默认值;未知扩展字段应允许兼容客户端忽略,但核心身份、状态和来源字段不得被改名后改变含义。
与当前协议结构对应的响应最小骨架是 discoveryDid、candidates、createdAt 和可选的 proof。候选项中的 resourceDid、resourceType、score、version、lifecycleState、capabilityTags、authorizedDomains、services、protocolBindings、packageInfo 和 rootProof 分别承担身份、检索、状态、能力、范围、服务和证明引用的展示职责。当前接口未必返回独立的 matchReason 或完整新鲜度对象,客户端不能把缺省字段补成已经验证的事实。
当前发现查询入口为 POST /discovery/resources/query,请求体对应 ResourceDiscoveryQuery。该类型可包含 query、resourceType、capabilityTags、protocol、version、versionMode 和 limit;其中 limit 默认值为 10,versionMode 默认值为 latest。响应对应 ResourceDiscoveryResponse,候选项使用 ResourceDiscoveryCandidate,返回的 score 是匹配相关性分数,不是授权等级或可信等级。
POST /discovery/query/explain 也接收 ResourceDiscoveryQuery,但返回动态解释 JSON,包括匹配资源 DID、资源类型、匹配标记、分数、标签重合、资源类型/协议是否匹配以及语义搜索状态等。解释响应用于诊断检索过程,不是普通发现结果,也不能作为资源已经通过控制权或发布证明验证的替代品。
当前公共协议中的字段名称应作为客户端兼容的基准。资源候选使用 lifecycleState、services、packageInfo 和 rootProof 等字段时,客户端应按字段是否存在处理可选信息;示例中的 lifecycle、serviceEndpoints、rootProofRef 或 freshness 只能作为说明性扩展,不能据此声称当前所有部署都会返回这些名称。新增响应字段时,应保持旧客户端能够忽略未知字段,并为字段的事实来源和验证方式给出说明。
11.12 发现结果新鲜度与状态
发现结果的新鲜度由索引更新时刻、已处理的发布游标、治理事件序列和本地错误状态共同说明,而不是由 HTTP 响应时间单独决定。响应应尽可能提供 createdAt、索引更新时间、发布序列或同步游标、治理状态读取位置和来源节点 DID。调用方据此判断结果是当前快照、可接受的旧快照还是部分可用结果。
| 状态 | 含义 | 允许的使用方式 |
|---|---|---|
| current | 已完成必要发布和治理状态同步,且未发现更新缺口 | 可进入调用前验证流程 |
| stale | 本地仍有可验证快照,但发布或治理同步落后于允许范围 | 仅作带新鲜度标记的只读参考;调用前必须重新确认状态 |
| partial | 部分资源或部分索引分片可用,完整性范围已缩小 | 只能按响应明确的范围使用,不得宣称全量结果 |
| unknown | 无法确认同步位置、治理状态或证明新鲜度 | 不得作为敏感动作的可信依据 |
版本状态和治理状态发生冲突时,撤销、暂停或节点授权失效等限制性状态优先于相关性和时间排序。发现服务节点可以保留历史快照以改善网络异常时的访问体验,但必须显式标记快照状态,不能把缓存命中描述为网络最新状态。
发现结果的状态判断应以本地索引材料及其同步记录为依据。createdAt 只表示本次响应生成时间,不等于资源发布或索引应用时间;发布游标表示传播位置,索引更新时间表示本节点处理时间,治理事件序列表示治理读模型位置。调用方需要比较这些来源和位置,才能判断结果是否可能落后。
错误响应应让调用方区分请求错误、资源未命中、索引暂不可用和后端暂时失败。DID 格式错误、未知资源类型、无法解析的版本模式、超过查询限制等属于请求侧错误;合法查询但没有可见候选属于空结果;数据库、语义索引、治理读模型或上游同步失败属于服务或数据侧错误。错误信息应包含机器可判断的错误类别、请求标识和必要的重试提示,不应泄露受限资源的详细内容。
{
"error": {
"code": "INDEX_STALE",
"message": "The discovery index is temporarily behind the publication cursor.",
"requestId": "...",
"retryable": true
},
"freshness": {
"status": "stale",
"lastKnownPublicationSequence": 41
}
}
语义后端不可用时,节点可以回退到词法和结构化路径;回退只改变排序能力,不得放宽资源类型、生命周期、授权域、版本和显式标签条件。若基础索引本身不可用,节点不得用空数组伪装成“没有资源”,应返回可识别的服务错误或带有明确范围的部分结果。重试应由客户端依据 retryable、退避提示和自身请求预算执行,节点不得因自动重试造成请求放大。
错误处理应保持“请求错误”和“数据暂不可用”的边界:格式错误、未知枚举和超限参数不应重试原请求;语义后端暂时不可用可以在同一硬条件下走词法降级;基础索引或治理状态不可读时,返回部分结果必须明确范围和状态。发现节点可以记录查询统计和后端名称用于运维,但不应在公开错误中泄露授权域外资源的存在。
发现接口的错误处理应保持响应结构稳定,并使客户端能够决定是否修正请求、等待后重试或停止使用结果。可按以下边界处理:
| 错误类别 | 典型原因 | 客户端动作 |
|---|---|---|
| 请求无效 | DID 格式、资源类型、版本模式或 limit 不合法 |
修正请求后重新发起,不重复原请求 |
| 无可见结果 | 条件合法,但本节点没有满足条件且可见的候选 | 可调整查询条件,但不得据此断言全网不存在 |
| 语义降级 | 语义索引或嵌入服务暂不可用,基础索引仍可读 | 接受词法/结构化结果,并降低对相关性的预期 |
| 索引不可用 | 资源索引、数据库或必要治理读模型无法读取 | 按服务错误处理,等待恢复或切换已知节点 |
| 同步滞后 | 本地发布游标落后或快照不完整 | 只按响应标记的范围使用,必要时稍后重试 |
语义降级与基础索引故障必须在实现和运维观测中区分:前者通常仍能返回满足硬条件的候选,只是相关性排序能力下降;后者无法证明候选集合完整或可见性判断有效,不应伪装成普通空结果。错误日志可以记录后端、耗时、候选数量和失败原因,但公开响应只返回客户端完成处理所需的最小信息。
11.13 发现错误与降级响应
资源能够通过某个 HTTP 端点访问,只说明该端点对当前请求可达;进入发现索引,说明发现服务节点已经保存了相应索引记录;具有根平台可信发布证明,说明根平台对特定版本和材料形成了可验证发布事实;通过调用前验证,则还要求调用方重新检查 DID 控制关系、证明、治理状态、端点和自身业务策略。四者是逐级增加的事实,任何一级都不能自动替代其它级别。
| 事实 | 主要来源 | 不能推出的结论 |
|---|---|---|
| 端点可访问 | 资源服务端点 | 资源已登记或值得信任 |
| 已进入发现索引 | 发现服务节点索引 | 资源是全网最新或允许调用 |
| 有根平台可信发布证明 | 根平台发布材料 | 业务端点一定可用或适合特定场景 |
| 通过调用前验证 | 调用方及其验证组件 | 调用方已经获得全部业务权限 |
公开发现响应可以展示必要的 DID、资源摘要、端点和证明引用;对受限资源应仅返回授权范围内的最小摘要。调用方在建立连接前,应根据资源风险重新取得或核验完整 DID文档、注册凭证、根平台可信发布证明、最新治理状态和端点声明。
公开可见性由发现服务节点当前授权域和索引状态共同决定。资源没有出现在公开结果中,可能是尚未同步、已被过滤、已暂停或当前索引不可用,不能仅凭空结果判断资源不存在。调用方如果需要确定性结论,应使用精确 DID 查询、读取状态信息并执行完整的调用前验证,而不是枚举标签或分页结果推断隐藏清单。
可见性判断至少涉及三个独立问题:资源是否已经登记,资源是否已经传播到本节点,当前查询方是否能够看到该资源。发现服务节点只能依据本地可验证的索引材料和授权域作答,因此“返回候选”表示该资源在当前节点的可见范围内具备发现记录,“未返回”只表示当前查询没有获得可见候选。涉及敏感资源时,成功、空结果和权限过滤的响应不应通过错误码、字段数量或响应时延泄露额外信息。
可信可发现性还要求候选具备与当前版本对应的 DID文档、注册凭证或根平台可信发布证明引用,并且没有已知的暂停、撤销或授权失效状态。发现节点提供的是索引和证据入口;调用方是否接受该资源,还要结合自身风险策略验证控制权、证明有效性、端点安全性和业务授权。
11.14 公开可见性与可信可发现性
去重的首要键是完整资源 DID。来自多个注册服务节点、内容分发平台或同步批次的记录,只要指向同一资源 DID,默认视为同一资源身份;如果记录还包含版本,则以资源 DID 加版本标识区分版本。包哈希、根平台发布序列和来源节点用于确认内容是否一致及保留证据,不能把名称相同或描述相似的资源错误合并。
去重决策应保留“合并依据”和“被舍弃记录的来源”,以便解释为什么一个候选只出现一次。默认查询可以采用以下优先级选择代表记录:先排除生命周期受限、授权域不匹配或证明不可核验的记录;再比较版本模式要求和发布序列;最后以包哈希、来源节点和确定性 DID 顺序消除并列。这个优先级只用于构造发现结果,不改变注册服务节点的原始受理记录,也不删除历史审计材料。
| 记录关系 | 发现结果处理 | 必须保留的依据 |
|---|---|---|
| 同 DID、同版本、同包哈希 | 合并为一个候选 | 来源节点和同步批次 |
| 同 DID、不同版本 | 按 versionMode 选择或分别返回 |
版本、发布序列和前序关系 |
| 同 DID、同版本、不同包哈希 | 不自动合并为可信记录 | 冲突哈希、来源和诊断状态 |
| 不同 DID、内容相同 | 作为不同资源返回 | 各自 DID、控制关系和证明 |
去重必须发生在分页之前,否则同一资源的重复记录会占用多个结果位置,并在客户端跨页合并时造成遗漏。历史版本查询是例外:它可以返回同一 DID 的多个版本,但每个版本都必须带有明确版本和状态,不能让客户端误把历史候选当成当前有效版本。
11.15.1 DID 级去重
同一查询响应中,同一资源 DID 默认只返回一个代表记录。代表记录应来自当前有效且发布序列较新的版本,并保留可追溯的来源节点、根平台证明引用和同步位置。若不同记录的治理状态相互冲突,应保留冲突诊断信息并采用限制性状态,不得通过任意排序隐藏冲突。
11.15.2 版本级去重
同一 DID 的不同有效版本只有在查询明确要求历史版本或指定版本约束时才同时返回。默认查询返回当前有效版本;历史查询应将版本标识、前序版本和发布序列作为结果字段,避免客户端把历史记录误当成当前版本。相同版本标识但包哈希不同属于一致性异常,应拒绝合并并进入诊断或隔离处理。
11.15.3 注册节点重复记录
同一资源重复向一个或多个注册服务节点提交,不应产生多个资源身份。发现节点应依据根平台发布事实、资源 DID、版本和包哈希去重;注册服务节点的本地受理记录可以作为来源审计信息保留,但不能单独生成公开候选。重复提交是否重新签发注册凭证属于注册协议行为,不改变发现侧的资源身份规则。
11.15.4 资源内容相同但 DID 不同的处理
内容、名称或端点相同而 DID 不同的记录仍是不同资源身份,不能仅因内容哈希相同就合并。节点可以在解释字段中提示内容相似或共享包哈希,但必须分别展示控制关系、注册状态、版本和根平台证明。是否允许同一内容被多个 DID 代表,应由资源控制方和治理规则决定。
11.15 结果去重与资源身份匹配
节点应限制查询文本长度、结构化条件数量、单次返回条数和语义检索资源消耗。limit 必须经过服务端上限校验,客户端不得通过重复请求或异常参数绕过该限制。无效游标、过期游标、与原查询不匹配的游标应返回明确错误,而不能静默从第一页重新返回,避免客户端误以为分页结果完整。
在同一索引快照中,分页必须沿用同一套过滤、去重和排序规则。排序至少应由检索分数、确定性的资源 DID 或其它稳定键组成;不能使用每次请求随机数、未定义的数据库自然顺序或不稳定的并发完成顺序。索引快照在分页期间发生变化时,响应应通过快照标识、游标失效或新鲜度字段告知客户端,避免跨快照重复或遗漏被误认为协议错误。
| 情形 | 推荐处理 |
|---|---|
结果少于 limit |
返回全部可见且满足条件的候选,并标明没有更多结果 |
| 结果达到上限 | 返回稳定的分页游标和当前快照信息 |
| 查询超过长度或资源预算 | 返回不可重试的请求错误 |
| 游标无法解析或不匹配查询 | 返回游标错误,要求客户端重新发起查询 |
| 索引在分页期间更新 | 继续使用原快照或明确使游标失效 |
分页只解决传输和展示规模问题,不改变授权域和可信可发现性的判定。客户端合并多页时应以资源 DID 和版本作为去重键,并保留每页来源和快照信息。
11.16 查询限制、分页与结果稳定性
授权域过滤应在结果返回前完成,而不是先返回候选再依赖客户端自行隐藏。对于不在请求方或节点授权范围内的资源,节点不应通过名称、标签、端点、证明引用或错误差异泄露其存在;在需要区分权限不足和资源不存在的管理接口中,才可以向已授权管理方返回更详细的原因。公开查询默认只返回已发布、可发现且属于本节点服务域的最小必要字段。
索引材料应按字段敏感性划分:资源 DID、资源类型和公开能力摘要可以进入公开结果;私有端点、内部标签、控制公钥以外的敏感配置、提交人的私密身份信息和未公开证明材料不得因语义索引被暴露。向量索引、词法索引和查询日志都应遵守同一授权域边界,不能因为检索后端需要文本而复制不应公开的内容。
查询日志应最小化记录原始自然语言输入、调用方标识和过滤条件,并按照部署方的隐私策略设置保留期限、访问控制和脱敏规则。请求方不能通过枚举 DID、标签组合、分页游标或错误响应推断受限资源的完整清单。授权域变更、资源撤销和节点停权传播期间,发现节点应优先收紧可见性,并保留状态来源和处理时间供审计。
flowchart TD
A[接收发现查询] --> B{输入是否合法}
B -- 否 --> E[返回请求错误]
B -- 是 --> C[解析 DID、结构化条件、标签和文本]
C --> D[加载本地索引快照]
D --> F{索引和治理状态可用}
F -- 否 --> G[返回可解释降级或服务错误]
F -- 是 --> H[授权域与生命周期过滤]
H --> I[版本选择与 DID 级去重]
I --> J[词法、向量或混合排序]
J --> K[稳定排序与分页]
K --> L[附加来源、证明和新鲜度]
L --> M[返回发现响应]
该流程表达的是处理责任顺序:输入校验和硬过滤先于相关性排序,版本选择和去重先于分页,来源、证明和新鲜度随响应一起返回。语义后端的使用是排序能力,不得改变前置身份、授权和生命周期判断。任何降级路径都必须说明它实际完成了哪些验证以及没有完成哪些验证。
| 检查项 | 合格判据 |
|---|---|
| DID 查询 | 完整资源 DID 按精确路径处理,不退化为模糊搜索 |
| 结构化过滤 | 资源类型、版本、协议、能力标签和生命周期条件按明确交集执行 |
| 授权域 | 未获授权的资源不出现在公开结果,域状态不明时按收紧规则处理 |
| 相关性解释 | 检索分数只表达相关性,不被称为信任等级或调用许可 |
| 版本选择 | 默认返回当前有效版本,历史版本查询不混淆当前状态 |
| 去重 | 同一 DID 不因多节点同步或重复注册产生重复候选 |
| 响应来源 | 结果能指向发现服务节点、索引状态、发布序列和证明引用 |
| 新鲜度 | 旧快照、部分结果和治理状态不明均有明确标记 |
| 错误降级 | 语义后端故障不放宽硬条件,基础索引故障不伪装为空结果 |
| 分页稳定性 | 同一快照中排序稳定,游标与查询和快照绑定 |
| 隐私边界 | 查询、索引和错误响应不泄露授权域外资源的敏感信息 |
| 调用前验证 | 发现结果只作为候选输入,调用方仍重新验证身份、证明和业务权限 |
11.17 发现隐私与授权域可见性
授权域是发现可见性的边界,不是资源控制权或调用权限的替代物。发现服务节点应先依据本节点获授权的服务域和资源包中的 authorizedDomains 判断候选是否可见,再对可见候选进行结构化和语义处理。资源域与节点服务域不相交时,候选应在公开响应前被过滤;查询方不能通过名称、标签、端点、响应数量或错误差异推断被过滤资源的详细信息。
索引和展示应遵循最小披露原则。公开候选可以提供资源 DID、资源类型、公开能力标签、必要的服务端点、版本和证明引用;控制私钥、提交人的本地身份备份、内部治理材料、未授权端点和不属于公开资源包的配置不能进入索引或查询响应。语义索引使用的文本、标签别名和向量表示也应继承原始字段的授权边界,不能因为进入检索后端就扩大可见范围。
当授权域、生命周期或治理状态正在同步,且本地无法确认最新状态时,应优先收紧公开可见性。对管理和审计用途,可以在受控接口中记录过滤原因、来源节点、治理事件序列和处理时间;对普通发现请求,只返回不泄露受限资源存在性的统一结果。查询日志也应按最小必要原则保存,并限制原始自然语言、调用方信息和查询条件的访问范围与保留期限。
| 信息类别 | 可进入公开发现结果 | 处理要求 |
|---|---|---|
| 资源身份 | 资源 DID、资源类型 | 与当前可见版本绑定 |
| 能力描述 | 已公开的能力标签、名称和摘要 | 不得扩展为资源未声明的能力 |
| 服务信息 | 授权范围内的服务端点和协议绑定 | 调用前仍需验证端点 |
| 信任材料 | 根平台可信发布证明的必要引用 | 不把引用当作已完成验证 |
| 私密材料 | 私钥、本地身份备份、内部配置和未公开证明 | 不进入公开索引、响应或错误详情 |
参考来源
| 来源 | 类型 | 链接 |
|---|---|---|
oan-discovery-node |
代码仓:同步、索引、结构化查询和语义查询 | https://github.com/OpenAgenet/oan-discovery-node |
oan-protocol-common |
代码仓:发现请求、响应和查询类型 | https://github.com/wolfbrother/oan-protocol-common |
oan-sdk-ts |
代码仓:发现客户端和查询结果处理 | https://github.com/OpenAgenet/oan-sdk-ts |
| GRAIL Semantic Discovery Paper | arXiv 论文:混合语义检索和发现解释 | https://arxiv.org/abs/2605.02489 |
| Efficient Agent Discovery Profile | IETF 草案:智能体发现元数据和查询配置 | https://datatracker.ietf.org/doc/draft-xu-efficient-agent-discovery-profile/ |