DeepSeek Harness 职业技能树
把“职业 + 公共技能树 + 职业核心技能树 + 技能点 + 加点”变成 DeepSeek Harness 的可执行能力预算系统。
共享目录
└─ 公共技能树定义(所有职业都可加)
职业
├─ 单一技能点钱包
├─ 该职业的公共树 Build
└─ 该职业的多棵核心技能树 Build这里的“公共”只表示节点定义向所有职业开放,不表示存在一份全局共享的公共加点结果:
- 每个职业都在同一份公共技能树定义上独立加点。
- 每个职业的公共加点和核心加点共同消耗该职业的一个钱包。
- 切换职业时,目标职业的公共 Build 与核心 Build 一起生效。
- 其他职业的两层 Build 和钱包继续持久化,但不产生实时效果。
例如,software-engineer 可以在公共树点出 Planning,而 researcher 在同一公共树点出 Evidence。切到 Researcher 后,不会继承 Engineer 的 Planning 加点。
技能点不是模型自己打分的经验值,而是人或外部评估根据证据授予的稀缺预算。“加点”也不只是修改 UI 数字,它会改变 Harness 的实时组成:
| 节点效果 | 加点后的真实行为 |
|---|---|
skills | 动态注册或卸载运行时 Skill |
plugins | 动态挂载或销毁 Cordis 插件 Fiber |
tools | 在执行边界按当前职业的公共/核心加点解锁已有工具 |
安装
当前版本面向 @deepseek-ai/dsh@0.1.0-rc.6(DeepSeek Harness 仍处于 Developer Preview)。
dsh plugin --profile <profile> add ./dsh-plugin-skill-tree-0.7.2.tgz
dsh --profile <profile> --dump-config
dsh --profile <profile>也可以从源码目录安装:
npm install
npm test
dsh plugin --profile <profile> add .默认 Bundle 包含:
- 一份所有职业可用的 General Work 公共技能树。
- 14 个预制职业,每个职业两棵核心树(
software-engineer、ai-video-artist三棵):
- 通用底座:software-engineer、researcher - 创意类:artist(视觉艺术家)、lyricist(作词人)、composer(作曲人)、screenwriter(编剧)、novelist(小说作家) - AI 创作类:ai-video-artist(AI 视频艺术家)、ai-image-artist(AI 绘画艺术家) - 影像类:photographer(摄影师)、film-director(导演) - 生活与知识类:chef(厨师)、teacher(教师)、translator(翻译)
- 每个职业开箱即可工作:公共层 3 点 + 全部一阶核心节点已满级分配;高级节点带
requiresCareerLevel: 2门槛、初始锁定,钱包预留 3–4 点,经skill_tree_advance_career审批升级后解锁。
默认节点只注册运行时 Skill,不会替你锁定现有工具。
模型可用工具
| 工具 | 作用 | 是否改变状态 |
|---|---|---|
skill_tree_status | 查看某职业的钱包和 public 或 core 层 | 否 |
skill_tree_skills | 按 category 跨职业浏览和检索所有技能 | 否 |
skill_tree_ledger | 增量读取哈希链账本(since/limit) | 否 |
skill_tree_plan | 模拟某职业一层 Build,校验两层合计预算 | 否 |
skill_tree_allocate | 提升某职业公共或核心层中的一个节点 | 是,需批准 |
skill_tree_respec | 完整重构某职业的一层 Build | 是,需批准 |
skill_tree_grant_points | 根据证据向指定职业的统一钱包授点 | 是,需批准 |
skill_tree_advance_career | 提升某职业的职业等级,解锁更高级节点 | 是,需批准 |
skill_tree_switch_profession | 一起切换当前职业的公共与核心 Build | 是,需批准 |
skill_tree_save_build | 把某职业当前 Build 保存到命名槽位(每职业最多 8 个) | 是,需批准 |
skill_tree_load_build | 把槽位恢复为实时 Build,两层一次性事务切换 | 是,需批准 |
skill_tree_delete_build | 删除一个槽位;实时 Build 与钱包不变 | 是,需批准 |
插件支持中文别名:配置里的 alias(默认 技能树)会出现在 skill_tree_status 和 skill_tree_skills 输出的 plugin.alias 字段,以及所有工具调用卡片的人读标题(如「读取技能树:当前职业的核心层 Build」)。
读写公共层时传 layer: public;省略 layer 时默认为 core。所有变更必须携带最新的全局 expected_revision,旧修订会被拒绝,以免加点、授点和转职相互覆盖。
skill_tree_skills 是只读的全目录技能索引。不带任何过滤参数时,列出每个 category 及其技能数量;传 category 列出某一类(或 "(uncategorized)" 查未分类),传 query 对技能名和描述做不区分大小写的检索,传 active_only 只看当前激活职业 Build 下生效的技能。技能可带一个可选的 category(小写标识符,如 prompt-engineering);未填的技能归入未分类。
Web 面板
在 web profile 下,插件会通过 webServer 服务注册会话视图和对应的 HTTP 端点:
- 职业面板:所有职业的钱包、加点概况和当前激活标记;点击非当前职业卡片上的按钮即可切换,走与模型工具相同的事务、修订校验和账本。浏览器请求返回可交互 HTML 页面。
- 技能树面板:按职业、按公共/核心层查看完整 Build、节点等级、下一级成本和阻塞原因。浏览器请求返回可交互 HTML 页面。
- 技能目录面板:跨职业按
category分组浏览所有技能,支持关键词检索和"只看当前生效"过滤。浏览器请求(Accept: text/html)返回可交互 HTML 页面,API 请求返回 JSON。
| 端点 | 作用 |
|---|---|
GET /skill-tree/status?layer=&profession=&tree= | 读取状态视图,与 skill_tree_status 工具同构 |
GET /skill-tree/skills?category=&query=&active_only= | 读取技能目录索引,与 skill_tree_skills 工具同构 |
GET /skill-tree/ledger?since=&limit= | 面向外部聚合器的增量账本流,与 skill_tree_ledger 工具同构 |
POST /skill-tree/switch-profession | 切换当前职业;必须携带 x-skill-tree-client 自定义头,跨域网页无法伪造该头,因此只有同源面板能调用 |
CLI/TUI profile 没有 webServer 服务时,端点与面板自动不挂载。
配置模型
config:
stateFile: !!js dshHomePath('skill-tree', 'professions-v3.json')
catalogId: my-agent-professions
catalogVersion: 1
initialProfession: software-engineer
maxGrantPoints: 20
# 定义共享;每个职业的 allocation 不共享
public:
title: Public Skills
trees:
- id: general
nodes:
- id: foundation
costs: [0]
- id: planning
costs: [1]
requires:
- node: foundation
skills:
- name: public-planning
description: Plan around observable outcomes.
content: State the outcome, constraints, verification, and rollback before acting.
professions:
- id: software-engineer
title: Software Engineer
initialPoints: 4
initialPublicAllocations:
general:
foundation: 1
planning: 1
initialCoreAllocations:
delivery:
foundation: 1
coreTrees:
- id: delivery
nodes:
- id: foundation
costs: [0]
- id: implementation
costs: [1, 2]
requires:
- node: foundation
- scope: public
tree: general
node: planning
plugins:
- module: '@acme/dsh-delivery-plugin'
config:
strict: true
tools:
- name: bash
- id: reliability
nodes:
- id: recovery
costs: [2]
requires:
- tree: delivery
node: implementation
level: 1关键字段:
public.trees:所有职业都能选择加点的共享定义。professions[].initialPoints:该职业唯一钱包的初始总点数。professions[].initialPublicAllocations:该职业在公共树上的初始 Build。professions[].initialCoreAllocations:该职业在核心树上的初始 Build。professions[].coreTrees:该职业专属的一棵或多棵核心树。costs:逐级增量成本;[1, 2]表示 1 级花 1 点,升到 2 级再花 2 点。requires:达到atLevel时要求另一节点至少达到level。核心节点可依赖本职业其他核心树,或用scope: public依赖公共树。excludes:只允许同层互斥,不跨公共/核心边界。skills、plugins、tools:节点达到atLevel后产生的运行时效果。
公共节点不能依赖某个职业的核心节点,因为公共定义必须对所有职业成立。核心节点不能跨职业依赖。
更多示例:
- [
examples/crawler-engineer.patch.yml](examples/crawler-engineer.patch.yml):公共 Engineering 树 + Crawler Engineer 三棵核心树。 - [
examples/coding-tree.patch.yml](examples/coding-tree.patch.yml):两个职业在同一公共工具树上的不同加点,以及职业核心工具门控。
工具名称必须与实际 Harness 工具名完全一致。复制门控示例前,先运行 dsh --profile <profile> --dump-config 核对。
职业切换语义
假设 Engineer 与 Researcher 在同一公共定义上采用不同加点:
1. 两个职业各自的钱包、公共 Build 和核心 Build 都保存在状态文件中。 2. Engineer 激活时,只有 Engineer 的公共节点效果和核心节点效果生效。 3. 经批准切换到 Researcher 后,系统暂存 Researcher 的两层效果。 4. 新效果全部进入 ACTIVE 后,卸载 Engineer 不再需要的效果并原子保存状态。 5. 两个职业恰好都点出的同一公共节点可复用现有 Fiber;这只是运行时差分优化,不代表分配共享。 6. 任一步失败,则清理新效果并恢复原职业的完整两层 Build。
当前一次只激活一个职业。多职业混合、主副职业和职业等级属于后续 Career Graph。
预算与依赖不变量
对职业 p:
$$ Cost(PublicBuild_p) + Cost(CoreBuild_p) \le Points_p $$
修改公共层时,会同时验证该职业现有核心 Build 的公共前置;不会扫描或改变其他职业的 Build。因此一个职业洗掉自己的公共 Planning 可能被自己的核心 Implementation 阻止,但不受另一个职业如何加点影响。
事务与安全
每次授点、加点、洗点或转职都会:
1. 在文件锁中读取磁盘最新状态并验证完整哈希链。 2. 用 expected_revision 做 compare-and-set。 3. 校验职业统一钱包、公共/核心前置、跨核心树前置、互斥和总预算。 4. 对当前职业的实时效果执行可回滚的 Cordis 生命周期事务。 5. 以 0600 权限原子保存状态,并写入含完整职业 Build 快照的账本项。
哈希链能发现意外修改或简单篡改,但没有密钥签名,不能对抗能重写完整文件和整条链的攻击者。
重要边界
- 目录现在支持职业等级(Career Level)。每个职业有
initialCareerLevel(默认 1)和maxCareerLevel(默认 5);skill_tree_advance_career通过审批提升某职业等级。节点可声明requiresCareerLevel——在该职业达到该等级前分配会被阻塞,产生insufficient-career-level阻塞。升级不改点数与当前 Build,只解锁分配权限。 - 0.7 使用状态 schema v5;不会静默读取 schema v4 的状态——v5 为每个职业新增
careerLevel(以及 v4 的buildSlots)。请使用新的stateFile,或显式迁移。 skill_tree_grant_points支持可选的verification对象(kind、reference、可选 64 位十六进制digest),把授点绑定到不可变评测结果并写入哈希链账本。- 当前钱包是 profile 级,不是每个子 Agent 一套职业目录。
- 已有工具仍可能出现在模型看到的 schema 中,但执行会按当前职业的公共与核心加点拒绝;需要 schema 消失时,应把能力封装成
plugins效果。 - 多进程共享状态文件时写入有锁,但实时效果在下一次调用技能树工具时惰性同步。
- 插件不自动判断“完成任务就奖励点数”。授点必须由人或外部 verifier 的证据批准,避免自证、自奖、自解锁。
- 修改定义后必须提升
catalogVersion并迁移状态,或选择新的stateFile。 - DeepSeek Harness 仍是 Developer Preview,后续 RC 可能需要适配 API。
完整模型见 [DESIGN.zh.md](DESIGN.zh.md)。Harness 背景见官方 Architecture 与 Plugin lifecycle。
开发
npm test
npm run pack:check测试覆盖公共定义共享、按职业隔离的公共加点、公共/核心合并预算、跨层前置、跨核心树循环、互斥、工具门控、两层职业切换、持久化账本和运行时回滚。
MIT License。