DPE 投递协议
面向外部数据源系统的 DPE(Document / Page / Element)投递协议。外部系统将自己业务数据转换为 DPE 标准结构后,通过本协议投递到指定 Robot 的 Memory 中;协议在传输层实现增量协商——只传服务端缺失的内容,传输量与实际变更内容成正比,与文档总量解耦。
!!! note "状态" 起草中(v1)· 2026-09-18 · 归属 TFRS-379 · 内核依赖 TFROB-374(已完成)
权威规范
| 文档 | 范围 |
|---|---|
| push-protocol-v1.md ⭐ | 投递协议规范正文:三阶段流程、报文形状、认证授权、错误模型、幂等与版本治理 |
| hash-contract-v1.md ⭐ | Hash 算法 wire 契约与一致性测试向量 —— 跨语言 SDK 的实现基准 |
新读者从这两份开始。
为什么需要这个协议
内核三层内容寻址 hash(TFROB-374 Epic 交付)已让写侧最小化:源文档变更后重新入库,未变的 element 不再触发 GraphIndex 的 LLM 抽取。但传侧仍是全量——外部源每次更新都要重传完整 Document,大文档(数百 element、含 base64 图片)每次同步占用大量带宽,且传输耗时随文档体积线性增长。
DPE 三层 hash 与 Git 的 blob / tree / commit 对象模型同构,天然支持「只传缺失对象」。本协议采用 Git 式批量协商:数据源先推 manifest(hash 骨架),服务端回缺口清单,数据源仅补传缺口内容。
与全量推送的关系
增量投递与全量推送在服务端语义上完全一致——两者最终都走内核 upsert_doc 的 LCS reconcile,收敛结果逐字节相同。本协议不引入任何新的并发语义,也不引入第二套 diff 权威:内容配对独家交给 upsert_doc,协议层只做「内容缺失补全」。
这一约束是本协议最重要的设计决策。双 diff 权威(客户端算一套、服务端算一套)是此类协议最典型的失败模式,必须在规范层面排除。
设计基线:三条既有机制
制定本协议前核实的既有能力。协议不重造这些轮子:
| 能力 | 内核现状 | 协议如何衔接 |
|---|---|---|
| 算法版本记录 | 已有 —— Document.hash_strategy_uri(NOT NULL),格式 hash-strategy://{name}?algo_version={v};跨版本自动 _full_rebuild |
原样透传该 URI,不另立 hash_algo_version 字段 |
| 服务端重算 hash | 已有 —— Document 构造时传入 hash_strategy 实例会触发 HashStrategy.attach(),三层 hash + seq_in_page 全自动 |
服务端重算作为唯一权威,客户端 hash 仅作协商提示 |
| 免 setting_id 取用 Robot | 已有 —— container.robot() 为 Singleton,Robot → Brain → Memory 进程内 1:1 |
统一接口无需 Robot 配置检索;请求打到哪个部署就投给哪个机器人 |
!!! tip "为什么外部系统不需要理解 Factory"
setting_id 只存在于 Factory 配置管理面(发布 / 草稿 / 编辑);运行时取用路径(Celery 任务、聊天)走的都是 container.robot(),由进程 env 中的 rid 决定身份,根本不经过 setting_id。
因此统一接口对外的形态只需暴露一个 URL。请求中的 `X-TFRS-Robot-Id` 仅用于**防误路由校验**,不是查询键。
三层版本模型
三个版本维度正交、独立演进:
| 维度 | 载体 | 谁决定 | 变更时 |
|---|---|---|---|
| 协议版本 | dpe-push/1(media type) |
TFRobotServer | 破坏性变更 → /2;非破坏 → 同版本内加可选字段 |
| 算法策略版本 | hash_strategy_uri |
TFRobot 内核(SDK 跟随) | 内核 bump algo_version → SDK 加实现 → 服务端 allowlist 放行 |
| 内容版本 | doc_hash |
由内容决定 | 每次投递 |
!!! warning "content_hash 不是全局可比标识"
content_hash / page_hash 不带算法前缀,其算法由同文档的 hash_strategy_uri 决定。
**不得跨文档比较或搬运 hash,除非两者的 `hash_strategy_uri` 完全相同。** 这条约束必须在 SDK 的 API 契约中固化(相关函数不接受裸 hash 参数),否则必然被误用。
明确不支持
| 项 | 原因 |
|---|---|
image-source 策略 |
该策略的 doc_hash = source_file_hash,需要源文件字节;而 DPE-only 投递没有源字节 |
image_path 图片通道 |
现有链路强制图片相对路径以 {robot_id}/ 开头(隔离规则);新端点不复用该检查,v1 直接禁止 image_path,要求使用 image_base64 |
| 部分提交 / 断点续传 | 内核 upsert_doc 是整文档事务,无法部分提交 |
详见 push-protocol-v1.md 的「明确不支持」章节。
待决策
| # | 议题 | 说明 |
|---|---|---|
| 1 | scope 命名 | 新增 dpe:push(需协调 TFRSManager,scope 词表 SoT 在 M0/TFRM-164),或复用现有 scope 换取零跨项目成本。推荐前者——复用 config:write 会让外部集成方获得改写机器人配置的权限,属提权 |
| 2 | file_uri 保留 scheme |
file_uri 在 PG 中 UNIQUE,外部系统 URI 需与内部源(feishu / cos)命名空间隔离。候选:dpe://{tenant}/{path} |
| 3 | image-source 是否 v1 支持 | 决定是否现在向 TFROB 提「允许客户端自带 source_file_hash」的能力需求 |