DeepSeek Harness 初探:1、一切皆插件的 Agent 框架

系列第 1 篇 · 入门 | 项目定位、架构全景与源码速览

本文基于 dsh v0.1.0-rc.5,API 可能随版本变化,一切以官方仓库与本地源码为准。

摘要

DeepSeek 官方开源的 agent harness(智能体运行框架)DeepSeek Harness(dsh)以"一切皆插件"为架构宣言,基于内嵌(vendored)的 Cordis 框架构建。本文作为系列开篇,回答三个问题:dsh 是什么、为什么"一切皆插件"、二次开发能改什么。你将获得一张完整的架构全景图、一份仓库速览地图,以及一套避免踩坑的认知框架。后续 15 篇将带你从"会用"到"能改"再到"能发布自己的发行版"。

标签:DeepSeek Harness、AI Agent、插件开发、Cordis、开源项目


文章目录

    • 摘要
    • [1. 引言:为什么值得关注 dsh](#1. 引言:为什么值得关注 dsh)
    • [2. dsh 是什么:一个 agent harness](#2. dsh 是什么:一个 agent harness)
    • [3. 一切皆插件:理解插件树](#3. 一切皆插件:理解插件树)
      • [3.1 插件是什么](#3.1 插件是什么)
      • [3.2 插件树:Profile → Bundle → Patch](#3.2 插件树:Profile → Bundle → Patch)
      • [3.3 核心服务一览](#3.3 核心服务一览)
    • [4. 架构全景图](#4. 架构全景图)
      • [一次对话的节奏:turn 与 step](#一次对话的节奏:turn 与 step)
    • [5. 仓库速览:一张二开地图](#5. 仓库速览:一张二开地图)
    • [6. 能力缝(Capability Seam):三件套思维](#6. 能力缝(Capability Seam):三件套思维)
    • [7. 二次开发能改什么:官方扩展点地图](#7. 二次开发能改什么:官方扩展点地图)
    • [8. 风险与预期:先管理好"漂移"](#8. 风险与预期:先管理好"漂移")
    • [9. 术语速查(开篇用)](#9. 术语速查(开篇用))
    • [10. 踩坑与经验(认知篇)](#10. 踩坑与经验(认知篇))
    • [11. 总结](#11. 总结)
    • [12. 延伸阅读](#12. 延伸阅读)

1. 引言:为什么值得关注 dsh

DeepSeek 最近的开源动作不断。这一次不是模型权重,而是一个 agent harness------一个用来构建、运行、调试智能体的"运行时框架"。它叫 DeepSeek Harness (简称 dsh ),官方仓库在 github.com/deepseek-ai/deepseek-harness

最吸引我的是它的架构宣言:Everything is a Plugin(一切皆插件)。这个说法在很多项目里是营销话术,但在 dsh 里是字面事实------连模型适配器、工具注册表、会话日志、甚至 agent 主循环本身,都是插件,都可以从配置里换掉。

这意味着什么?意味着二次开发的门槛被设计得很低:你想改 dsh 的任何一个行为,都不需要 fork 后硬改核心代码,而是写一个插件挂进去。这正好是本系列要带你做的事。

在开始之前,先把丑话说在前面:dsh 目前处于 **developer preview(开发者预览)**阶段,版本是 v0.1.0-rc.5,官方在 README 里白纸黑字写着 "THERE WILL BE COMPATIBILITY-BREAKING CHANGES"(必然存在破坏性变更)。所以本系列所有内容都会标注版本号,你在阅读时也要有这个心理预期------后面第 12 篇会专门讲"fork 之后如何管理这种漂移"。

2. dsh 是什么:一个 agent harness

先厘清概念。Agent Harness 和"Agent 应用""Agent 框架"不是一回事:

  • Agent 框架(如 LangChain)给你一套组装 LLM 调用的积木;
  • Agent 应用(如某个聊天机器人)是组装好的成品;
  • Agent Harness 介于两者之间:它提供运行 agent 的完整运行时------会话管理、工具执行、权限审批、持久化、Web UI、多进程,但把"你的 agent 长什么样"完全留给你通过插件/配置决定。

dsh 的官方定位是"open-source agent harness developed by DeepSeek AI"。它开箱即带:

  • 一个 Web GUI (默认 http://127.0.0.1:3080),直接 npx @deepseek-ai/dsh web 就能跑;
  • 一套 headless 运行方式(一次性任务,无服务器);
  • 一个 ACP 自动化服务(Agent Client Protocol,给外部程序调用 agent 用)。

它依赖一个叫 Cordis 的框架。Cordis 是开源社区 cordiverse 维护的插件化框架(著名的 Koishi 机器人框架就基于它)。dsh 没有走 npm 依赖,而是把 Cordis 及其基础库以源码形式 vendor(内嵌)进了自己的仓库 ,重新命名到 @deepseek-ai scope 下(如 @deepseek-ai/cordis,当前版本 4.0.0-rc.7),目的在 vendor/README.md 里写得很清楚:让 harness 完全拥有自己的框架层------可审计、可打补丁、可钉版本。这一点对二次开发者很重要:你改的"框架"和"产品"在同一个仓库里,没有黑盒。

3. 一切皆插件:理解插件树

3.1 插件是什么

在 Cordis 的世界里,插件(plugin)是一个最小的注册单元:它向一个共享的 Context(上下文)贡献服务事件效果(effect) 。一个典型的 dsh 插件长这样(改编自官方文档 docs/cookbook/adding-a-tool.md 的最小工具示例,简化了参数):

ts 复制代码
import { readFile } from 'node:fs/promises'
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

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

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'read_file',
    description: 'Read a file from disk.',   // 模型看到的就是这段描述
    parameters: {
      path: { type: 'string', required: true, description: 'Absolute path' },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args, exec) {
      return readFile(args.path, { encoding: 'utf8', signal: exec.signal })
    },
  }))
}

注意两个关键点:

  1. 注册是副作用 :插件通过 ctx.tools.register(...) 这样的调用产生效果,插件卸载时效果自动逆注册(dispose),不留残留。整个 dsh 都遵循"注册即副作用、卸载即回收"这一纪律。
  2. 没有特权核心 :上面这段代码注册的工具,和 dsh 内置的 bash、fs、web 工具处于完全相同的地位。dsh 官方文档(docs/architecture.md)原话是"There is no privileged core to patch"------你要扩展 dsh,不是去改一个特权核心,而是在一堆插件旁边挂一个自己的插件。

3.2 插件树:Profile → Bundle → Patch

一个正在运行的 dsh,是一个插件树(plugin tree)------由启动时按顺序叠加的多个"层"组合而成。理解这三层,是理解 dsh 配置体系(第 5 篇会展开)的钥匙:

是什么 例子
Profile(档案) 一个命名的组合,列出它要叠哪些 bundle webheadless 是官方自带模板
Bundle(包) 可分发/可安装的 Cordis 配置行 + 代码的打包格式 dsh-base(基础层)、dsh-web-app(Web 应用层)、dsh-headless
Patch(补丁) 按"行 id"覆盖已有配置或插入新行 用户的 cordis.patch.yml--patch 覆盖

层级叠加顺序大致是:profile 列出的 bundle 依次应用 → profile 的 cordis.patch.yml → 用户主目录的 patch → 命令行 --patch 覆盖。每一层都能改掉下面层的任何一行配置。

想亲眼看到你的机器真正 boot 出什么样的树,跑这一条命令(本机实测可用):

sh 复制代码
dsh --profile web --dump-config

它会打印出完整的配置树------上面每一行都可以被你自己的 patch 覆盖。这是"配置即二次开发"的最轻入口。

3.3 核心服务一览

插件向 Context 贡献的服务 通过 ctx.<key> 访问。以下是 dsh 的核心服务(摘自 docs/architecture.md):

服务 拥有什么 ctx 键
Session 追加式会话事件日志与内存存储 ctx.sessions
System Prompt 提示词分段与工具 schema 组装 ctx.systemPrompt
Tools 作用域工具注册表与受守卫的执行管线 ctx.tools
Agent Agent 接口、活动注册表、agent/* 事件 ctx.agents
Agent Loop 实现 Agent 接口的默认驱动器(主循环) ctx.agentLoop
LLM 消息与流式词汇表 + 适配器缝 ctx.llm

注意 ctx.agentLoop主循环本身也是一个可替换的服务 。这也是"一切皆插件"最极致的体现------你甚至可以换掉 agent 怎么思考的主循环,只要实现同一个 Agent 接口。

4. 架构全景图

把上面的概念拼起来,dsh 的一次典型对话流程大致是:
#mermaid-svg-uPQhdZjCzgmp4xuN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uPQhdZjCzgmp4xuN .error-icon{fill:#552222;}#mermaid-svg-uPQhdZjCzgmp4xuN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uPQhdZjCzgmp4xuN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uPQhdZjCzgmp4xuN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uPQhdZjCzgmp4xuN .marker.cross{stroke:#333333;}#mermaid-svg-uPQhdZjCzgmp4xuN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uPQhdZjCzgmp4xuN p{margin:0;}#mermaid-svg-uPQhdZjCzgmp4xuN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster-label text{fill:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster-label span{color:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster-label span p{background-color:transparent;}#mermaid-svg-uPQhdZjCzgmp4xuN .label text,#mermaid-svg-uPQhdZjCzgmp4xuN span{fill:#333;color:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN .node rect,#mermaid-svg-uPQhdZjCzgmp4xuN .node circle,#mermaid-svg-uPQhdZjCzgmp4xuN .node ellipse,#mermaid-svg-uPQhdZjCzgmp4xuN .node polygon,#mermaid-svg-uPQhdZjCzgmp4xuN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uPQhdZjCzgmp4xuN .rough-node .label text,#mermaid-svg-uPQhdZjCzgmp4xuN .node .label text,#mermaid-svg-uPQhdZjCzgmp4xuN .image-shape .label,#mermaid-svg-uPQhdZjCzgmp4xuN .icon-shape .label{text-anchor:middle;}#mermaid-svg-uPQhdZjCzgmp4xuN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uPQhdZjCzgmp4xuN .rough-node .label,#mermaid-svg-uPQhdZjCzgmp4xuN .node .label,#mermaid-svg-uPQhdZjCzgmp4xuN .image-shape .label,#mermaid-svg-uPQhdZjCzgmp4xuN .icon-shape .label{text-align:center;}#mermaid-svg-uPQhdZjCzgmp4xuN .node.clickable{cursor:pointer;}#mermaid-svg-uPQhdZjCzgmp4xuN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uPQhdZjCzgmp4xuN .arrowheadPath{fill:#333333;}#mermaid-svg-uPQhdZjCzgmp4xuN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uPQhdZjCzgmp4xuN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uPQhdZjCzgmp4xuN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uPQhdZjCzgmp4xuN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uPQhdZjCzgmp4xuN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uPQhdZjCzgmp4xuN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster text{fill:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN .cluster span{color:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uPQhdZjCzgmp4xuN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uPQhdZjCzgmp4xuN rect.text{fill:none;stroke-width:0;}#mermaid-svg-uPQhdZjCzgmp4xuN .icon-shape,#mermaid-svg-uPQhdZjCzgmp4xuN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uPQhdZjCzgmp4xuN .icon-shape p,#mermaid-svg-uPQhdZjCzgmp4xuN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uPQhdZjCzgmp4xuN .icon-shape .label rect,#mermaid-svg-uPQhdZjCzgmp4xuN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uPQhdZjCzgmp4xuN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uPQhdZjCzgmp4xuN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uPQhdZjCzgmp4xuN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 能力层
运行时
用户层
Web GUI / CLI / ACP
Agent Loop(turn/step 驱动)
Session 日志(append-only 事件流)
System Prompt 组装
Tools 注册表 + 执行管线
LLM 适配器缝
shell / fs / web / subprocess / terminal ...
sandbox / approval(策略与审批)

(图 1:dsh 运行时全景。自绘,建议用 drawio 重新绘制后导出 PNG 上传)

几个值得记住的机制:

  • 模型可见 ⟺ 已记录 :模型每次请求看到的上下文,都从 Session 日志投影(deriveMessages())而来。这条不变式意味着:任何想让模型看到的新输入,都必须对应一个新的事件类型------第 9 篇专门讲怎么扩展。
  • 事件是扩展点 :会话事件(持久)、agent 事件(agent/*,拦截进行中的工作)、能力事件(fs/*tools/*telemetry/*,给能力缝挂策略和适配器)。
  • 瀑布事件要 next()agent/pre-stepagent/requestllm/streamtools/* 的监听器是瀑布(waterfall),必须调用 next() 放行,否则会短路整条链------这是新手最容易写错的点(第 6 篇展开)。

一次对话的节奏:turn 与 step

dsh 里有两个节奏单位:**step(步)**是"一次模型请求 + 它调用的工具";**turn(回合)**是零个或多个 step,从第一个输入被认领开始,到没有欠账为止。典型流程是:

text 复制代码
turn/start
  认领下一步输入 + 一条排队消息
  组装提示词分段 + 工具 schema
  -> agent/pre-step(可改写或拒绝)
  step/start
  模型请求(llm/stream)-> assistant/chunk* -> assistant/message
  工具调用(tools/pre-execute -> tools/execute -> tools/post-execute -> tool/result*)
  step/end
  工具还欠一次请求,或新输入到达 -> 下一步
turn/end

其中 turn/*step/*user/messageassistant/*tool/*持久会话事件 (写进日志、可回放),其余是运行期扩展点,分属三个事件域。第 6 篇会带着断点逐事件走一遍这条流程。

(图 3:turn 序列图。自绘,参考 docs/agent-lifecycle.md 的 sequence diagram 重绘后导出)

5. 仓库速览:一张二开地图

拿到源码后(本系列基于本地克隆,实测环境:Node v24.15.0、pnpm 11.7.0、HEAD 47f943859b,版本 0.1.0-rc.5),顶层结构如下(本机实测目录):

text 复制代码
D:\ai\deepseek\deepseek-harness
├─ .agents/        # Agent Notes(决策记录)与工作流技能
├─ apps/           # cli(命令行入口)、web(前端构建)
├─ docs/           # 架构/开发/子系统/手册,中英双语
├─ examples/       # 可运行示例:acp-agent、headless-agent、mcp-memory ...
├─ native/         # Landlock 沙箱原生模块
├─ packages/       # 219 个 @deepseek-ai/dsh-* 包(49 个组)
├─ patches/        # pnpm 补丁
├─ python/         # Python SDK
├─ scripts/        # 门禁与生成器
├─ vendor/         # vendored 的 Cordis 框架源码(9 个包)
└─ website/        # 文档网站(VitePress)

(图 2:仓库顶层结构。作者实测 Get-ChildItem 输出整理)

二次开发者最需要熟悉的是 packages/,它按"组"组织,每个组有明确职责(完整清单见 packages/README.md),挑几个重要的:

  • core/ :产品 API 骨架------sessionsystem-prompttoolsagentagent-loopscope
  • llm/ :LLM 能力族------抽象服务 + 各 provider 适配器(llm-deepseekllm-pi-ai);
  • shell/ fs/ subprocess/ terminal/ web/:模型面向的执行能力(bash、文件、进程、PTY、网页搜索);
  • session/:会话持久化(JSONL/SQLite)、投影、标题、遥测;
  • client/ host/:Web GUI 的浏览器端与 HTTP 服务端;
  • bundle/:可安装的 profile 补丁层(base/web-app/headless);
  • interaction/:审批、权限、命令、ask-user;
  • sandbox/:进程沙箱(bwrap/Landlock/Seatbelt/Windows ACL)。

每个包都是标准形态:package.json@deepseek-ai/dsh-<name>private: true)、src/(TypeScript)、tests/README.md。所有包统一走 pnpm workspaces + 双聚合 tsconfig(Host/Client)构建,这带来一个现实:改动任何一个包的源码,都要通过仓库的构建和门禁------第 2 篇会带你把整套构建跑通。

docs/ 是双语文档体系,按层级组织:architecture.md(架构总览)→ subsystems/(每个子系统的类型与 API 参考,50+ 页)→ cookbook/(步骤式指南)→ user/(产品手册)。中文版与英文版成对维护(如 architecture.zh.md),仓库用自动配对与字数门禁保证它们不漂移------你在官方仓库里看到的任何 .zh.md 都不是机器直译的凑数内容。

6. 能力缝(Capability Seam):三件套思维

这是 dsh 架构里最重要的一个概念,值得在开篇就种下(第 7 篇会完整实战)。

一个**能力缝(Capability Seam)**是一个可替换的能力,由三个角色构成:

角色 职责 例子(shell 能力)
Service Definition(服务定义) 声明接口、注入键、事件 dsh-shell 定义 ctx.shell 与请求/规格类型
Service Provider(服务提供者) 实现该接口 dsh-bash-local / dsh-pwsh-local(本机执行)、dsh-bash-sandbox / dsh-pwsh-sandbox(沙箱执行)
Consumer(消费者) 使用该接口,通常是模型面向的工具 dsh-tool-bash(bash 工具)

关键在依赖方向 :Consumer 只依赖 Service Definition,绝不依赖具体 Provider。所以换一个 Provider,整个产品跟着换------比如把 fs/subprocess 的 Provider 指向远程沙箱,Bash、PTY、LSP 全部随之迁移,不需要改任何 Consumer 代码。

对二次开发者来说,这个思维的价值是:先找缝,再写插件。你想加的能力,大概率有一个现成的缝可以挂(工具缝、LLM 缝、shell 缝、fs 缝......),而不是去改核心循环。

7. 二次开发能改什么:官方扩展点地图

docs/architecture.md 里有一张"Where new behavior goes"表,是二开最权威的起点,我摘录几个高频目标(完整版见官方文档):

你的目标 机制
接一个新模型 ctx.llm 上注册适配器
加一个模型面向的能力 注册到 ctx.tools,schema 自动进入提示词组装
加 shell / 持久终端执行 注册 ctx.shell / ctx.terminals 后端
拦截一次请求、工具或回合 agent/*tools/* 事件
给模型加上下文 agent.inject(),落进下一次请求
加持久会话状态 扩展 SessionEventMap,从日志渲染和回放
加 UI / 编辑器集成 驱动 ctx.agents,从 session/event 渲染
给一个会话不同的能力集 组合 agent preset(preset 插件)

配套的官方 cookbook 也值得收藏(都是步骤式指南,本系列会逐个展开):

docs/cookbook/adding-a-package.mdadding-a-tool.mdadding-an-llm-adapter.mdadding-a-conversation-node.mdextension-cookbook.md

本系列的路线图

把官方地图收进口袋后,说清楚本系列 16 篇怎么带你走完"从入门到精通":

  • 入门篇(01--05)· 会用:环境搭建(02)、第一个插件(03)、第一个工具(04)、配置体系(05)。目标:你能让 dsh 跑起来、能挂上自己的插件和工具。
  • 进阶篇(06--11)· 能改:核心包与事件流(06)、能力缝三件套(07)、接入新 LLM(08)、会话事件扩展(09)、Web GUI(10)、策略与安全(11)。目标:你能读懂核心源码、按官方范式改 dsh。
  • 精通篇(12--16)· 会造:fork 后私有构建与发布(12)、vendor 内核与自修改(13)、会话持久化与检索(14)、测试与门禁(15)、踩坑实录(16)。目标:你能维护自己的发行版。

每一篇都遵循同一条流水线:先用真实源码/文档核实每一个命令、路径与 API(禁止编造),再给出可运行的示例,最后标注哪些输出需要你实跑回填------确保文章里的每一行都经得起你在本地验证。

8. 风险与预期:先管理好"漂移"

先看生态现状,再谈风险。dsh 已经通过 npm 公开发布(官方 README 提供 npx @deepseek-ai/dsh web 一键启动,本仓库最近的提交也正好是 feat/npm-publicpublish the dsh family publicly),官方有 Discord 社区,也鼓励插件仓库打上 dsh-plugin topic 便于被发现。生态在起势,但远未稳定。

作为开篇,我想把最容易翻车的认知问题讲在前面。dsh 目前的状态决定了二开策略:

  1. rc 阶段无兼容承诺 :官方明确"backends reject old on-disk formats"------旧格式的磁盘数据会被拒收。SQLite 用单调递增的 SCHEMA_VERSIONdsh-sessionSESSION_FORMAT_VERSION 保持在 0 且无兼容承诺。你的二开代码要跟着版本走,不要假设 API 稳定。
  2. 版本漂移管理:建议在 fork 上建立一个自己的基线(tag 或 release 分支),官方上游有更新时再评估合并。这是"能改"和"会造"的分水岭,第 12 篇完整讲。
  3. vendor 纪律vendor/ 里的 Cordis 是钉版本的源码副本,改动需要登记到 vendor/README.md 的 Local modifications 清单,并有 manifest 守卫。能通过插件解决的问题,不要动 vendor。
  4. 双语文档门禁 :仓库对文档有严格的字数预算、中英配对、死链检查(doc-sync)。改代码时顺手改文档是仓库纪律,但发博客时注意区分"仓库纪律"和"读者需要"。

9. 术语速查(开篇用)

本文出现的术语都给了英文原名,这里汇总成一张速查表,后面 15 篇会反复用到:

术语 含义
Plugin(插件) 贡献服务/事件/效果的注册单元,卸载时效果自动回收
Context 插件共享的上下文,服务通过 ctx.<key> 访问
Effect(效果) 注册产生的副作用,随插件卸载逆注册(disposer)
Seam(能力缝) Service Definition / Provider / Consumer 三件套
Profile(档案) 命名组合,列出要叠加的 bundle
Bundle(包) 可分发的 Cordis 配置行 + 代码
Patch(补丁) 按行 id 覆盖或插入配置
Waterfall(瀑布事件) 监听器必须调用 next() 放行的链式事件
Turn / Step 回合 / 步:一次对话的节奏单位
Harness home dsh 的用户主目录(profile、补丁、数据;本机实测 DSH_HOME 指向用户目录下的 .dsh

10. 踩坑与经验(认知篇)

本篇是认知篇,没有代码坑,但有三个"认知坑",提前排掉:

  • 坑 1:把 rc 当稳定版用 。有人照着旧文章配置 cordis.yml,升级后字段失效。解法:写作/阅读一律标注版本;升级前看 git log 与 release notes;二开代码把版本号写进 README。
  • 坑 2:想改行为就改核心 。dsh 的设计就是让你别这么干------先查扩展点表(第 7 节),90% 的需求能落到某个缝或事件上。改 agent-loop 意味着你要同步更新架构文档,代价很大。
  • 坑 3:忽略"注册即副作用"纪律 。写插件时手动注册却忘了随卸载回收,会导致 HMR(热更新)后重复注册、行为叠加。记住:一切贡献走 ctx.effect() / ctx.on(),注册函数的返回值就是 disposer。

11. 总结

本文你能带走的结论:

  1. dsh 是 DeepSeek 开源的 agent harness,基于 vendored Cordis,一切皆插件,没有特权核心------扩展 dsh 的方式是挂插件,不是改核心。
  2. 一个运行中的 dsh 是插件树 :Profile(档案)→ Bundle(包)→ Patch(补丁)三层组合,dsh --profile web --dump-config 能看你的树。
  3. 核心服务(sessions/tools/agents/agentLoop/llm)都可替换;模型可见 ⟺ 已记录是头号不变式。
  4. 仓库有 219 个包、双语文档、严格的构建门禁;二开入口在 docs/cookbook/ 与扩展点表。
  5. 当前是 rc 阶段、无兼容承诺------先建自己的版本基线,再动手改

下篇预告 :第 2 篇《DeepSeek Harness 二次开发:源码搭建与首次运行》------带你把环境搭好、构建跑通、Web GUI 亮起来,并亲手用 --dump-config 看清你的插件树。

12. 延伸阅读

  • 官方架构文档:docs/architecture.md(仓库内,改动 packages/ 前必读)
  • Cordis 入门:docs/cordis-primer.md
  • 术语表:docs/glossary.md
  • 包清单:packages/README.md
  • 扩展 cookbook:docs/cookbook/extension-cookbook.md
  • 官方仓库:https://github.com/deepseek-ai/deepseek-harness
相关推荐
小马过河R2 小时前
Graph Engineering 深度解析:模型越强,越需要给它画好“地图”
人工智能·langchain·graph·ai工程化·harness·驾驭工程
墨心@2 小时前
阶段 4:事件总线
人工智能·语言模型·大语言模型·agent·codex·harness
用户548775431603 小时前
DeepSeek Harness 与 xAgent:两种 Agent Harness 架构路线怎么选
人工智能·deepseek
舒灿3 小时前
DeepSeek Harness——Agent自我进化的实现途径?
前端·ai编程·deepseek
Do1you1believe1light3 小时前
AI Agent 无法自己进化自己——我给它配了一支“外部教练团队”
deepseek
鱼饼Y3 小时前
DeepSeek Harness 来了!从用户界面分析DSH
agent·deepseek
skywalk81633 小时前
硬核移植实录:在 FreeBSD 15.1 上从零跑起 DeepSeek 智能体 harness(附完整踩坑手册)
人工智能·freebsd·deepseek·harness
sjh97143 小时前
我把 DeepSeek Harness 每次会话的账单拆开看了一遍,第一个请求占了 52%
deepseek
牛奶咖啡134 小时前
Deepseek大语言模型解析、商用授权协议与国内合规资质说明
人工智能·deepseek·deepseek是什么·deepseek的核心产品·deepseek的行业地位·deepseek的开源协议·deepseek的商用授权规则