dsh-plugin-subagent-roster
为 DeepSeek Harness 增加一套受约束的子代理名册:每个角色都被固定了系统提示词、能力范围和模型档位,并且「大量重复性任务」与「团队分工任务」走不同的工具形状。
这个插件解决什么
DSH 内置的 subagent 工具让子代理继承父代理的身份与全部工具。真实的委派有两个问题:
- 身份不收敛:子代理会带着父代理的人设去做一件很窄的事,输出格式随缘。
- 能力不收敛:你只想让它读文件,它却有 shell;你让它评审,它顺手把代码改了。
- 模型不收敛:批量任务和关键决策跑在同一个(往往是最贵的)模型上。
本插件把这三件事从「提示词请求」变成结构约束:
| 约束 | 机制 | 效果 |
|---|---|---|
| 系统提示词 | 每次委派把角色 persona 放进请求,注入子代理的 persona-prefix 段落 |
子代理身份由角色决定,父代理身份不泄漏 |
| 能力范围 | 请求里的 toolFilter.allow 精确列出可用工具 |
评审角色没有写文件的工具,想改也改不了 |
| 模型档位 | 请求里的 agentOptions 固定 provider/model/maxTokens |
批量档便宜、评审档够用、团队档最强,各自独立可换 |
| 委派深度 | maxDepth: 1 且工具过滤从不授予 subagent* |
角色子代理是叶子,不能无限递归 |
两条任务线
- 批量线:一次一条、并行发起、子代理没有任何工具。适合 20 条数据的字段抽取、逐条校验、逐条改写。
- 团队线:规划、实现、评审、检索、成稿,每个角色能力范围不同,子代理之间不可互换。
完整的 20 个角色见 角色手册(English)。父代理只花一个工具 schema 的成本,而不是二十个。
安装
# 从 GitHub 安装(源码即产物,无需构建授权)
dsh plugin --profile <你的 profile> add github:/dsh-plugin-subagent-roster
# 或从本地 checkout 安装
dsh plugin --profile add /path/to/dsh-plugin-subagent-roster
安装后组合层自动生效(只挂一行),父代理会多出一个 delegate 工具,其 role 枚举就是 20 个角色。dsh --profile --dump-config 应能看到 subagent-roster 一行。
操作页面(自己设置角色)
profile 启动后,插件在本机回环起一个页面:
http://127.0.0.1:4317/
可以增删角色、改岗位/性格/档位/能力范围、直接编辑每个角色的 persona(子代理的系统提示词),保存即生效,无需重启(页面保存时会替换工具注册与分流段落,失败会回滚到上一版)。
角色数据在 $DSH_HOME/subagent-roster/roles.json(首次启动由内置 20 个角色播种),也可以手动编辑该文件。
- 端口由插件配置
pagePort控制,设为0关闭。 - 无鉴权:只绑定
127.0.0.1,权限等价于本机 shell。不要把它暴露到别的网卡上。 - 保存前会整体校验:id 必须 kebab-case、档位/能力/形态必须是已知值、能力范围与角色定位冲突(例如评审角色带写权限)会被拒绝,且不会覆盖已有文件。
确定性入口(不靠模型判断该不该委派)
实测表明:让父模型自己决定「要不要委派」在免费模型上不可靠(见测试报告第 3 节)。所以把判断挪到入口——按条目数直接驱动:
node bin/roster-fanout.mjs \
--profile <你的 profile> \
--role batch-exact \
--items-file items.json \
--contract '单个 JSON 对象 {"text": <条目原文>}' \
--expect-json \
--concurrency 3 \
--out results.jsonl
- N 条输入 → N 个该角色的子代理,形态由调用方式决定,与模型心情无关
- 每条答案是从子代理的
tool_result事件里直接取的,不经过父代理转述 --expect-json会校验契约;子代理报错/空输出/不合法 JSON 都判为失败- 任一失败退出码非 0,可直接用于 CI 或脚本编排
--item alpha --item beta可代替--items-file
> 契约由 --expect-json 硬校验,且契约文本会和条目一起传给子代理(否则它会看不到要求)。实测 8/8 合规,用的是最便宜的批量档模型。校验失败时不会把裸文本当成功返回。
接入插件市场(官方索引格式)
本仓库自带一份符合 DSH 插件市场 format: 1 的索引,已用官方校验器
@deepseek-ai/dsh-plugin-market-index 验证通过,可直接作为索引源订阅:
https://121212165.github.io/dsh-plugin-subagent-roster/market/index.json
添加方式:插件 → 发现 → 添加索引源,粘贴上面的 URL(需先在「实验性插件」里打开「自定义插件市场」)。
索引里只有一个版本,来源是固定 commit 的 git(24f55f2),所以确认框里显示的就是
装上去的那一版,不会随分支变动。
仓库同时带有 dsh-plugin topic,按 topic 抓取的社区聚合站(awesome-dsh-plugin 等)会在
下一次抓取时收录。
配置模型档位
组合里的模型 id 全部从环境变量解析,因此同一份包可以服务不同部署:
| 变量 | 作用 |
|---|---|
ROSTER_PROVIDER |
四个档位共用的 provider 路由名 |
ROSTER_BATCH_MODEL / ROSTER_BUILD_MODEL / ROSTER_REVIEW_MODEL / ROSTER_TEAM_MODEL |
各档位模型 id |
ROSTER_BATCH_MAX_TOKENS 等 |
各档位输出上限 |
也可以在 profile 的 cordis.patch.yml 里按 id 覆盖任意一行(例如只改 roster-builder-surgical 的模型)。
插件设置
| 字段 | 默认 | 含义 |
|---|---|---|
mode |
advisory |
advisory 只告警;strict 在名册自相矛盾时拒绝加载 |
provider |
deepseek-official |
档位解析所用 provider |
allowedModels |
[] |
非空时,任何解析到名单外路由的档位都会被视为违规 |
routingGuidance |
true |
是否向父代理注册「批量 vs 团队」的分流说明段落 |
验证
npm test # 18 项单元测试,0 次模型调用
node bench/run.mjs --repeat 1 # 真实调用测试(需要本地 OpenAI 兼容网关)
真实测试的判定全部来自网关请求日志,而不是回答文本:子代理 persona 是否命中、模型是否等于档位模型、可用工具数是否等于角色授权数、负向用例是否真的没有改动工作区。
- 设计说明:docs/design.md
- 测试报告:docs/test-report.md
- 审核报告:docs/review.md
兼容性
- DSH
>=0.2.0-rc.2 <0.3.0 - Node
>=22.18 - 纯 ESM JavaScript 产物,无构建步骤
社区
本项目认可并链接 LINUX DO 社区。
License
MIT