切换主题
外部知识协议与权限过滤
本页阅读位置
完成第一轮对话后,按当前业务需求深入。Spring 常规声明优先使用 RegistrationManifest 与注解;本页的底层 register / publish 或直连方法供协议细化与兼容集成参考。
外部知识源可以连接已有数据库、搜索引擎或企业知识库。平台负责授权、限时、结果验证、文档访问过滤和引用事件;Provider 负责在业务查询中实施用户权限,不把检索正文当指令。
配置与发布
在“知识库 → 新建”选择远程知识服务,填写已获准的 endpoint、服务端密钥引用,选择“1.0 · 结构化结果”。受限源填写 TENANT, SUBJECT;新版定义配置 permissions 时必须声明 SUBJECT。服务不支持所要求过滤时应拒绝,不能返回不受限正文。
json
{
"mode": "REMOTE",
"endpoint": "https://business.example.com/agent/knowledge/project-documents/1.0.0",
"secretRef": "PROJECT_CALLBACK_KEY",
"callbackProtocolVersion": "1.0",
"mandatoryFilters": ["TENANT", "SUBJECT"],
"topK": 3,
"permissions": ["project.read"]
}服务端配置 HTTPS origin、密钥名称/origin/application 绑定,业务回调使用同一密钥。先发布知识版本,再把精确 id/version 加入 Agent.allowedKnowledge 并发布 Agent;业务权限服务、文档 ACL 与强制查询过滤均独立生效。
请求字段
| 字段 | 类型与来源 |
|---|---|
| protocolVersion | 固定字符串 1.0 |
| appId / subjectId / tenantId | 已认证应用、用户和租户,身份最长 128 字符;tenantId 可为空 |
| knowledgeId / version | 被授权的知识资源精确版本 |
| query / topK | query 1–16384 字符;topK 1–10 |
| filters | appId/subjectId/tenantId 与顶层一致;required 为定义要求的 TENANT/SUBJECT 去重列表 |
| runId / traceId / executionId | 当前任务、追踪和此次检索编号;Idempotency-Key 为 executionId |
| deadline | Unix 毫秒截止时间,受当前 Agent 与全部祖先约束 |
| trustedContext | 经过平台验证的业务数据,不能代替鉴权 |
filters 与身份不从聊天 Context 获取。即使用户写入 context.subjectId 或 context.filters,它们也不会覆盖回调身份。回调处理器在调用业务 Provider 前校验认证、应用、知识编号/版本、过滤身份及声明一致性。
结果字段
json
{
"protocolVersion": "1.0",
"appliedFilters": ["TENANT", "SUBJECT"],
"items": [{
"id": "chunk-18",
"documentId": "project-spec",
"content": "设备安装位置应符合项目要求。",
"title": "安装规范",
"source": {"type": "DOCUMENT", "id": "project-spec", "version": "v2", "page": 18},
"score": 0.91,
"metadata": {"section": "设备安装"},
"tenantId": "team-a"
}]
}| 字段 | 要求 |
|---|---|
| items | 0–100 项;空数组为正常无匹配;完整响应最多 1 MiB |
| id | 命中项编号,1–128 字符,只含字母/数字/下划线/点/冒号/横线,去重,不能为 . 或 .. |
| documentId | 原文档编号,用于平台文档 ACL;省略时使用 id;分片必须填写原文档编号 |
| content | 非空正文,最多 16384 字符;不是 HTML 或附件 |
| title / tenantId | 可选,最多 512 / 128 字符;空租户表示应用共享,不代表私人文档可公开 |
| source | 必填,type 为 DOCUMENT/URL/INLINE,id 最长 128;可含 version、page、locator 和 uri |
| source.page / locator | 页码 1–1000000;定位说明最多 512 字符 |
| source.uri | 最多 2048 字符,仅 HTTP/HTTPS、有效主机、无 userInfo;URL 类型必须提供 |
| score | 可选有限数字 0–1;未知时省略,不填写伪造的零分 |
| metadata | 可选 JSON 对象,最多 4096 UTF-8 字节,嵌套深度 8 |
| appliedFilters | 明确确认已在业务查询中实施的过滤;必须包含 mandatoryFilters 全部条目 |
Provider 的 appliedFilters 是对业务实现的声明,不能把“照抄 required”当成已经完成权限过滤。平台继续根据 documentId、租户、当前文档 ACL 与业务安全 epoch 过滤;撤权后历史事件/会话不能绕过当前权限。SDK 额外在截断前排除不匹配租户,业务服务也必须在查询本身限制用户/租户范围。
SDK 示例
java
@AgentKnowledge(
name = "project-documents",
description = "检索项目业务文档",
mandatoryFilters = {"TENANT", "SUBJECT"}
)
public final class ProjectKnowledgeProvider implements KnowledgeProvider {
private final DocumentService documents;
public ProjectKnowledgeProvider(DocumentService documents) {
this.documents = documents;
}
@Override
public KnowledgeResult retrieve(KnowledgeQuery request, KnowledgeContext context) {
// 该业务方法必须在查询中限制应用、租户和用户 ACL,而不是检索后照抄声明。
List<KnowledgeItem> hits = documents.searchAuthorized(
context.appId(), context.tenantId(), context.userId(),
request.query(), request.topK());
return KnowledgeResult.items(hits, Set.of("TENANT", "SUBJECT"));
}
}kotlin
@AgentKnowledge(
name = "project-documents",
description = "检索项目业务文档",
mandatoryFilters = ["TENANT", "SUBJECT"]
)
class ProjectKnowledgeProvider(private val documents: DocumentService) : KnowledgeProvider {
override suspend fun retrieve(request: KnowledgeQuery, context: KnowledgeContext): KnowledgeResult {
val hits = documents.searchAuthorized(
context.appId(), context.tenantId(), context.userId(), request.query(), request.topK())
return KnowledgeResult.items(hits, setOf("TENANT", "SUBJECT"))
}
}Java 示例说明:
DocumentService 是已有业务服务,返回实际命中映射为 KnowledgeItem(id,documentId,content,title,KnowledgeSource,Double score,Map metadata,tenantId);来源可用 KnowledgeSource.document(id)、KnowledgeSource.url(id,uri) 或 new KnowledgeSource(Map.of(...)),metadata 和返回快照不可变。上述类需导入 dev.sparktide.sdk.*、java.util.List/Set,DocumentService 接口由项目提供。
使用 new AnnotatedKnowledge(bean, endpoint, secretRef) 创建注册定义,挂载 resource.callback(appId, credentialSupplier);构造注解生成 callbackProtocolVersion=1.0。保持业务安全拦截器在 Service 内,不反射创建第二个业务实例。Spring 自动发现与续租方式见知识提供器与自动注册说明。
Kotlin 示例说明:
Java DTO 仍来自 dev.sparktide.sdk,Kotlin suspend 接口来自 dev.sparktide.sdk.kotlin.KnowledgeProvider,挂载用 annotatedKnowledge(bean,endpoint,secretRef)。桥接协程使用剩余期限,超时转换为 KNOWLEDGE_TIMED_OUT;不能据线程或协程取消承诺撤销业务系统已经发生的行为。
错误、无匹配和可观测事件
失败使用非 2xx 与 {"error":{"code":"KNOWLEDGE_ACCESS_DENIED"}}。Java/Kotlin Provider 可以抛出 KnowledgeProviderException(Code...)。SDK 的未知业务异常返回 503/KNOWLEDGE_UNAVAILABLE,异常正文不返回给平台;HTTP 401/403、408/504、429、5xx 分别映射拒绝、超时、限流、不可用。明确分类代码优先于 HTTP 状态,未知分类/畸形返回为协议错误;即使 HTTP 200 含分类 error,也不当作成功结果。
| 代码 | 含义 |
|---|---|
| KNOWLEDGE_ACCESS_DENIED | 回调认证/业务拒绝,或缺少强制过滤确认 |
| KNOWLEDGE_TIMED_OUT | 回调/检索超过期限 |
| KNOWLEDGE_RATE_LIMITED | 业务知识服务限流 |
| KNOWLEDGE_UNAVAILABLE | 服务/网络不可用,或未分类 Provider 异常 |
| KNOWLEDGE_REQUEST_REJECTED | 请求被业务服务拒绝 |
| KNOWLEDGE_PROTOCOL_ERROR | 未知协议、字段/体积/分数/来源/编号错误 |
检索失败没有自动重试,也不伪造空结果继续回答。knowledge.retrieved 保留 count,增量 status 为 SUCCEEDED/EMPTY/FAILED、knowledgeVersion 与失败 errorCode。失败不会修改模型健康,也不会产生该轮模型请求。
新版 citation.created 增量 sourceRef/score/metadata/itemId,documentId 表示 ACL 文档;旧协议及托管引用的 documentId 保持原行为,不静默改写历史。来源页码只是定位事实,尚不能替代鉴权预览;不要直接把 source.uri 当已授权下载。前端仍按任务所有者权限读取事件。
兼容与回退
未设置 callbackProtocolVersion 的 REMOTE 继续读取 {"documents":[{"id":"doc","text":"正文","title":"标题","source":"来源","tenantId":"team-a"}]};结果也受格式、体积与文档 ACL 检查。旧 Java KnowledgeQuery(query,topK)、KnowledgeResult(List<KnowledgeDocument>) 保留;SDK 能在没有强制条件时转换为新 items,但不会编造 appliedFilters。已有 Provider 应升级知识版本和 Agent 引用,不修改已发布定义。
回退到旧知识精确版本前确认该版本实施业务权限;需要过滤的源不能退成公共检索。无数据库迁移,不修改旧事件或访问规则。协议由知识回调 Schema 和 OpenAPI 六个 Knowledge 结构给出;字段约束之外的 URI、体积、过滤身份和深度校验以运行时为准。
状态:已确认;日期:2026-09-30;责任人:SparkTide 维护者;关联任务:K07;来源:KnowledgeProtocol、AnnotatedKnowledge、KnowledgeItem、HTTP/SDK 行为测试。真实企业数据源需按其查询权限与质量单独验收。
下载 Knowledge 回调 Schema · 注解与自动注册
请求校验
新版认证回调要求完整的 runId、traceId、executionId 与 trustedContext 对象。SDK 在业务 Provider 执行前拒绝缺字段、额外字段、重复 JSON 键、尾随 JSON 以及非法截止时间。运行、追踪和执行编号各最多 128 字符;业务上下文不能替代授权。
