中文 · English
为 DeepSeek Harness 生态打造的常驻代理实体插件
不属于任何会话的 bot:有自己的实例、你能打开和修改的记忆、一条任务队列,和一个会在边界处停下等你的执行器。
文档
| 目标 | 入口 |
|---|---|
| 了解插件为什么存在、和「会话」有什么不同 | 为什么做常驻实体 |
| 安装、配置与日常使用 | 用户指南 |
| 全部 7 个工具的参数、输出与示例 | 工具参考 |
| 了解 store / 执行器 / 记忆分层 / 审批闸门 | 架构说明 |
| 对照 2026 主流助理调研:已实现与未实现 | 功能对照 |
| 查看全部文档与 README 分工 | 文档索引 |
这是什么
dsh-bot 给 DeepSeek Harness 提供一种不属于任何会话的代理实体:
- 它不属于某一次对话:会话关掉、上下文压缩、机器重启,它都还在。实例、记忆、任务队列都在
$DSH_HOME$DSH_HOME/bot/里,每个会话读写的都是同一份; - 记忆是你能打开的文件:不是不可见的向量库,而是
$DSH_HOME$DSH_HOME/bot/memory/下一棵.md文件树。改一处,之后每次对话都按新的来;根文件常驻上下文,子目录只在提示里贡献名字和一句话描述; - 它会自己推进事情:一条任务队列 + 可选的执行器。自主时间默认关闭,打开后也只在可检查的条件成立时才动——队列里有自己的活、有没回应过的外部消息、有到点的日程;
- 它在边界处停下等你:需要动工作区外面的东西时,任务进入
awaiting状态并把工具名和完整参数摆给你看。你批准的是这一个动作,不是一类动作。
一句话:安装插件 = 得到一个会说「我记着这件事」、并且真能去做的常驻实体。
快速开始
插件要装进你要用的那一端的 profile 里。
# 从源码目录安装(独立仓库,一插件一仓库)
dsh plugin --profile web add <本仓库路径>
# 或从 npm 安装(若已发布)
dsh plugin --profile web add dsh-bot
装好后:左侧栏出现 bot 条目,点开就能按类型创建一个实例(内置伴侣 / 助手 / 研究员 / 记录员四种,也可以自己建),或者进入已有的。右上角齿轮进设置页,里面是记忆、任务、限额、连接、MCP 服务、头像、类型。
安装后 agent 即可使用 7 个 bot_* 工具:
| 想做什么 | 用哪个工具 | 说明 |
|---|---|---|
| 看它现在什么状态 | bot_status |
实例、心跳、队列、当前模型与来源 |
| 让它记住一件事 | bot_remember |
写进它自己的记忆文件,可标注来源 |
| 问它记过什么 | bot_recall |
按词检索;中文按双字切分 |
| 让它去做一件事 | bot_task |
排队、指定时间、循环、续跑或另起 |
| 让它对外说一句话 | bot_connector |
经用户配置的连接(Telegram / HTTP)发出 |
| 用一次凭据 | bot_secret |
值不进上下文,只送进虚拟桌面 |
| 提醒它某个时刻 | bot_agenda |
到点经连接器提醒 |
完整清单见工具参考。
主要功能
记忆是文件,不是向量库记忆落在 |
每条记忆带来源条目记录它来自 |
敏感信息分两道门硬门:身份证号、社保号、银行卡号、密码密钥、会话令牌 —— 无论设置怎么调都拒绝,并告诉你该怎么绕(用 |
记忆有时效每条记忆算得出「多少天前」。超过设定天数(默认 90)的条目被标成陈旧并在提示里注明。算不出时间时用 |
审批是一等的任务状态它想动工作区外面的东西时会停下来,任务进入 |
一键豁免,但带过期同一个动作反复问会把人磨钝,于是可以授一张通行证。通行证只匹配完全相同的工具名,而且一定带过期时间 —— 没有「永久允许」这个选项,因为没人能替未来的自己签字。改任务标题或备注会撤销批准:你当初批准的是当时读到的那个任务。 |
自主时间靠理由驱动默认关闭,打开后空闲只是前置条件,不是理由本身。必须有一个可检查的条件成立:队列里有自己的活(默认)、有没回应过的外部消息、有到点的日程、工作区里有比自己上次看过更新的文件。找不到理由就明确报告「空闲够了,但没有任何符合条件的理由」,而不是被悄悄填满活动。 |
它自己的权限分三档
|
MCP 是客户端,不是硬编码集成插件不带任何 MCP 服务、不带地址、不带凭据 —— 它带一个客户端和一个输入框。你填一个 streamable HTTP 地址,那边的工具就出现在它能用的工具里。工具名沿用 |
状态灯三态,不撒谎每个服务旁边的圆点:绿=真的测过一次并且通过,红=测过一次并且失败,灰=还没测过。「没人看过」和「它没问题」不是同一个说法,所以灯不合并这两种。绿点下还留着上次成功和上次失败两个时刻 —— 「14:02 还能用、14:31 停了」和「它从来没好过」是两种处境。 |
周期工作两种语义循环任务可选续跑同一上下文(带上上次结论,例行公事要的就是这个)或另起独立任务(从零开始,审计要的是这个)。理由是:先读自己上次的结论,一个检查就悄悄变成了橡皮图章。 |
入口不止一个入站连接把外面的消息带进来:Telegram 长轮询、或一个带令牌的 HTTP 端点。外部消息会被标明来源并限长(默认 4000 字,可调),因为「谁说的」和「说了多久」都是判断的一部分。 |
限额全部由用户定没有任何写死的配额。每次召回几条、提示里回放多少轮、记忆总量、单次任务分钟数、每天多少分钟、入站消息上限、并发数与轮询间隔 —— 全在设置页里,默认值集中在一处可查。 |
头像与类型都能自己来内置四种类型(伴侣 / 助手 / 研究员 / 记录员),名字、说明、人设都能改,也可以自己建。头像可以上传自己的图片(PNG / JPEG / WebP / GIF,4 MB 以内),按内容类型校验而不是看文件名。 |
为什么选它
- 它不是一个更长的会话:常见的做法是把上下文做长,而这里是把状态搬到会话外面。会话是暂时的,实体是持续的 —— 两者不是同一件事,混起来会同时得到两者的缺点。
- 可治理优先于聪明:记忆是文件、来源是标签、限额是设置、审批是状态。每一条都让「它为什么这样」有一个能查的答案,而不是一个需要相信的结论。
- 危险的事做成可见的:界面上每一步都能看到它在请求什么、上次是什么时候好的、这条记忆是谁说的。最危险的不是它会做错事,而是它悄悄做对了错事。
工具参考
| 工具 | 用途 | 碰外部 |
|---|---|---|
bot_status |
实例清单、心跳、队列、当前生效的模型与来源 | – |
bot_remember |
记一条持久条目(text + 可选 kind / source) |
– |
bot_recall |
按词检索记忆(中文按双字切分;可按类型筛选) | – |
bot_task |
任务队列:排队 / 指定时刻 / 循环 / 续跑或另起 / 取消 | – |
bot_connector |
让实例经用户的连接对外说话 | ✅ |
bot_secret |
把凭据送进虚拟桌面(值不进上下文) | ✅ |
bot_agenda |
记下一个时刻该做什么,到点经连接器提醒 | ✅ |
「碰外部」指该工具会让数据离开本机 —— 前四个只读写
$DSH_HOME$DSH_HOME/bot/。
记忆写在哪
bot_remember 按类型落到不同文件:focus 进 USER.md(用户在意什么)、decision / fact 进 MEMORY-CORE.md、其余进 notes/YYYY-MM.md。这不是实现细节,是策略:常驻上下文的那几份只放最能改变行为的,其余按需检索。
它会怎么读自己的记忆
根文件全文进系统提示;子目录里的每个文件只贡献 name 和 description 两行 frontmatter。所以给一份笔记写一句好的 description,比给它写长正文更有用 —— 那决定它会不会想起来去读。
配置
插件通过 cordis.patch.yml 挂载一行(以裸包名注册)。用户可改的东西几乎都在设置页,不在这个文件里:
| 位置 | 内容 |
|---|---|
$DSH_HOME$DSH_HOME/bot/bot.json |
实例、类型、记忆索引、任务、连接、MCP 服务、限额、规则 |
$DSH_HOME$DSH_HOME/bot/memory/ |
记忆本体(.md 文件树,可直接编辑) |
$DSH_HOME$DSH_HOME/bot/avatars/ |
上传的头像文件 |
设置页分这些栏目:实例与类型 · 记忆 · 任务与队列 · 自主时间 · 限额 · 规则 · 连接 · MCP 服务 · 头像 · 日程。
限额项(全部有默认值,全部可改,0 一律表示不限):
| 设置 | 默认 | 说明 |
|---|---|---|
| 单次任务上限 | 30 分钟 | 一次后台任务最多跑多久 |
| 每天合计 | 不限 | 所有后台任务当天总时长 |
| 每任务工具轮数 | 8 | 一次任务里模型能连续调用几次工具 |
| 任务总数 | 300 | 队列保留多少条,超出丢最早的 |
| 提示里回放的消息数 | 12 | 系统提示带多少条历史消息 |
| 面板一次加载 | 60 | 界面上一次拉多少条消息 |
| 可检索记忆条数 | 200 | 索引上限;记忆文件本身永不被裁掉 |
| 入站消息上限 | 4000 字 | 超出截断并注明来源 |
| 记忆陈旧阈值 | 90 天 | 超过标记为陈旧 |
| 敏感信息模式 | 排除 | 排除 / 记(硬门不受影响) |
唯一两个有上下界的是自主时间的并发数与轮询间隔 —— 它们是机制参数而不是配额,所以给了范围而不是「不限」。
工作原理
会话侧(模型) 宿主侧(插件) 磁盘
bot_* 工具 ──→ ctx.tools 注册的处理器 ──→ $DSH_HOME$DSH_HOME/bot/bot.json
│ └─ memory/*.md
├─→ 执行器(可选,默认关) └─ avatars/
│ └─ 任务队列 → 一次模型会话 → 工具调用
├─→ 审批闸门(工作区边界判定)
└─→ 入站连接(Telegram 长轮询 / HTTP 端点)
Web 侧(浏览器) 同一条 HTTP 路由
侧边栏条目 ──→ /api/bot.state(只读轮询,3 秒)
bot 页面 ──→ /api/bot.manage(写操作)
设置页 ──→ 同一组路由
- 两半都在一个包里:
impl.js是宿主(store、执行器、工具、路由),client.js是 Web 半(侧边栏、页面、设置)。客户端那半通过window.__ModuleLoader__.load()注册,不 import 任何@deepseek-ai/dsh-client-*包; - 一次轮询喂所有界面:侧边栏的每个条目和页面订阅同一次
/api/bot.state,所以它们不会各说各话; - 工作区边界是可判定的:
workspaceVerdict(toolName, args, workspace)是纯函数,返回inside/guarded/refused/unchecked。unchecked是其中最重要的一个 —— 「查过了,没问题」和「这里没东西可查」必须在代码里分得开,否则前者会冒充后者。
环境要求
- DeepSeek Harness(dsh),已安装
webprofile - Node.js ≥ 22.19
- 一个可用的模型(插件默认跟随 DSH 的默认模型,无需单独配置)
验证过的版本
| 组件 | 版本 |
|---|---|
| DeepSeek Harness(dsh) | 0.2.0-rc.2(peer 声明 >=0.2.0-rc.1 <0.3.0) |
| Node.js | 22.20.0 |
| 操作系统 | Windows(10.0.26200) |
| dsh-bot | 1.0.0 |
当前仅在 Windows 环境实测(macOS / Linux 未验证,暂不承诺)。宿主侧代码没有平台相关的分支,但没跑过就是没跑过。
已知限制
- 没有远程执行:执行器跑在宿主进程里,机器关了就停。这是本机插件的结构性限制,不是待办 —— 「端休眠也照跑」需要云端,而这一版没有。
- 没有向量检索:记忆全部按文件分层进上下文,没有「容量超阈值自动切检索」。在当前规模下,引入 RAG 只会多一个更不可解释的层;代价是它有规模上限。
- 没有浏览器集成:DSH 自带的浏览器插件是会话级的,不是这个常驻实体的一部分。
- 没有语音、没有跨设备:本机单点。
- 没有专属邮箱入口:有 Telegram 与 HTTP 入站,但没有「转发邮件即派活」这种零成本入口。
- 自主时间的「逐条提示」只做了一半:敏感信息默认是被拒绝而不是被询问;「不回溯」在实现层面成立(改设置不会改动已有条目),但界面上没有把这句话说出来。
- MCP 只实现了客户端,而且是最小面:
initialize/tools/list/tools/call三件事。没有resources、没有prompts、没有订阅、没有 OAuth 流程(需要认证的服务请把 token 填进请求头字段)。长耗时任务没有走官方的tasks扩展。 - 只支持 streamable HTTP 的 MCP 传输:stdio 的服务需要用户自己套一层 HTTP。
- 入站连接的注入防御是限长与标注,不是内容过滤:公开记录对检测式防御很不客气(多数在攻击者适应后被绕过 90% 以上)。所以这里选了持续有效的两条:限制大小、标明来源。
- 审批的豁免只匹配完全相同的工具名:改一个参数就不算命中。这是保守的一侧,代价是同一类操作换个参数会再问一次。
bot_secret依赖虚拟桌面插件(dsh-vdesktop):没装时该工具会明确报错,而不是静默失败。- 没有现成的「会话内联操作」:所有管理都在设置页,聊天里只能通过
bot_*工具。
开发
这个仓库是纯 JavaScript,没有构建步骤 —— impl.js / client.js / entry.js 就是运行的东西。
# 离线验证套件(不需要 dsh 在跑)
node verify-bot-plugin.mjs
# 客户端接线检查(改了界面之后跑)
node scripts/check-client-wiring.mjs
# 对照调研报告,回归审计「已实现 / 未实现」
node scripts/audit-against-research.mjs
代码结构:
| 文件 | 职责 |
|---|---|
entry.js |
薄壳。stat() 实现文件的 mtime 并把它编进 import URL,于是改 impl.js 不必重启宿主。它导出的 inject 才是宿主读的那一份(见下) |
impl.js |
宿主全部逻辑:store、记忆文件层、工作区判定、执行器、审批、连接、MCP 客户端、路由、7 个工具 |
client.js |
Web 全部:侧边栏条目、bot 页面、设置页。自带样式,不依赖任何客户端包的内部类名 |
scripts/ |
两个检查脚本 + 一个可跑的 MCP 示范服务 + 虚拟桌面探针 |
tests/ |
端到端验证(HTTP 路由 + store 语义 + 工具行为) |
一个踩过的坑:Cordis 读的是 entry 模块导出的
inject,不是实现文件里的那一份。两者不一致时,插件会在缺服务的情况下启动,然后在第一次用到时报「cannot get property … without inject」。entry.js与impl.js的inject必须逐字一致,验证套件里有一条断言守着这件事。
更新记录
完整明细见 CHANGELOG.md。本插件还没有版本化发布,下面是开发轮次。
| 轮次 | 内容 |
|---|---|
| 第一轮 | 落地第一版:store、实例与类型、任务队列、执行器、侧边栏条目、bot 页面、设置页 |
| 第二轮 | 记忆改成文件:.md 文件树 + frontmatter、根文件常驻、子目录只贡献描述、「从文件重新导入」 |
| 第三轮 | 可治理性:来源标签(user / agent / tool)、时效与陈旧标记、敏感信息两道门、硬门永不放开 |
| 第四轮 | 审批链条:awaiting 一等状态、停下时展示工具与完整参数、waiver 带过期、修掉「批准后重跑再次拦下」的死循环 |
| 第五轮 | 限额全部可调:去掉所有写死的配额,默认值收敛到一处;UI 去掉一切非交互元素的边框 |
| 第六轮 | 自主时间改为理由驱动:空闲降为前置条件,4 个可检查条件,找不到理由就明说 |
| 第七轮 | MCP 客户端:streamable HTTP + 惰性工具名、用户自填地址、测试按钮与三态状态灯;用独立进程的真 server 端到端验证 |
| 第八轮 | 周期工作两种语义:continue 带上次结论 / fresh 从零开始 |
| 第九轮 | 界面收口:侧边栏条目宽度与右对齐修正(:has() 撑开两层)、输入框改成与 DSH 同形的卡片(共用同一根宽度轴)、头像可由用户上传、类型可编辑 |
特别感谢
特别感谢 DeepSeek Harness 原始仓库 与 DeepSeek AI 团队:本插件的插件体系、工具运行时与模型接口都构建在这个项目之上。
同时感谢 Cordis 提供的插件化基础。
本插件的调研工作参考了 2026 年主流个人助理与 Agent 产品的公开文档,逐条对照结果见功能对照。
License
本项目遵循 MIT License。
本项目是 DeepSeek Harness 的社区插件,并非 DeepSeek 官方产品。
还没有评论,来写第一条。