dsh-qq-bot
把 QQ 接到 DSH Agent 的插件:通过 NapCat 等 OneBot 11 实现收发消息,每个 QQ 会话对应一个 DSH Agent。 适合需要将QQ群聊或私聊作为智能体交互渠道的开发者。
Other repositories with this package name
Install
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:arrow1031/dsh-qq-botREADME
Read the full README ↗四、配置
方式一:在 DSH 设置里改(推荐)
重启 dsh web 后,打开 设置 → QQ 机器人,所有配置都在这一个选项卡里:
连接方式、WS/HTTP 地址、access_token、群聊开关与 @ 要求、白名单、命令前缀、
回复分片长度、慢回复提示、来源前缀、每会话独立、preset、工作目录、逐帧日志。
- 改完点「保存」;连接方式那几项(模式/地址/token)保存后会自动重启适配器,其它项下一条消息生效。
- 类型映射:布尔是勾选框;白名单是逗号分隔的文本框;连接方式是下拉框。
- 配置分两层:composition 行配置是 base 层,设置面板里改的是 用户层(存在
$DSH_HOME的设置文档里)。 - 连接状态不在设置页里显示,在对话里让 Agent 调用
qqbot工具(action=status)看。 access_token是只写字段:已设置时页面显示「已设置;留空则保持不变」,只有输入新值才会覆盖。 Host 侧把它声明成 schema 的 secret,值不会下发到浏览器,保存时也不会被空值清掉。
方式二:改 composition 行配置(当 base 层用)
不要改包内的 cordis.patch.yml(升级会覆盖)。写进你自己的
$DSH_HOME/profiles/web/cordis.patch.yml —— 它在所有 bundle 之后应用,按 id 定向覆盖:
- id: dsh-qq-bot
config:
mode: forward # forward | reverse
workspace: '/home/dsh' # 每个 QQ 会话 Agent 的工作目录
onebot:
wsUrl: 'ws://127.0.0.1:3001' # mode=forward 用
listen: '0.0.0.0:6199' # mode=reverse 用
httpUrl: 'http://127.0.0.1:3000' # 留空则改用 WS action 发消息
accessToken: ''
group:
enabled: true
requireAt: true # 群里是否必须 @
allow: [] # 群号白名单,空数组 = 所有群
private:
enabled: true
allow: [] # 用户号白名单,空数组 = 所有人
commandPrefix: '' # 例如 '/ai',空串 = 不限制
reply:
maxChars: 1200
ackAfterMs: 8000 # 慢回合先回「正在处理」;0 关闭
ackText: '正在处理,请稍候…'
contextHeader: true # 给消息加 "[QQ群 123 · 小明(22222)]" 前缀
firstTurnHint: '(提示:这是一次 QQ 聊天。请用简体中文、简洁自然的口语作答;不要输出 Markdown 表格,代码块保持简短。)'
auth: # 权限,见「五、权限与群管理」
owners: [] # 拥有者 QQ:全权限 + 永久授权 + 可走独立会话
superAdmins: [] # 后台设定的高级管理员(不可永久授权)
ownerPreset: '' # 填了才把拥有者/非拥有者分成两条会话
guestPreset: '' # 非拥有者用的 preset(仅人格分离,非安全边界)
guestDshTools: false # 是否允许访客用 DSH 内部工具(默认否)
guestToolAllow: ['qqbot', 'qqgroup'] # 访客仍可用的工具白名单
grantTtlMinutes: 60 # 群管理员动态授权默认时长
grantMaxTtlMinutes: 1440 # 群管理员单次可授最长
admin:
enabled: true
manageGroups: [] # 可管理的群;空 = 回退用 group.allow
requireGroupAdmin: true # 是否承认「本群管理员」这一路权限
prefix: '/' # 指令前缀(必须在消息首位)
dryRun: false # true = 只回复将执行什么
allowConsole: false # 允许 Web UI 会话直接调用管理工具
perChatSession: true # true=每个 QQ 会话一个 DSH 会话
agentPreset: '' # ''=部署默认 preset;可填自定义 preset id 换人格/工具
adapterPath: '' # ''=用包内自带适配器
nodePath: '' # ''=自动解析 node
logAdapterFrames: false # 排查时开,会打印每一帧 JSON
agentPreset 是换人格的正规做法:给 QQ 机器人做一个专属 preset,把 id 填进来。
方式二:改 composition 行配置(当 base 层用)
不要改包内的 cordis.patch.yml(升级会覆盖)。写进你自己的
$DSH_HOME/profiles/web/cordis.patch.yml —— 它在所有 bundle 之后应用,按 id 定向覆盖:
- id: dsh-qq-bot
config:
mode: forward # forward | reverse
workspace: '/home/dsh' # 每个 QQ 会话 Agent 的工作目录
onebot:
wsUrl: 'ws://127.0.0.1:3001' # mode=forward 用
listen: '0.0.0.0:6199' # mode=reverse 用
httpUrl: 'http://127.0.0.1:3000' # 留空则改用 WS action 发消息
accessToken: ''
group:
enabled: true
requireAt: true # 群里是否必须 @
allow: [] # 群号白名单,空数组 = 所有群
private:
enabled: true
allow: [] # 用户号白名单,空数组 = 所有人
commandPrefix: '' # 例如 '/ai',空串 = 不限制
reply:
maxChars: 1200
ackAfterMs: 8000 # 慢回合先回「正在处理」;0 关闭
ackText: '正在处理,请稍候…'
contextHeader: true # 给消息加 "[QQ群 123 · 小明(22222)]" 前缀
firstTurnHint: '(提示:这是一次 QQ 聊天。请用简体中文、简洁自然的口语作答;不要输出 Markdown 表格,代码块保持简短。)'
auth: # 权限,见「五、权限与群管理」
owners: [] # 拥有者 QQ:全权限 + 永久授权 + 可走独立会话
superAdmins: [] # 后台设定的高级管理员(不可永久授权)
ownerPreset: '' # 填了才把拥有者/非拥有者分成两条会话
guestPreset: '' # 非拥有者用的 preset(仅人格分离,非安全边界)
guestDshTools: false # 是否允许访客用 DSH 内部工具(默认否)
guestToolAllow: ['qqbot', 'qqgroup'] # 访客仍可用的工具白名单
grantTtlMinutes: 60 # 群管理员动态授权默认时长
grantMaxTtlMinutes: 1440 # 群管理员单次可授最长
admin:
enabled: true
manageGroups: [] # 可管理的群;空 = 回退用 group.allow
requireGroupAdmin: true # 是否承认「本群管理员」这一路权限
prefix: '/' # 指令前缀(必须在消息首位)
dryRun: false # true = 只回复将执行什么
allowConsole: false # 允许 Web UI 会话直接调用管理工具
perChatSession: true # true=每个 QQ 会话一个 DSH 会话
agentPreset: '' # ''=部署默认 preset;可填自定义 preset id 换人格/工具
adapterPath: '' # ''=用包内自带适配器
nodePath: '' # ''=自动解析 node
logAdapterFrames: false # 排查时开,会打印每一帧 JSON
agentPreset 是换人格的正规做法:给 QQ 机器人做一个专属 preset,把 id 填进来。
非拥有者不使用 DSH 内部功能:执行级工具闸
用一个 tools.guard 硬闸,只在建会话时注册一次,判据是闭包里的可变标志位:
- 注册在
agent.ctx上 → 只作用于该会话的 agent - 每次工具执行时才求值 → 拥有者/访客交替说话不需要增删限制
- 用白名单(
auth.guestToolAllow,默认qqbot,qqgroup)→run_code(PTC 保留传输)这类"不在全局层"的特殊工具也会被自动挡住 - 被拦时返回拒绝原因,模型会把它转达给用户(最多多一次"被拒绝的调用"往返)
因此它同时满足:0 额外 token(不注入提示词、不改工具表、不记 request/header)、单会话单历史、不改 DSH 本身。
想放开就设 auth.guestDshTools: true(不建议)。
为什么不用"每条消息增删
tools.restrict":restrict是静态过滤器,想按说话人变就得反复增删,工具面抖动会让 agent loop 多记request/header,反而更费 token、代码也更多。guard 是每次执行才求值的函数,配一个可变标志位就够。