在这里插入图片描述

目录


1. 先建立正确预期

官方把 Agent 拆成一句公式:

Agent = Model + Harness

  • Model:负责推理、规划、生成工具调用
  • Harness:负责读文件、跑命令、管会话、做沙箱、调度子 Agent、把结果写回日志

DeepSeek Harness 的口号是 Everything is a Plugin(一切皆插件)
和常见 Coding Agent 的差别在于:

类型 你能改什么 典型产品感
成品 Coding Agent 外围 Skill / MCP / 少量 hooks 开箱即用,黑盒多
DeepSeek Harness 模型适配、工具、会话、沙箱、甚至 Agent Loop / UI 乐高底座,毛坯感更强

所以:

  • 想「打开就能写代码」→ 先用 标准模式,别一上来创造模式
  • 想「改运行时、写插件、做内部 Agent 平台」→ 这才是 dsh 的主场
  • 它目前是 开发者预览版,官方明确会有破坏性变更;适合学习、试点、自托管实验,不建议一上来绑生产关键路径

项目入口:

  • 官网:https://www.deepseek.com/harness/
  • 仓库:https://github.com/deepseek-ai/deepseek-harness
  • 文档站:https://deepseek-harness.github.io/deepseek-harness/

2. 30 分钟跑通:安装与首次配置

