扩展点 SDK 参考
前置/后置对称 Hook 模型、Hook 签名与生命周期、扩展点的注册与启停、编排约束与失败处置,以及扩展点的能力边界声明
灵渠平台的中间件管道是可编程的:除三类内建治理中间件外,平台开放一组扩展点,允许在管道的既定位次上挂载自定义的治理逻辑。每个扩展点以一对对称的 Hook(前置 Hook 与后置 Hook)呈现,挂载到某个中间件节点上,随该节点的执行段位(前置 / 后置)被调用。
本页是扩展点 SDK 的接入参考,覆盖:Hook 模型与签名、Hook 在一次请求生命周期中的调用时序、扩展点的注册与启停、编排约束与失败处置,以及扩展点必须遵守的能力边界。
本页定位。 本页与 概念与编排 共同构成灵渠扩展能力的完整文档;扩展点的"接口形态/接入规范齐备"以本页为权威依据。Hook 的具体字段若与平台运行态出现偏差,以「中间件编排」页的扩展点清单与实际运行为准,本文随之修订。
1. 前置 / 后置对称 Hook 模型
每个扩展点提供一对 Hook,二者对称地包裹一次上游调用:
| Hook | 触发时机 | 典型用途 |
|---|---|---|
| 前置 Hook(pre-hook) | 请求转发上游之前,于前置段按位次执行 | 改写或校验入站请求、补充路由提示、入站护栏判定、短路返回 |
| 后置 Hook(post-hook) | 上游响应返回之后,于后置段按位次执行 | 复核或脱敏出站响应、采集计量、写缓存、收尾清理 |
对称性体现在执行顺序上:前置 Hook 正序执行、后置 Hook 逆序执行。即若三个扩展点的前置 Hook 按 1 → 2 → 3 的位次执行,则它们的后置 Hook 按 3 → 2 → 1 的逆序执行。这种"先进后出"的栈式收敛,保证每个扩展点在前置阶段建立的上下文,都能在后置阶段被对称地清理或收尾。
前置段(正序) 内建段 后置段(逆序)
pre-Hook ① ┐ ┌ post-Hook ①
pre-Hook ② ├─→ 上游推理调用 ─→ ┤ post-Hook ②
pre-Hook ③ ┘ └ post-Hook ③
(①②③ 正序) (③②① 逆序,与前置对称配对)即使某个前置 Hook 触发了短路(如缓存命中),管道仍保证已执行的前置 Hook 都得到其配对的后置 Hook——逆序收尾从短路点开始回溯,不遗漏任何已建立的上下文(参见 概念与编排 §2.4 短路语义)。
2. Hook 签名与生命周期
Hook 以"接收一个上下文对象、返回一个处置结果"的统一形态定义。下文以接口契约形态给出入参与出参的 JSON 结构(字段名 + 语义),描述 Hook 在请求前、响应后两个阶段各自的入参出参形态。
2.1 前置 Hook
入参——前置 Hook 在请求转发上游前被调用,拿到待转发请求的治理上下文:
{
"phase": "pre",
"request_id": "<本次请求追踪标识>",
"api_key_id": "<归属子账户标识>",
"request": {
"model": "<请求声明的模型中性名>",
"messages": [
{ "role": "user", "content": "<用户查询>" }
],
"stream": false
},
"routing": {
"complexity": "<复杂度研判结果(简单/复杂)>",
"candidate_model": "<路由当前选定的上游模型中性名>"
},
"metadata": {
"received_at": "<请求进入时间>",
"node_id": "<当前扩展点挂载的中间件节点>"
}
}出参——前置 Hook 返回一个处置结果,决定请求是否继续、是否被改写、是否短路:
{
"action": "<continue | rewrite | short_circuit | reject>",
"request": {
"messages": "<改写后的入站请求(action=rewrite 时)>"
},
"short_circuit_response": "<直接返回的响应(action=short_circuit 时,如缓存命中)>",
"reject_reason": {
"code": "<拒绝错误码(action=reject 时,如 guardrail_blocked)>",
"message": "<面向用户的可读说明>"
},
"context": "<本扩展点向后置 Hook 传递的上下文(在配对后置 Hook 中回传)>"
}action 取值 | 语义 |
|---|---|
continue | 放行,继续后续节点 |
rewrite | 改写入站请求后继续(仅限治理面改写,如脱敏、补充路由提示) |
short_circuit | 短路,跳过内建段上游调用,以 short_circuit_response 进入后置段 |
reject | 拒绝本次请求(如护栏命中应拒答),按 reject_reason 返回结构化拒答 |
2.2 后置 Hook
入参——后置 Hook 在上游响应返回后(或短路后)被调用,拿到响应与前置阶段传递的上下文:
{
"phase": "post",
"request_id": "<本次请求追踪标识>",
"api_key_id": "<归属子账户标识>",
"response": {
"model": "<实际路由的上游模型中性名>",
"content": "<上游返回内容(非流式时整段,流式时当前 chunk)>",
"finish_reason": "<停止原因>"
},
"usage": {
"input_tokens": "<输入词元数>",
"output_tokens": "<输出词元数>",
"cache_hit": "<是否命中上游缓存(布尔)>",
"thinking": "<是否 thinking 档(布尔)>",
"price_tier": "<适用单价档(6 档之一)>"
},
"stream": {
"is_stream": "<是否流式(布尔)>",
"chunk_index": "<当前 chunk 序号(流式逐 chunk 时)>",
"is_last": "<是否末块(布尔)>"
},
"context": "<配对前置 Hook 传递来的上下文>"
}出参——后置 Hook 返回对出站响应的处置结果:
{
"action": "<pass | redact | block>",
"response": {
"content": "<脱敏或改写后的出站内容(action=redact 时)>"
},
"block_reason": {
"code": "<拦截错误码(action=block 时,如 output_unsafe)>",
"message": "<面向用户的可读说明>"
}
}action 取值 | 语义 |
|---|---|
pass | 放行出站响应 |
redact | 脱敏 / 改写出站内容后放行(仅限治理面处置,不重新生成内容) |
block | 拦截本次出站(如输出安全复核未过),按 block_reason 返回结构化拒答 |
2.3 流式响应下的后置 Hook
当 stream.is_stream 为 true 时,标记了逐 chunk 处理的后置 Hook 会被多次调用——每一个 chunk 调用一次,chunk_index 递增,末块 is_last 为 true。计量类后置 Hook 通常在 is_last 为 true 时汇总落账;护栏类后置 Hook 则逐 chunk 复核与脱敏,确保流式输出在生成过程中即被治理。
一次流式请求中,前置 Hook 仍只调用一次(请求转发前);逐 chunk 的多次调用只发生在后置段。
request_id在整条流(含全部 chunk)中保持一致,便于把多次后置调用归并到同一条逐条记录。
3. 注册与启停
扩展点在挂载到中间件节点后即纳入管道编排。查看当前已注册的扩展点清单:
curl https://your-platform/api/v1/pipeline/extensions \
-H "Cookie: <控制台会话凭证>"响应给出每个扩展点的挂载节点、Hook 类型与接入规范引用:
{
"items": [
{
"extension_id": "<扩展点标识>",
"node_id": "<挂载的中间件节点>",
"hook_type": "<pre | post>",
"enabled": true,
"order": 30,
"capability_boundary": "仅控制面治理处置,不实质性生成、加工或合成内容",
"registered_at": "<注册日期>"
}
]
}| 字段 | 含义 |
|---|---|
extension_id | 扩展点标识 |
node_id | 扩展点挂载到哪个中间件节点(路由 / 缓存检查点 / 安全护栏) |
hook_type | Hook 类型:pre(前置)/ post(后置) |
enabled | 是否启用(启停不需重排管道,停用即在执行时跳过) |
order | 在所属段位内的执行位次(与节点共用位次空间,见 §4) |
capability_boundary | 该扩展点的能力边界声明(见 §5) |
- 注册:扩展点注册时声明其挂载节点、Hook 类型与目标位次;注册后即对后续请求生效。
- 启停:
enabled控制单个扩展点的启用状态。停用的扩展点保留在编排中但执行时被跳过——便于灰度与回退,无需删除注册。 - 位次调整:扩展点的段位内位次随其挂载节点,通过 概念与编排 §2.2 的
PUT /api/v1/pipeline/order重排。
扩展点的启停与位次变更是编排面操作,仅运营控制台可见,且只影响治理面行为,不触及上游凭证与计量底座。
4. 编排约束
扩展点接入管道时须满足以下约束,违反者在注册或重排时被拒绝:
| 约束 | 说明 |
|---|---|
| 段位归属固定 | 前置 Hook 只能落在前置段、后置 Hook 只能落在后置段;不可跨段挂载 |
| 段间顺序不可破 | 任何扩展点都不能把后置处置排到内建上游调用之前,反之亦然 |
| 对称配对 | 一个扩展点的前置 Hook 与后置 Hook 共享同一 context 通道;后置 Hook 的逆序位次由前置位次镜像推导,不单独指定 |
| 位次唯一性 | 同一段位内位次相同的扩展点按注册先后保序;建议为关键扩展点显式留出位次间隔 |
| 短路收尾完整 | 任一前置 Hook 触发短路后,其之前已执行的所有前置 Hook 的后置 Hook 必须被逆序执行,扩展点不得依赖"短路后我的后置不会被调用"的假设 |
5. 失败处置
扩展点 Hook 执行过程中的异常,按"治理可控、请求可解释"的原则处置:
| 情形 | 处置 |
|---|---|
前置 Hook 返回 reject | 请求被结构化拒答,按 reject_reason 返回,不再转发上游;逐条记录护栏处置结果为对应类别 |
| 前置 Hook 执行报错 | 按该扩展点的失败策略决定"放行(fail-open)"或"拒绝(fail-closed)";安全护栏类扩展点默认 fail-closed |
后置 Hook 返回 block | 出站响应被拦截,按 block_reason 返回;已发生的计量按实落账 |
| 后置 Hook 执行报错 | 不影响已完成的上游调用与计量落账;按失败策略决定是否放行出站内容,护栏类默认拦截 |
| 短路路径上的后置异常 | 逆序收尾继续执行其余后置 Hook,单个扩展点异常不阻断整条收尾链 |
失败策略(fail-open / fail-closed)随扩展点注册声明。涉及安全合规的护栏类扩展点一律默认 fail-closed——"宁可拒绝,不放行未经复核的内容",与平台安全护栏的治理基线一致。
6. 能力边界声明
每个扩展点在注册时必须携带能力边界声明,并在「中间件编排」页随扩展点清单展示。这条声明对应灵渠中间件管道的统一边界:
扩展点只在控制面 / 治理面对请求与响应施加处置——校验、路由提示、缓存判定、脱敏、拦截、计量采集——不对结果内容做实质性的生成、加工或合成。内容生成始终由路由选定的上游模型完成。前置 Hook 的
rewrite与后置 Hook 的redact都限于治理面改写(如去除敏感片段、补充结构化路由提示),不构成对生成内容的实质性创作。
这一边界既是平台的设计原则,也是扩展点接入的硬性约束:注册一个试图替代上游做内容生成的扩展点,不符合扩展点 SDK 的能力定义。
7. 接口版本与兼容策略
扩展点接口是一份对外稳定的契约——Hook 签名、上下文字段、动作枚举与注册契约,构成自定义中间件可长期依赖的接口面。为此平台对扩展点接口遵循以下版本与兼容策略:
| 维度 | 策略 |
|---|---|
| 版本编号 | 扩展点接口采用语义化版本 主版本.次版本.修订号;当前接口版本随扩展点清单一并暴露 |
| 向后兼容 | 同一主版本内只做向后兼容的演进——新增可选字段、新增动作取值、放宽约束;既有 Hook 签名与必选字段语义保持不变 |
| 破坏性变更 | 任何破坏向后兼容的变更(移除 / 重命名字段、收紧约束、变更动作语义)必须提升主版本,并提前足够的日历日通知,提前期以服务协议与控制台公告为准 |
| 弃用过渡 | 计划移除的字段或动作先标记为弃用(deprecated)并保留过渡期,过渡期内新旧并存、运行态对弃用项给出告警,期满后随主版本提升移除 |
| 版本可见 | 当前接口版本与已弃用项可经扩展点清单查询,便于自定义中间件在升级前评估影响 |
读取当前接口版本与弃用项,随扩展点清单一并返回:
curl https://your-platform/api/v1/pipeline/extensions \
-H "Cookie: <控制台会话凭证>"{
"sdk_interface_version": "<扩展点接口语义化版本>",
"deprecations": [
{ "field": "<弃用的字段 / 动作>", "since": "<弃用起始版本>", "removed_in": "<计划移除版本>" }
],
"items": []
}区分两种版本。 这里说的是扩展点接口契约的版本(平台对所有自定义中间件的统一承诺);它与单个插件构建产物的版本(
artifact_ref携带、用于热替换,见 自定义插件开发 §5.1)是两个独立的版本空间。接口契约的稳定让插件产物得以长期沿用,无需因平台内部演进而频繁重构;破坏性变更的提前通知也以接口契约版本为单位发布。
相关链接
- 概念与编排:三类治理中间件、执行位次、条件分支、短路语义与流式逐 chunk 处理。
- 自定义插件开发:把 Hook 组织成可分发插件的工程闭环——构建产物、动态加载、注册、启停与失败处置。
- 用 Go 编写原生插件:原生可加载单元(Go)的语言落地指南——同进程、性能最优、须与平台运行环境构建参数对齐。
- 用 TypeScript 编写插件:经 AssemblyScript 兼容子集编译为 WASM 沙箱可加载单元的语言落地指南。
- 用 WebAssembly 编写插件:沙箱可加载单元的通用 host-guest ABI 与跨语言(Rust 等)编写路径。
- API 参考:管道编排与扩展点接口的完整端点契约。