@stofone/dsh-agent-roster
Defines multi-agent team rosters as YAML or JSON files, validates them, bridges each member into dsh-agent-teams member arguments, and verifies the result against the running team.
Install
dsh plugin --profile web add @stofone/dsh-agent-roster
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
@stofone/dsh-agent-roster
[English](README.md) | 简体中文
面向多 Agent 团队的静态成员档案插件(DeepSeek Harness)。
一份档案就是磁盘上的文件:团队里有谁、各自负责什么、走哪个模型路由、被允许碰哪些工具。本插件定义这套格式、校验它,并把它翻译成 agent_teams_* 调用参数——它不运行团队。
它是什么 / 不是什么
是 · 不是
定义与校验层:格式可版本化、可评审,写错时带文件路径与字段路径报错,不静默降级 · 团队运行时:从不建成员、不调度任务、不替代调度器
对 dsh-agent-teams 的桥接:roster_create 产出可直接使用的建员参数,并逐字段标注运行时是否真的接收 · 不写 .agent-teams/ 状态:只读,用于核对
核对手段:roster_verify 读 team.json 里实际存下的值 · 不假装通过:证据源缺席时记「无法核对」
安装
前置:DSH 提供 tools 服务;Node.js ≥ 22.19。运行依赖已声明(yaml、@deepseek-ai/schemastery),@deepseek-ai/dsh-tools 是 peer。
@stofone/dsh-agent-roster
包内带 cordis.patch.yml,安装即把插件插进 profile。装好后应看到十一个工具(见「工具」)与左侧栏里的 Agent 档案 面板。
插件代码在 DSH 启动时加载:升级包后必须重启 dsh web,面板与工具才会是新的;只换 node_modules 不重启,运行中的宿主仍是旧版本。
快速开始
档案库默认是全局的:一台机器一份,不跟工作区走,位于 $DSH_HOME/agent-roster(默认 ~/.dsh/agent-roster;docker 下就是挂载的数据卷)。目录在第一次保存时自动创建。
v2 空间长这样:
~/.dsh/agent-roster/
├── space.yaml # 可选:把这座库登记成一个空间
├── roles/
│ └── core-review-lead/
│ └── AGENT.md # 角色 = 一个目录 + 一份 AGENT.md
├── rosters/
│ └── core-review/
│ ├── roster.yaml # 档案 = 成员清单 + 编排
│ └── capabilities.yaml # 可选:声明部署侧必须先提供什么
└── dist/
└── core-review-1.0.0.json # 编译产物(自包含)
npx dsh-agent-roster validate --dir examples # 校验示例库(v2) npx dsh-agent-roster list --dir examples # 列出档案与成员 npx dsh-agent-roster compile --roster examples/rosters/core-review # 只打印编译结果
本仓自带两座示例库:[examples/](./examples)(v2)与 [examples-orchestration/](./examples-orchestration)(v2,演示门与施工图)。
三种落盘形态
形态 · 目录特征 · 由谁产生
平铺库(v1) · <根>/<id>/roster.yaml · 手写、单份安装、老库
空间(v2) · <根>/roles/ + <根>/rosters/(+ 可选 snippets/、space.yaml) · 手写、migrate、clone
拉取副本 · 空间或平铺库 + .dsh-roster-origin.json(来源账本) · clone / 面板「拉取整个空间」
space.yaml 是可选的登记层:有它就有「声明了几份、实际几份、缺了谁、谁没登记」的核对;没有它,库仍按目录扫描,只是没有这层对账。收藏存在库根的 .dsh-roster-favorites.json(点文件,扫描器跳过)。
档案格式(v1,平铺库)
kind: dsh-agent-roster/v1
roster: core-review # 必须与所在目录名一致
version: 1.0.0 # 精确 SemVer
title: 核心评审组
description: 负责代码评审与发布把关的固定成员。
license: MIT
maintainers: [STofone]
tags: [review, release]
defaults: # 成员共享的路由默认值
provider: deepseek
model: deepseek-v4.1-flash
reasoningEffort: high
members:
- name: reviewer # kebab-case,团队内唯一
role: 代码评审
systemPrompt: |
你先找语义错误,再看风格。
toolPolicy: readonly
- name: release-manager
role: 发布把关
systemPrompt: |
你核对变更、版本号与回滚方案。
model: deepseek-v4.1-pro
captain: # 可选:记录队长(= 创建团队的那个会话)应该是什么样
name: lead
provider: tsingmicro
model: deepseek-v4.1-flash
personaPrefix: |
派活前先复述目标与验收标准。
键 · 必填 · 说明
kind · 是 · dsh-agent-roster/v1
roster · 是 · kebab-case id,必须等于目录名(位置即身份)
version · 是 · 精确 SemVer,不接受范围
title / description / license / maintainers / tags · 否 · 展示与检索元数据
defaults · 否 · 成员继承的 provider / model / reasoningEffort
members · 是 · 1–32 个
captain · 否 · 只描述、不创建;应用时人设会注入会话
成员键:name、role、systemPrompt(必填),以及 provider、model、reasoningEffort、toolPolicy、fallback、toolScope、maxTokens、title、tags、notes、description、aliases、skills、examples。
同一目录按 roster.yaml → roster.yml → roster.json 探测,只认一份;出现第二份是 error,绝不静默挑一份。未知键一律 error。
角色 → 档案 → 产物(v2)
角色 roles/<name>/AGENT.md
角色是「一个目录 + 一份精确命名为 AGENT.md 的文件」;目录可以嵌套(最多 3 层),但一个目录只能有一份角色。角色身份取 frontmatter 的 name,不是目录名;重名是 error。
--- kind: "dsh-agent-roster/role@1" name: "core-review-lead" version: "1.0.0" role: "队长" title: "编排与取舍" description: "编排这次审查、拆任务、合并结论;不写具体代码" tags: ["orchestration"] route: provider: "deepseek" model: "deepseek-v4.1-flash" reasoningEffort: "high" tools: policy: "read-only" requires: skills: ["frontend-skill"] ---
正文就是人设。prompt.parts 可以再拆若干片段,按顺序拼在正文之后;片段必须位于角色目录内(越界即 error)。
档案 rosters/<id>/roster.yaml
kind: dsh-agent-roster/roster@2
id: core-review
version: 1.0.0
title: 核心评审组
description: 一个小团队:队长拆任务,评审把关,修复收尾。
license: MIT
maintainers: [stofone]
tags: [review, example]
defaults:
route:
provider: deepseek
model: deepseek-v4.1-flash
reasoningEffort: high
targets: [agent-teams/members]
members:
- as: reviewer # 团队里的名字
role: reviewer@1.0.0 # 引用角色与精确版本
- as: fixer
role: fixer@1.0.0
prompt:
append: overrides/fixer.md # 成员级追加,拼在执行提示词末尾
captain:
role: lead@1.0.0
persona: captains/lead.md # 文件路径(相对档案目录),内容是队长人设
orchestration:
shape: gate-pipeline
stages:
- id: build
serial: [fixer]
- id: audit
parallel: [reviewer]
gates:
- id: tests-pass
after: [audit]
by: reviewer
requires: [现有测试全部通过]
verify:
- command: node --test
expectExit: 0
requires:
toolPolicies: [member-safe]
onMissing: refuse
档案级键:kind、id、version、title、description、license、maintainers、tags、defaults、targets、members、captain、orchestration、requires、onMissing、notes。
执行提示词只有一种拼法(lib/frontmatter.js#assemblePrompt):
executionPrompt = join("\n\n", [成员 prepend, 展开引用后的正文, ...prompt.parts, 成员 append])
预算口径按字符:正文 8000、单片段 6000、片段 16 个、展开后 12000、成员追加 6000。
编排与门
orchestration.stages 是阶段(serial / parallel 列表,可选 join、on、maxRounds),gates 是门(after、by、requires、verify)。
门没有可执行判据就是 error(gate-unverifiable):每条 verify 必须给出 command 与 expectExit(1–8 条)。能被机器跑的才算门,纯文字标准只能写进 requires 供人看。
编译产物
npx dsh-agent-roster compile --roster examples/rosters/core-review --write
dist/<id>-<version>.json(compiled@1):自包含,成员带executionPrompt、promptStats(字符数、逐段{path, kind, line?, sha256}、整体 sha256)与provenance;source里带发现元数据(标题、描述、标签、许可、维护者)。dist/<id>-<version>.tasks.json(plan@1):有编排时生
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::42,最后更新 2026-11-06