2.1 环境要求

  • Node.js:官方要求较新(实践中建议 22.19+24+
  • 操作系统:Linux / macOS / Windows 均可;涉及强沙箱能力时,Linux / WSL 更稳
  • 一个可用的 模型 API Key(默认 DeepSeek 开放平台)
  • 一个可丢弃的练习目录当工作区(别直接指向生产仓库)

先检查 Node:

node -v
npm -v

2.2 最快启动(推荐新手)

npx @deepseek-ai/dsh web

成功后本地 Web UI 默认在:

http://127.0.0.1:3080

首次会看到开发者预览声明,点继续即可。

2.3 源码方式(准备写插件时用)

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

源码方式的好处:能直接读 docs/、本地 --patch 插插件、对照 cookbook。

2.4 首次必做的 5 件事

  1. 填 API Key
    设置 → 模型;也可先设环境变量 DEEPSEEK_API_KEY 再启动。
  2. 选工作区
    例如:
mkdir DeepSeekProjects

在 UI 里把该目录加为 workspace。不选工作区,很多文件/命令能力等于没边界。
3. 选模型
Flash 适合轻任务;复杂多步规划更常上 Pro 档。
4. 选模式
新手直接 标准模式
5. 确认权限
日常推荐 workspace-write:只在工作区写文件,越界操作会触发审批。
danger-full-access 名字已经说明风险,练习阶段别开。

2.5 第一条验证任务

把下面丢给 Agent,验证「读盘 + 写文件 + 给预览说明」整条链路:

请在当前工作区创建一个简单待办网页:
1. 使用 HTML/CSS/JS
2. 可添加任务、勾选完成
3. 风格简洁,适配手机
4. 完成后列出生成文件,并说明如何本地打开预览

能稳定创建文件并解释结果,说明基础环境 OK。

2.6 Headless:塞进脚本/CI

dsh --profile headless "run the tests and summarize failures"

一次性跑完、打印最终答案后退出,适合批处理。


3. 四种模式怎么选(实战决策)

先记住一句:四种模式不是等级,而是四套插件模板(preset)
同一套 Harness 宿主,装入不同插件组合,就长成不同「形态」。

在这里插入图片描述

模式 你实际得到什么 什么时候用
标准 Standard 文件编辑、Shell、检索、Skills、计划、目标、子 Agent、工作流 日常开发、陌生任务探索
PTC / Code 标准能力 + Code Mode SDK:模型写 TypeScript,一次 run_code 组合多步工具 路径/参数已稳定的重复流程,想压缩工具往返
极简 Minimal 持久 Bash + 文件编辑器;提示词极短;少附加能力 模型基准对比、控制变量实验
创造 Creator 标准能力 + 检查 Cordis 运行时、内存试验插件、创作 preset 学插件系统、改装 Agent 自己

实战选型口诀

  1. 陌生任务 → 标准
  2. 流程已跑通、工具往返很碎 → 再试 PTC
  3. 只想比模型裸 Agent 能力 → 极简
  4. 要改装工具/预设 → 创造

PTC 的真实体感(避免踩预期坑)

  • PTC 不是「自动更快」:模型要先写出正确的编排程序
  • 路径规则写错(例如 Glob 写法不符合 SDK 约定)会空跑一轮
  • 第一次探索陌生仓库,多数人用标准更省心;稳定后把重复链路迁到 PTC 更划算

4. 「一切皆插件」落到工程上是什么

4.1 Cordis:只做三件事的内核

底层是 Cordis 插件框架。内核几乎不做业务,只负责:

  1. 加载 / 卸载插件
  2. inject 管理依赖
  3. 用可逆 effect 回收副作用

因此:

  • 模型适配器是插件
  • 工具注册表是插件
  • 会话日志是插件
  • Agent Loop 也是插件
  • Web UI 也是插件

扩展方式不是 fork 主仓库改 loop,而是:旁挂插件 + 订事件 + 改配置组合

4.2 运行中的 dsh = 一棵插件树

启动时从空配置开始,按层叠加:

  1. Profile 声明的 Bundles(如 dsh-basedsh-web-app
  2. Profile 自己的 cordis.patch.yml
  3. Home 级 $DSH_HOME/cordis.patch.yml
  4. 命令行 --patch overlay(最高优先,适合临时调试)

在这里插入图片描述

想看清本机真实装了什么:

dsh --profile web --dump-config

打印出来的每一行,理论上都能被你的 patch 按 id 替换。
注意:patch 是整行替换 config,不是深合并。只改一个字段时,别把其它必要字段覆盖丢了。

4.3 五个必须会的 Cordis 词

概念 实践含义
插件 导出 apply(ctx) 的模块(也可对象/类)
Context ctx 服务仓库:ctx.tools / ctx.llm / ctx.sessions
inject 硬依赖声明;服务没就绪就 PENDING,不瞎跑
effect 注册即带 disposer;卸载自动撤销
事件 扩展点:emit 观察、waterfall 拦截改写(记得 next()

4.4 能力 seam:为什么换一个 Provider 能搬整条链路

可替换能力通常拆三角色:

  1. Service Definition:接口与事件词汇(如 shell 能力定义)
  2. Service Provider:具体实现(本地 bash / 远程沙箱…)
  3. Consumer:面向模型的工具(dsh-tool-bash

你换 Provider,Consumer 仍调同一接口——这就是「一切皆插件」在工程上的可替换性,而不是只会在外围挂 MCP。

4.5 Session Log:模型可见 ⇔ 已记录

会话不是随便一份消息数组,而是 仅追加的事件日志
系统提示、工具调用、结果、注入上下文,最终都要能从日志重建。
Trajectory 视图就是这条事件流的「黑匣子回放」,排错极有用。


5. 实战:写一个模型可调用的工具插件

目标:做一个 greet 工具,让模型在对话里真正调用它。

在这里插入图片描述

以下路径假设你已 clone 源码仓库,并完成 pnpm install / pnpm run build

5.1 建临时插件目录

mkdir -p scratch-plugin/src

5.2 最小插件骨架(先证明能加载)

scratch-plugin/src/my-plugin.ts

import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello-plugin'

export function apply(ctx: Context) {
  console.log('[hello-plugin] plugin loaded!')
}

要点:

  • 函数插件请用具名导出 export function apply / export const inject
  • 不要「默认导出 + 具名 inject 混用」——Loader 可能丢掉 inject 元数据,表现为「装上了但不依赖、行为诡异」

5.3 用 patch 插入本地插件

先在仓库根目录拿到绝对路径,再写 scratch-plugin/cordis.yml

- insert:
    - id: hello
      name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'

启动:

pnpm dsh web --patch ./scratch-plugin/cordis.yml

终端出现 [hello-plugin] plugin loaded! 即挂载成功。

5.4 升级为真正的 Tool

替换为:

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'greet-tool'
export const inject = ['tools']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'greet',
    description: 'Greet someone by name. Use when the user asks to greet.',
    parameters: {
      name: {
        type: 'string',
        required: true,
        description: 'The name to greet',
      },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args) {
      return `Hello, ${args.name}!`
    },
  }))
}

重启同样的 --patch 命令,在 Web UI 说:

请使用 greet 工具问候 Ada

模型应发起 greet,并拿到 Hello, Ada!

