灵渠 LingQu
中间件管道与扩展点 SDK

扩展点 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_streamtrue 时,标记了逐 chunk 处理的后置 Hook 会被多次调用——每一个 chunk 调用一次,chunk_index 递增,末块 is_lasttrue。计量类后置 Hook 通常在 is_lasttrue 时汇总落账;护栏类后置 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_typeHook 类型:pre(前置)/ post(后置)
enabled是否启用(启停不需重排管道,停用即在执行时跳过)
order在所属段位内的执行位次(与节点共用位次空间,见 §4)
capability_boundary该扩展点的能力边界声明(见 §5)
  • 注册:扩展点注册时声明其挂载节点、Hook 类型与目标位次;注册后即对后续请求生效。
  • 启停enabled 控制单个扩展点的启用状态。停用的扩展点保留在编排中但执行时被跳过——便于灰度与回退,无需删除注册。
  • 位次调整:扩展点的段位内位次随其挂载节点,通过 概念与编排 §2.2PUT /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 参考:管道编排与扩展点接口的完整端点契约。

On this page