前言¶
在 DeepSeek Harness(DSH)里跑智能体时,工具调用往往会在你未看清参数前就执行:改文件、跑 shell、调 MCP 等,一旦误触很难撤回。常见做法是自己在插件里写一层确认逻辑,或只在少数危险工具上手工拦截,维护成本高,且不同插件之间行为不一致。
下面介绍社区插件 dsh-hitl(维护者 YunpengDon,分类:工作流):它把「执行前先让人看、再批准 / 修改 / 拒绝」做成可挂载的门,目标工具不必改业务代码,也可由其他插件通过 API 一行挂载。
这是什么¶
dsh-hitl 是 DSH 的可安装 bundle 插件:在工具真正执行前,在 DSH Web UI 展示决策卡片(标题、待执行提案、批准 / 修改 / 拒绝按钮)。简介原文为:Human-in-the-loop gate for DSH tool calls: mount any tool behind an approve / modify / reject decision card in the DSH Web UI.
实现上为零依赖、零构建的纯 JS(index.js 宿主侧 + client.js 浏览器侧 + lib/),安装后刷新页面即可注入 window.__DSH_HITL__。npm 包版本为 0.2.1,许可证 MIT,Node 引擎要求 ^22.19.0 || >=24.0.0。
核心功能¶
挂载方式¶
- 配置一行:在
cordis.patch.yml的hitl插件config.protect里列出要保护的工具名(支持mcp__*等模式)。 - API 一行:其他插件
inject: ['hitl']后调用ctx.hitl.protect(...),建议传入调用方ctx作为owner,以便插件卸载时自动解除挂载。
决策卡片与提案展示¶
执行前展示标题与待执行内容;提案字段可配置为:并排 diff(只读)、纯文本输入、可编辑 / 可渲染的 Markdown;文本与 Markdown 可只读或可编辑。未配置 fields 时,默认展示该次调用的全部参数(键名或 schema 的 title,值以 Markdown 输入形式展示,非字符串为格式化 JSON)。
修改与拒绝¶
编辑提案文本后,主按钮由【Approve】变为【Modify】,修改内容作为修订意见回传给智能体。【Reject】可带反馈框,拒绝原因一并返回。
倒计时¶
可配置倒计时及三种结束行为:自动批准、自动拒绝、将超时报告给智能体。
与 DSH 运行模型的配合¶
- 进程内子智能体透传:
spawn/fork子 Session 内的工具调用同样过门;请求会挂在子 Session 与当前查看的 Session 下,卡片可标注「from subagent Session xxx」并提供【Open that Session】。文档说明进程外后端不会经过此门。 - 不在对话页时的提醒:在插件页、设置页或未选中 Session 时,页面顶部浮动通知(数量、工具名、来源 Session、剩余时间 + 批准 / 拒绝 / 打开 Session),避免必须停在原对话才能处理。
服务 API(诊断与生命周期):protect(matcher, options?, owner?)、unprotect(matcher)、list()、pending()。同一工具多次挂载时,以最近一次为准(配置行先注册,插件可覆盖配置)。
安装与启用¶
官方安装方式如下(<your profile> 换成你的 profile 名):
# 从 npm(推荐)
dsh plugin --profile <your profile> add dsh-hitl
# 从 GitHub(无需构建)
dsh plugin --profile <your profile> add github:YunpengDon/dsh-hitl
# 本地目录(开发时改代码后需重启 dsh)
dsh plugin --profile <your profile> add /path/to/dsh-hitl
也可在 GUI:Settings → Plugins → install bundle。
安装后:
- 刷新浏览器页面一次(首次安装必须;已打开页无法拿到注入 token,仅靠热重载不够)。
- 在
cordis.patch.yml配置protect列表,或让其他插件调用ctx.hitl.protect(...)。
卸载:
dsh plugin --profile <profile> remove dsh-hitl
典型用法¶
方式一:仅改配置,不动目标工具代码¶
在 cordis.patch.yml 中为 hitl 插件增加或覆盖一行(注意:patch 覆盖整行 config 时需写全仍要保留的键):
- id: hitl
name: 'dsh-hitl'
config:
protect:
- tool: bash
title: Confirm before running
countdown: { seconds: 30, action: reject }
reject: { feedback: true }
方式二:在自有插件代码里挂载¶
export const name = 'my-plugin'
export const inject = ['hitl']
export function apply(ctx) {
ctx.hitl.protect('bash', {
title: 'Run this command?',
countdown: { seconds: 30, action: 'reject' },
reject: { feedback: true },
}, ctx)
ctx.hitl.protect(['write', 'edit'], {
title: 'Confirm before editing',
diff: { path: 'file_path', before: 'old_string', after: 'new_string' },
countdown: null,
}, ctx)
}
matcher 支持工具名、含 * 的 glob、RegExp、数组或 (exec) => boolean。若挂载未随插件卸载而消失,可用 ctx.hitl.list() 排查,并用 ctx.hitl.unprotect('bash') 或在插件页开关 hitl 行重建状态。
适用场景与注意¶
适合:需要在 DSH Web UI 统一给 bash、写文件、MCP 工具等加人工门的工作流;多插件生态里由各自 protect 绑定生命周期,避免散落手写确认框。
注意:
- 插件与当前 dsh 进程同权限 运行,安装前请自行查看 GitHub 仓库 源码与 MIT 许可证。
- 社区目录 SkillHub 插件页 为独立生态站点,与 DeepSeek / 幻方无官方从属关系;DSH 本身遵循「一切皆插件」,本插件是其中一类工作流扩展。
- 更多交互示例见项目 Landing 站点。
结尾¶
dsh-hitl 把「工具执行前的人工决策」收敛成可配置、可 API 挂载的一层,减少每个工具各自实现确认 UI 的重复劳动。需要试用或查文档时,可访问目录页与仓库:
- 目录页:https://www.skillhub.cn/plugins/YunpengDon/dsh-hitl
- GitHub:https://github.com/YunpengDon/dsh-hitl