DSH plugin 钩子插件怎么写?tools/pre-execute 执行门禁的放行与拒绝

插件开发发布于 2026-10-02作者: DeepSeek Plugin 插件市场
DSH pluginDeepSeek Harness钩子插件tools/pre-execute权限门禁
DeepSeek Harness 的 DSH plugin 钩子插件在 tools/pre-execute 返回类型化决策:deny 拒绝、next() 放行;配合 ctx.tools.guard()、tools/execute、tools/post-execute、tools/result 覆盖不同拦截强度。

DSH插件里的钩子插件,就是「在拦截点上运行的普通 Cordis 插件」——监听 tools/pre-execute 拿到待执行的工具调用,返回 { kind: 'deny', reason } 拒绝、返回 next() 放行。 权限门禁只是它的一个示例;沙箱、权限与 plan-mode 插件都复用同一扩展点。它不需要任何外部协议,官方称之为「原生钩子」。

DSH plugin 钩子插件是什么:在拦截点上运行的普通 Cordis 插件

钩子插件本身不等同于权限门禁——它是在拦截点上运行的普通 Cordis 插件,可以拦截多种扩展点(来源)。 官方给出的最小示例是权限门禁,从 tools/pre-execute 返回类型化决策,决定允许或拒绝一次调用:

ts
import type { Context } from '@deepseek-ai/cordis'
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'

declare function isAllowed(exec: ToolExecution): Promise<boolean>

export const name = 'permission-gate'

export function apply(ctx: Context) {
  ctx.on('tools/pre-execute', async (exec, next): Promise<PreToolDecision> => {
    if (!(await isAllowed(exec))) {
      return { kind: 'deny', reason: 'Denied by policy.' }
    }
    return next()
  })
}

它用到的正是 waterfall 事件:tools/pre-execute 是可重排的策略层,每个监听器拿到 exec 与 next(),可以返回决策,也可以调用 next() 交给下游。这与 DSH plugin 事件系统 里 waterfall「必须调用 next()」的纪律是同一条规则。

DSH plugin 的门禁怎么写:tools/pre-execute 的放行与拒绝

在 tools/pre-execute 上,返回 { kind: 'deny', reason } 即拒绝该次调用,调用 next() 即放行或继续下传(来源)。 按三步写一个最小门禁:

  1. 声明钩子插件 — 模块顶层导出 name,例如 permission-gate。预期:加载后作为独立插件生效。
  2. 在 apply 内注册监听 — ctx.on('tools/pre-execute', async (exec, next) => { ... })。预期:每次工具执行前都会进入你的 handler。
  3. 返回决策 — 不允许时返回 { kind: 'deny', reason: '...' },允许时 return next()。预期:被拒绝的调用不会执行,并带上 reason。

需要用户确认时返回 ask,再通过 ctx.approval 应答。 官方的权限系统 / AskUserQuestion 就是这样实现的:从 tools/pre-execute 返回 ask,并注册一个面向模型的独立 ask 工具。想了解审批策略的取值与结果,见 权限预设与审批。

DSH plugin 拦截点怎么选:pre-execute、guard、execute 与 result

四个拦截点的选择标准是「要不要改结果、要不要强制」:策略层用 tools/pre-execute,强不变式用 ctx.tools.guard(),包裹分发用 tools/execute,变换结果用 tools/post-execute,只观察不改动则用 tools/result(来源)。 对照如下:

  1. tools/pre-execute — 可重排的策略层,返回允许 / 拒绝 / 追问。预期:适合权限、沙箱、plan-mode 这类可组合策略。
  2. ctx.tools.guard() — 强制不变式、提供单调的最终拒绝。预期:适合硬约束,后续监听器无法翻盘。
  3. tools/execute — 包裹分发生命周期,可用于超时 / 重试 / 指标(仅 exec.signal 可替换)。预期:适合给工具调用加通用包装。
  4. tools/post-execute — 显式结果变换;只想观察不可变最终结果则用 tools/result。预期:不改结果就别用 post-execute。

一个实战提醒:钩子插件拦截工具调用时不要顺手改动工具自身的实现,工具契约归 ctx.tools.register() 与 defineTool 管,参见 工具插件开发。写完自检三项:handler 是否在所有分支都返回决策或 next();硬约束是否用了 guard();deny 是否带上可诊断的 reason。想找现成的沙箱 / 权限类插件对照,可在 DSH Plugin Hub 检索。

常见问题

DSH plugin 的钩子插件是什么?和权限门禁是一回事吗?

DSH plugin 的钩子插件就是在拦截点上运行的普通 Cordis 插件,不需要任何外部协议,官方称之为「原生钩子」。权限门禁只是钩子插件的一个示例,它从 tools/pre-execute 返回类型化决策;钩子插件还可以拦截其他扩展点,本身不等同于权限门禁。

DSH plugin 怎么写一个 tools/pre-execute 权限门禁?

DSH plugin 写门禁只需三步:声明 name、在 apply 里 ctx.on('tools/pre-execute', handler)、让 handler 返回类型化决策或调用 next()。官方示例在 isAllowed(exec) 为假时返回 { kind: 'deny', reason: 'Denied by policy.' },否则 return next() 放行。

DSH plugin 的 tools/pre-execute 返回什么决定放行还是拒绝?

DSH plugin 在 tools/pre-execute 上返回 { kind: 'deny', reason } 即拒绝该次调用,返回 next() 或继续调用 next() 则放行。官方也支持在此返回 ask,再通过 ctx.approval 应答,实现需要用户确认的权限流程。

DSH plugin 的 ctx.tools.guard() 和 tools/pre-execute 有什么区别?

DSH plugin 的 tools/pre-execute 是 waterfall 式策略层,决策可被后续监听器重排;ctx.tools.guard() 用于不变式场景,需要单调、不可翻盘的最终拒绝。前者适合可组合策略,后者适合必须被强制的硬约束。

DSH plugin 拦截工具调用有哪几种扩展点?guard、execute、result 怎么选?

DSH plugin 拦截工具调用主要有四种:tools/pre-execute 做策略层放行或拒绝、tools/execute 包裹分发生命周期、tools/post-execute 做显式结果变换、tools/result 观察不可变最终结果。按「要不要改结果、要不要强制」来选即可。

相关术语

钩子插件(hook plugin)
钩子插件是 DSH plugin 里的一种形态,通过监听并拦截工具或其他扩展点来实现策略;它在拦截点上运行,是普通 Cordis 插件,不依赖外部协议,官方称为原生钩子。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/extension-cookbook
tools/pre-execute
tools/pre-execute 是 DSH plugin 的执行门禁扩展点,钩子监听它会收到待执行的 ToolExecution 与 next(),返回类型化决策即可允许、拒绝或追问一次工具调用;沙箱、权限与 plan-mode 插件都使用它。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/extension-cookbook
PreToolDecision
PreToolDecision 是 DSH plugin 在 tools/pre-execute 上返回的决策类型,deny 表示拒绝并给出 reason,配合 next() 表示放行或继续下传。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/extension-cookbook
ctx.tools.guard()
ctx.tools.guard() 是 DSH plugin 用于强制不变式的工具守卫,提供单调的最终拒绝;当约束不允许被后续监听器翻盘时应使用它,而不是可重排的 policy 层。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/extension-cookbook

来源