5.5 这段代码为什么「像官方」

  1. inject: ['tools']
    保证 ctx.tools 就绪后再 apply
  2. defineTool
    参数 schema 自动校验;execute 里拿到的 args 与 schema 一致。
  3. 只返回规范值
    output.schema 声明返回形态;render 负责变成模型可见文本。
  4. 注册可逆
    register 附着在插件 fiber 上,卸载/HMR 时工具会从注册表消失。
  5. schema 自动进提示词组装
    模型「看得到」这个工具,不需要你手写进 system prompt。

5.6 给插件加可配置项(部署期参数)

可调参数不要写死,做成 Config:

import type { Context } from '@deepseek-ai/cordis'
import Schema from '@deepseek-ai/schemastery'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'greet-tool'
export const inject = ['tools']

export interface Config {
  greeting: string
}

export const Config: Schema<Config> = Schema.object({
  greeting: Schema.string().default('Hello'),
})

export function apply(ctx: Context, config: Config) {
  ctx.tools.register(defineTool({
    name: 'greet',
    description: 'Greet someone by name.',
    parameters: {
      name: { type: 'string', required: true, description: 'The name to greet' },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args) {
      return `${config.greeting}, ${args.name}!`
    },
  }))
}

在 patch 行里带 config.greeting,即可不改代码切换文案。
配置非法应在加载期直接失败(fail loud),不要运行时静默怪行为。

5.7 需要外部资源时:ctx.effect

定时器、连接池等必须留下 disposer:

export function apply(ctx: Context) {
  ctx.effect(() => {
    const timer = setInterval(() => {
      console.log('heartbeat')
    }, 5000)
    return () => clearInterval(timer)
  })
}

插件卸载、依赖服务消失、HMR 重载时,清理函数会按栈逆序执行。

5.8 进阶:用事件做权限门(钩子插件)

不新增工具、只想拦截调用时,挂 tools/pre-execute

import type { Context } from '@deepseek-ai/cordis'
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools'

async function isAllowed(_exec: ToolExecution): Promise<boolean> {
  return true
}

export const name = 'permission-gate'

export function apply(ctx: Context) {
  ctx.on('tools/pre-execute', async (exec, next): Promise<PreToolDecision> => {
    if (!(await isAllowed(exec))) {
      return { kind: 'deny', reason: 'Denied by local policy.' }
    }
    return next()
  })
}

waterfall 铁律:要放行必须 next()。忘记调用 = 整条链被你短路。


6. 挂载、安装与调试清单

6.1 三条挂载路径

路径 适用 做法
临时 overlay 本地调试、演示 dsh web --patch ./overlay.yml
外置插件包 自研可分发 `dsh plugin --profile web add <path
仓库内正式包 给 dsh 本体贡献 packages/<group>/<pkg> + cookbook 清单

安装示例:

dsh plugin --profile web add ./hello-plugin
dsh plugin --profile web add github:some-org/my-plugin
dsh plugin --profile web remove my-plugin

社区发现标签:GitHub topic dsh-plugin

6.2 正式函数插件的「四导出」

养成肌肉记忆:

export const name = 'my-plugin'          // 诊断名
export const inject = ['tools']          // 硬依赖
export const Config = /* schemastery */  // 可选
export function apply(ctx, config) {}    // 唯一副作用入口

6.3 插件三种形态怎么选

  1. 函数:大多数工具/钩子够用
  2. 对象:需要附带字段时
  3. extends Service:你要 对外提供 ctx.xxx 服务时

6.4 Host 平面 vs Agent preset 平面(高频概念坑)

  • boot profile(如 web / headless):启动哪棵宿主插件树
  • agent preset(标准/PTC/极简/创造):这个会话装哪些工具与人格

不要对 CLI 写 dsh --profile standard——standard 通常是 preset,不是 boot profile。
另外:preset 里若发布服务,注意 isolate realm,否则多会话同名服务可能撞车;纯消费 tools 的工具行,很多场景应平铺在顶层,而不是错误包进空 isolate。

6.5 社区插件怎么用(实践向)

常见增强方向:

  • @ 文件引用(减少模型反复扫目录)
  • 更好的侧边栏/工作台 UI
  • 视觉能力补充
  • 插件市场/发现器

安装后按插件 README 重启 profile,再在「设置 → 插件」确认启用。
插件=可执行代码:看 README、看权限、看维护活跃度,固定版本更稳妥。


7. 权限、轨迹与日常工作流

7.1 权限三档(先安全后爽)

级别 含义 建议
Read Only 只读工作区 审计/讲解代码
Workspace Write 工作区内读写 + 受限命令 日常默认
Full access 宽权限 仅明确需要且可回滚环境

越界写文件时,好的体验应是:沙箱拒绝 → UI 弹出升级/单次允许 → 轨迹里留痕。

7.2 用 Trajectory 排错

任务失败别只看最终一句话,打开轨迹检查:

  • 模型本轮到底看到了哪些工具
  • 哪一次 tool 参数错了
  • 是否被 pre-execute 拒绝
  • 是否在错误路径上空转

这是 dsh 相对「只给最终答案」的产品,对开发者最值钱的部分之一。

7.3 建议的日常节奏

  1. 练习目录 + 标准模式 + workspace-write
  2. 先让 Agent 完成小任务,确认权限与模型 OK
  3. 缺能力 → 先搜社区插件,再考虑自写
  4. 自写 → --patch 验证 → 再 plugin add 固化
  5. 重复链路稳定后,再评估 PTC 是否值得

7.4 多模型

Harness 模型无关:设置里可添加其它提供方或 OpenAI 兼容端点。
实践建议:同一任务固定「模型 + preset + 权限」再对比,否则变量太多得不出结论。


8. 常见坑与排错表

现象 优先检查
插件「没反应」 模块路径/包名拼写;解析失败可能只打日志不崩
有代码但模型看不到工具 是否 inject: ['tools'];是否被 preset scope / restrict 滤掉
apply 一启动就挂 设计如此:加载失败 fail loud,查依赖与 Config schema
patch 改了无效 是否按 id 命中;是否整行 config 覆盖丢字段
waterfall 逻辑怪 是否忘记 next()
HMR 后残留监听/工具 是否裸写全局副作用,而不是 ctx.on / register / effect
--profile standard 报不存在 分清 boot profile 与 agent preset
Windows 沙箱不稳 优先 WSL/Linux 路径做强隔离实验
git 安装插件缺 lib/ 作者需 prepare 构建;pnpm≥10 可能要 allowBuilds

官方开发文档入口:

  • 第一个插件:https://deepseek-harness.github.io/deepseek-harness/develop/basic/
  • 架构参考:https://deepseek-harness.github.io/deepseek-harness/reference/
  • Cordis 教程:https://deepseek-harness.github.io/deepseek-harness/develop/cordis-tutorial/

9. 总结与下一步

  1. dsh 是 Agent 运行时底座,不是对标某成品 Code 助手的换皮。
  2. 一切皆插件 = 无特权内核 + 配置层组合 + 可逆注册。
  3. 四种模式是 四套插件模板,标准起步,创造改装,极简评测,PTC 压缩稳定流程。
  4. 写插件抓手只有一条链:applyinjectctx.tools.register(defineTool) → patch 挂载。
  5. 排错先看 --dump-config + Trajectory + 是否 next()/effect`
  6. 预览版接口会变:冻结版本、小范围试点、权限默认收紧

建议学习顺序(继续深挖)

  1. 官方 Cordis 教程 7 章(无 Key 也能跑概念)
  2. cookbook:adding-a-tool / capability seam
  3. examples/headless-agent/cordis.yml,对照自己的插件树
  4. 做一个「只服务你工作流」的小工具(质检、发布检查、仓库约定扫描)
  5. 再考虑打包 bundle 与分享到 dsh-plugin topic

「一切皆插件」真正爽的时刻,不是背概念,而是:
你改了一行 patch,模型多了一个工具;你卸掉插件,世界干净回到从前。
把这条闭环在自己的机器上跑通,这篇实践教程的目标就达成了。


参考链接

  1. DeepSeek Harness 官网:https://www.deepseek.com/harness/
  2. GitHub 仓库:https://github.com/deepseek-ai/deepseek-harness
  3. 架构文档:https://deepseek-harness.github.io/deepseek-harness/reference/
  4. 第一个插件教程:https://deepseek-harness.github.io/deepseek-harness/develop/basic/
  5. Cordis 教程:https://deepseek-harness.github.io/deepseek-harness/develop/cordis-tutorial/
  6. 社区插件发现:https://github.com/topics/dsh-plugin
  7. Cordis 论文仓库:https://github.com/cordiverse/paper

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