内容
# DeepSeek Harness(dsh)保姆级理解教程:架构、插件体系与主流 Agent 框架对比
> **English**: A hands-on, source-code-level guide to [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`) — DeepSeek's open-source, MIT-licensed **agent harness** where *everything is a plugin* (built on the vendored [Cordis](https://github.com/cordiverse/cordis) framework). Covers the event-sourced session log, the capability-seam plugin pattern, the `cordis.yml` composition model, real UI walkthroughs, copy-paste examples, and an in-depth comparison with LangGraph, OpenAI Agents SDK, Claude Agent SDK, and Google ADK. **Full English version: [README.en.md](README.en.md).**
>
> **Keywords**: DeepSeek Harness tutorial, dsh agent harness, DeepSeek agent framework, agent harness vs agent framework, LangGraph alternative, Claude Code alternative, Cordis plugin architecture, event-sourced agent session, AI agent context compaction, agent harness comparison 2026.
> 仓库:https://github.com/deepseek-ai/deepseek-harness (MIT,TypeScript pnpm monorepo)
> 状态:**Developer Preview**(官方原话:"THERE WILL BE COMPATIBILITY-BREAKING CHANGES.")
> 本教程基于对仓库的全量精读(源码 + 官方文档约 1.8 万行)与**本机真实运行截图**,写作时间 2026-08-13(仓库公开发布日)。插件 API 处于快速迭代期,具体细节请以仓库最新 `README.md` 与 `docs/` 为准。
---
## 目录
1. [它是什么:先搞懂「Agent Harness」这个概念](#1-它是什么先搞懂agent-harness这个概念)
2. [五分钟跑起来(含真实界面截图)](#2-五分钟跑起来含真实界面截图)
3. [核心心智模型:一切皆插件](#3-核心心智模型一切皆插件)
4. [Cordis 框架速成:五个概念读懂 dsh 的地基](#4-cordis-框架速成五个概念读懂-dsh-的地基)
5. [架构总览:一次请求从出生到落盘的完整旅程](#5-架构总览一次请求从出生到落盘的完整旅程)
6. [事件溯源会话:dsh 最硬核的设计](#6-事件溯源会话dsh-最硬核的设计)
7. [能力接缝(Capability Seam):三段式插件分工](#7-能力接缝capability-seam三段式插件分工)
8. [配置即组合:cordis.yml / bundle / profile / preset](#8-配置即组合cordisyml--bundle--profile--preset)
9. [动手:写你的第一个插件和工具](#9-动手写你的第一个插件和工具)
10. [生态互操作:MCP、ACP、Claude Code / Codex 桥、Skills、SDK](#10-生态互操作mcpacpclaude-code--codex-桥skillssdk)
11. [与主流 Agent 框架的正面对比(重头戏)](#11-与主流-agent-框架的正面对比重头戏)
12. [工程实践亮点:普通项目也值得抄的作业](#12-工程实践亮点普通项目也值得抄的作业)
13. [现状、短板与适用判断](#13-现状短板与适用判断)
14. [附录:能力地图与关键默认值速查](#14-附录能力地图与关键默认值速查)
15. [实操示例集(可复制运行)](#15-实操示例集可复制运行)
16. [FAQ 高频问题速答](#16-faq-高频问题速答)
---
## 1. 它是什么:先搞懂「Agent Harness」这个概念
### 1.1 一句话定位
**DeepSeek Harness(命令行名 `dsh`)是 DeepSeek 官方开源的 Agent Harness——一个跑在模型"外面"的 Agent 运行时骨架。它的架构口号是「一切皆插件」(Everything is a Plugin),底层基于 vendored 的 Cordis 框架。**
注意它不是另一个 LangChain 式的"编排框架",官方自己在 cookbook 里说得非常直白:
> "DeepSeek Harness itself is an agent harness, not an SDK project."
### 1.2 Harness vs Framework:一场正在进行的行业争论
2026 年业界对「Agent Harness」这个词有一个逐渐收敛的共识公式(LangChain 的 Vivek Trivedy 提出的版本最干净):
> **Agent = Model + Harness**。"If you're not the model, you're the harness."
进一步拆解:**Harness = Tools + Context + Loop**(工具、上下文管理、模型-工具循环)。
DeepSeek 自己 2026 年 5 月的招聘 JD 里写得一模一样:「除模型本身以外的所有工作,都属于 Harness 的范畴。」
那 harness 和 framework 有什么区别?社区多源趋同的理解是:
- **Framework(框架)**:给你可复用的抽象构件,**loop 是你自己的代码**。LangGraph 的图、CrewAI 的 crew、Google ADK 的 typed nodes 都属于这层。
- **Harness(挽具/脚手架)**:一个**已经被配置好的执行与控制层**,loop 是产品方给你的。Claude Code、Codex CLI 是典型。
为什么 DeepSeek 要亲自下场做 harness?一个公开的行业事实:SWE-bench 这类基准测的是「模型 + 脚手架」的**整体**,同一个模型在不同 harness 下分数可以差很多。如果你的模型分数依赖别人家不可控的脚手架,理性选择就是自己造一个、MIT 开源、让社区帮你改进。时间线也印证这一点:2026-07-31 DeepSeek-V4-Flash 公测(官方披露 Code Agent 基准就是"使用 DeepSeek Harness 的极简模式"跑的)→ 08-10 npm 包 `@deepseek-ai/dsh` 首发 → 08-12 V4-Pro GA → 08-13 仓库公开。模型和 harness 是一对,只是只有一个收钱。
### 1.3 发布快照(2026-08-13)
- 仓库公开约 2 小时即 18k+ stars(这更多衡量 DeepSeek 的名字而非代码成熟度,请理性看待);
- 版本号 `0.1.0-rc.x`,无 tagged release,官方明确警告会有破坏性变更;
- 文档**全部中英双语**,文档目录、工具目录、配置目录均由脚本从源码生成并有 CI 新鲜度校验;
- 插件生态机制 = npm + GitHub topic `dsh-plugin`。
---
## 2. 五分钟跑起来
### 2.1 方式一:Web UI(产品主入口)
```sh
# 只需要 Node.js(^22.19 或 >=24)
npx @deepseek-ai/dsh web
```
浏览器打开 `http://127.0.0.1:3080`,然后:
1. **Settings → Models** 填入你的 DeepSeek API Key(热生效,不重启;写入 `$DSH_HOME/settings.yaml` 的 `llm-deepseek:` 段,密钥本体存 `$DSH_HOME/.credentials.yaml`);
2. 选择一个 workspace(工作目录);
3. 开会话,跑任务。
实拍:启动后的首页(本教程全部截图均为本机真实运行截取,`npx @deepseek-ai/dsh web`,macOS):

Settings → Models 页(DeepSeek 卡片一个 API-key 字段;也可以 Add provider 接 Anthropic/OpenAI 目录,或 Add a custom provider 接任意 OpenAI 兼容网关):

Settings → Plugins 页——「一切皆插件」不是口号,是设置界面里看得见摸得着的插件清单(Shell、Agent loop、Web search……每个都可以配置/检查):

Settings → General 与 Agent presets 页(新会话的默认 preset、默认权限档位、语言与外观都在这里;preset 即第 8 章讲的「每会话组合」):


注意一个和直觉相反的点是:**dsh 没有 Claude Code 那种终端交互式 TUI**。`dsh` CLI 只是个启动器,官方模板只有 `web` 和 `headless` 两个 profile(README 里出现的 `--profile tui` 明确标注是"假设你装了 tui profile"的示例)。发布当天国内社区最大的吐槽就是"居然没有 CLI 对话界面"——要交互就用浏览器。
### 2.2 方式二:Headless 一次性任务
```sh
dsh --profile headless "fix the failing test"
```
不开任何监听端口,stdout 打印最终回答;任务完成退出码 0,否则 1。适合 CI 和脚本。
### 2.3 方式三:Python SDK(目标机器无需 Node.js)
```sh
python -m pip install deepseek-harness-sdk
```
装 SDK 会自动带上同版本的 `deepseek-harness-runtime-bin` 平台 wheel(内置单文件可执行 `dsh-jsonrpc-agent`,自带全部插件,**不需要装 Node**;支持 Linux x64/arm64、macOS 14+ arm64):
```python
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness(provider="deepseek-official", model="deepseek-v4-flash",
max_tokens=49_152, cwd="/path/to/repo") as harness:
result = harness.run("Inspect the repository and fix the failing tests.",
session_id="example-001")
print(result.final_response)
```
底层是子进程 stdio 上的换行分隔 JSON-RPC 2.0 协议。两个值得知道的语义细节:
- `final_response` 是这次运行区间内**最后一条已提交的 assistant 文本**,不是因果意义上"对这句话的回答"(期间可能有 steering/inject 的贡献);
- 复用 `session_id` 会保留会话持有的持久 bash(cwd、环境变量、shell 函数都还在)。
### 2.4 方式四:从源码跑(想改代码/读源码的话)
```sh
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web # 起 Web UI
pnpm dsh --profile headless "task" # 需要 DEEPSEEK_API_KEY
```
常用命令速查:`pnpm run test`(单测)、`pnpm run test:coverage`(CI 覆盖率门禁,`packages/*/*/src` 逐文件 100%)、`pnpm run test:e2e`(真实 API,无 key 自动跳过)、`pnpm run test:snapshot`(无 key 的 ACP/headless 回放快照)、`pnpm run typecheck`、`pnpm run build`。
### 2.5 一次真实任务的完整界面走查(截图实录)
为了让你对后面章节的架构概念有体感,这里用本机真实跑的一个任务做走查:在一个放了「带 bug 的 `calc.py` + 失败测试」的 demo 工作区里,给 agent 一句话任务——“Run the tests with `python -m pytest -q`, find the failing test, fix the bug in calc.py, then re-run the tests to confirm all pass.”
新建会话(workspace = `dsh-demo-workspace`,preset = Standard mode,权限 = Workspace Write,模型 = DeepSeek-V4-Pro High):

运行中(第 8 秒抓拍)。注意图里的几个细节,每一个都对应后文的一个架构概念:
- **两条 Context injection**(`@deepseek-ai/dsh-system-prompt`、`skill-catalog`)——这就是第 5/6 章讲的「运行时上下文快照」与「skills 渐进式披露」,它们以 user-role 消息进入日志;
- **“Retried model request (1/2)”**——`dsh-llm-retry` 插件在 `agent/request-error` 扩展点上做的持久化重试(第 7 章);
- **Think / Bash / Glob / Read 工具卡片**——工具定义里声明的协议中立 render intent(第 5 章工具系统);
- 底部状态栏实时显示 **turns · steps · LLM 耗时 · TTFT · tok/s · Cache hit · 输入/输出 token**——会话遥测从同一条事件流派生。

任务完成(17 秒):agent 跑测试 → 定位 `fibonacci` 的 off-by-one → Edit 修复 → 重跑全绿(2 passed)。先看成品的完整对话流,再展开失败测试的 terminal 卡片看细节:


最有教学价值的是 **Trajectory 标签页**——它就是第 6 章「事件溯源会话」的可视化:顶部是 token 构成条(Input/Model/Tools),下面按 Turn 展开 SYSTEM / USER / CONTEXT / ASSISTANT / TOOL 的完整序列。你在 UI 里看到的每一行,就是 session log 里的一条持久事件;模型看到的上下文,就是这些事件的投影。

---
## 3. 核心心智模型:一切皆插件
### 3.1 「彻底」到什么程度?
绝大多数框架说"支持插件",意思是"你可以在固定内核上挂扩展"。dsh 的意思是:**没有特权内核**。
`docs/architecture.md` 原话:"There is no privileged core to patch." 具体清单:
- 模型适配器(`llm-deepseek`)——插件,可换;
- 工具注册表、session 持久化、审批策略、遥测——插件,可换;
- **Agent Loop 本身——也是插件,可换。**
实锤证据,`packages/core/agent-loop/src/index.ts`:
```ts
export class AgentLoop extends Service implements AgentFactory {
static inject = ['agents', 'sessions', 'llm', 'tools', 'systemPrompt']
static Config = z.object({ maxParallelToolCalls: ..., agents: z.array(...) })
constructor(ctx: Context, config: Config) { super(ctx, 'agentLoop') ... }
}
```
它就是一个普通的 Cordis 服务插件:声明依赖(五个服务齐了才激活)、用 schema 校验配置、注册为 `ctx.agentLoop`,由 base bundle 里的一行 YAML 挂载。官方文档明确说:扩展包只应该依赖 `dsh-agent` 的 `Agent` 接口和 `agent/*` 事件,**绝不依赖 `dsh-agent-loop` 这个具体实现**——所以 loop 可以整体替换。
对照主流框架:LangGraph 的 loop 藏在图执行引擎内部;Claude Agent SDK 的 loop 在 CLI 二进制里;OpenAI Agents SDK 的 `Runner` 是库里一个固定类。**dsh 的 loop 是一行可 patch 的配置。**
### 3.2 极限展示:Agent 修改自己的运行时
仓库自带一个自指 demo:
```sh
pnpm run demo:cordis # 需要 DEEPSEEK_API_KEY
```
它给 agent 挂上 `cordis_inspect` / `cordis_define` / `cordis_run` / `cordis_stop` / `cordis_undefine` 五个工具,让 agent 可以**在运行时检查自己所在进程的服务与插件、把模型现写的代码作为插件挂载进自己的运行时**。`cordis_inspect` 返回的接口参考和文档同源(都由 AST 生成,CI 保证不漂移),所以模型读到的是"真实的当前系统",不是过期的 prompt 描述。
边界也说得很诚实:动态插件只存在于进程内存(不写文件、不改 cordis.yml、不跨重启),且"沙箱只约束诚实代码,不是安全边界——应当像对待 bash 访问一样对待它"。
### 3.3 这套东西从哪来:Cordis 与 Koishi 渊源
Cordis(`cordiverse/cordis`)不是 DeepSeek 从零发明的。它源自聊天机器人框架 **Koishi** 的插件内核——Koishi 插件市场有 1000+ 插件、500+ 插件开发者,「一切皆插件 + 热更新」模型在聊天机器人领域被大规模实战验证多年。dsh 把 Cordis **vendored**(源码内嵌,`vendor/cordis`,上游 `cordis@4.0.0-rc.7`),并在其上做了 18 条成文的本地加固(fiber 生命周期、事务性配置重载、懒 `!!js` 解析等,见 `vendor/README.md`)——等于把框架层当作自有代码维护。
Cordis 的设计依据是一篇论文:*A Programming Paradigm for Spatiotemporal Composability*(时空可组合性编程范式,cordiverse/paper)。听着唬人,落到代码上就是两个维度:
- **空间可组合性(spatial)**:context 树 + `extend/isolate/intercept`,让同一份代码在不同子树里解析到**不同的服务实现/配置**——组合发生在"哪个 context 下";
- **时间可组合性(temporal)**:fiber 生命周期 + effect/disposer,让贡献随插件加载/卸载/热重载**动态出现和完全消失**——组合发生在"什么时候"。
论文里"组件被移除时副作用能被完全撤销"(时间)和"组件间依赖声明式表达并被反应式管理"(空间),就是下一节要讲的 `inject` 依赖解析和 effect 回收机制的理论化表述。
---
## 4. Cordis 框架速成:五个概念读懂 dsh 的地基
读懂这五个概念,dsh 的全部源码对你就是透明的。
### 4.1 Context——一个被 Proxy 包裹的服务仓库
`vendor/cordis/src/context.ts`:`Context` 构造时返回 `new Proxy(this, ReflectService.handler)`。你写的 `ctx.tools.register(...)`,属性读取走的是服务解析。
关键操作:
- `ctx.extend()` / `ctx.isolate(name)` / `ctx.intercept()`:创建**原型继承**的子 context,不改父级。`isolate` 为某个服务名开辟独立解析域——两个会话可以各挂各的 provider 实现而不污染根组合(per-session preset 靠的就是它);
- 内置四个核心服务:`ctx.events`、`ctx.logger`、`ctx.reflect`、`ctx.registry`。
### 4.2 Plugin——三种形态,依赖驱动激活
插件可以是:函数 `(ctx, config)`、类 `new (ctx, config)`、或带 `apply(ctx, config)` 的对象。三个静态元数据:
- **`inject`**:声明依赖的服务名。**依赖未齐时插件停在 PENDING,齐了自动激活**——加载顺序由服务可用性驱动,不是手工编排的 boot 序列。这就是为什么 cordis.yml 里"行顺序没有加载语义";
- **`Config`**:schema 校验器,启动前验证配置,失败直接抛错(fail loud);
- **`provide`**:声明提供的服务名。
### 4.3 Service——占住 `ctx.<key>` 的基类
```ts
abstract class Service {
constructor(ctx, name) // 内部调 ctx.reflect.provide(name, this)
}
```
服务注册本身就是 effect:**fiber 卸载时自动注销**。重复注册同名服务直接 throw——这是"一个能力同一上下文只允许一个实现"约束的来源。
### 4.4 Fiber 与 Effect——「一切皆插件」的运行时实体
每次 `ctx.plugin()` 创建一个 Fiber,状态机 `PENDING → LOADING → ACTIVE | FAILED → UNLOADING → DISPOSED`。核心规则(也是 dsh 根 AGENTS.md 的头号硬性约定):
> **Registrations are effects(注册即副作用)**:任何贡献——工具、prompt 段落、监听器、服务——都通过 `ctx.effect()` / `ctx.on()` 注册并返回 disposer;fiber 卸载时按**逆序**执行全部 disposer。
这条规则让 HMR 热重载和插件卸载"免费可用":卸载后系统严格回到干净状态。对比常见插件系统"加载容易卸载难、热更留残渣"的痛点,这是 dsh 热更新能力的全部秘密。
### 4.5 事件模型:五种分发模式 + waterfall 中间件
```ts
type DispatchMode = 'emit' | 'parallel' | 'serial' | 'bail' | 'waterfall'
```
| 模式 | 语义 | 典型用途 |
|---|---|---|
| `emit` | 同步广播,不等待 | 观察类通知(`tools/result`、`session/event`) |
| `parallel` | 并发等待全部 | 落盘检查点(`session/flush`) |
| `serial` | 顺序 await,首个有效返回值即终止 | 决策类(`agent/turn-stopping`) |
| `waterfall` | **around 中间件**:listener 收 `(...args, next)`,调 `next()` 委托下游,不调则短路 | 拦截改写(`agent/pre-step`、`agent/request`、`llm/stream`、`tools/pre-execute`) |
dsh 硬规则:**waterfall listener 必须调 `next()`**,除非该 listener 就是决策者(比如审批插件决定 deny)。模式是事件公共契约的一部分,JSDoc `@mode` 标注,静态校验。
类型安全靠 TypeScript declaration merging:插件往 `@deepseek-ai/cordis` 的 `Events` 接口 merge 自己的事件名,于是 `ctx.on('agent/pre-step', ...)` 全仓库类型安全。
---
## 5. 架构总览:一次请求从出生到落盘的完整旅程
### 5.1 分层图
```
┌─ 入口层 apps/cli、packages/boot
│ dsh CLI → boot() → 创建 root Context → 装载配置树
│ profile($DSH_HOME/profiles/<name>)= bundle 层叠 + 用户 cordis.patch.yml
│
├─ 组合层 vendor/loader、vendor/include、vendor/hmr
│ cordis.yml / cordis.patch.yml → EntryTree → 逐行 import 插件、建 Fiber
│
├─ 框架层 vendor/cordis(= @deepseek-ai/cordis)
│ Context / Registry / Fiber / 事件五种模式 / 服务解析
│
├─ 产品脊柱 packages/core/*
│ ctx.sessions · ctx.systemPrompt · ctx.tools · ctx.agents · ctx.agentLoop
│
├─ 能力层 packages/llm、shell、fs、web、subagent、compaction… 约 60 个 seam
│ 每个 seam = Service Definition + Provider(s) + Consumer(s)
│
└─ 表面层 packages/bundle/*、web-app、headless、acp、sdk
把插件树包装成 Web UI / 一次性 runner / ACP 服务 / JSON-RPC 服务
```
### 5.2 词汇表:turn / step / round
- **step(步骤)** = 一次模型请求 + 它引发的工具执行;
- **turn(轮次)** = 一次用户唤醒引发的完整模型循环,含 0~N 个 step,由 `turn/start`/`turn/end` 持久事件括号;
- **round** = 更外层的策略迭代(goal round 等)。
### 5.3 主循环逐步拆解(源码:`packages/core/agent-loop/src/agent.ts` 的 `ReactLoopAgent`)
```text
turn/start ← 持久 session 事件
认领输入(inbox:next-turn 一条 + 全部 next-step)
组装 prompt sections + tool schemas(ctx.systemPrompt.assemble)
-> agent/pre-step(waterfall) ← 插件可改写/拒绝模型所见(compaction 压力检查挂这里)
step/start ← 持久
user/message(每条进入的消息) ← 持久
deriveMessages() 从日志投影出模型历史
agent/request(waterfall)-> llm/stream(waterfall)
-> assistant/chunk*(每个原始分片都落日志,token 级可回放)
-> assistant/message
tool/call*(先落日志再执行)
-> tools/pre-execute(waterfall:allow/deny/ask,权限/审批/沙箱挂这里)
-> tools/execute(超时等环绕关注点)
-> tools/post-execute(可改写/替换结果)
-> tool/result*(落日志)
step/end
若工具结果需要再次请求模型,或有 next-step 输入 -> 进入下一 step
-> agent/turn-stopping(serial,给插件最后一次 steer 机会)
turn/end
```
整个链条里**没有一个环节需要改 loop 代码**——所有产品功能都是挂在这些公开事件上的监听器(官方 extension-cookbook 里有一张"feature → mechanism 映射表",逐条验证"No row modifies the loop")。
几个精妙细节:
- **Inbox 双列表投递**:`followup(msg)` 排下一整轮;`steer(msg)` 注入最近的步骤边界、运行中的 driver 下一步就消费(中途引导是一等公民);`inject(msg)` 只注入上下文不唤醒。没有第二套消息通道;
- **并行工具调度但顺序落盘**:分发可并行(池上限 `maxParallelToolCalls`,默认 10),但 `tool/call`/`tool/result` 事件严格按模型输出顺序提交。abort 时已启动的调用排空、未启动的补写合成错误结果——**回放永远有效,不会留下无结果的悬空调用**;
- **每次请求可完全重建**:`request/header` 事件把请求信封(调用配置 + 渲染后的 system prompt + 组装出的 tool schemas)记入日志,replay 时逐字节重现请求。
---
## 6. 事件溯源会话:dsh 最硬核的设计
### 6.1 一句话架构
> **会话日志(append-only 的 `SessionEvent` log)是唯一事实源;模型消息历史是从日志派生的投影,从不单独存储。**
这是事件溯源(event sourcing)架构。与 LangGraph 的 checkpointer state、OpenAI Agents SDK 的内存 Session 列表是根本性差异。
`Session.deriveMessages()` 从日志**投影**出 `Message[]`;核心持久事件 12 种:`turn/start|end`、`step/start|end`、`user/message`、`assistant/chunk|message`、`tool/call|result`、`request/header|context`、`session/end-seed`。插件可通过 declaration merging 扩展(`compaction/*`、`hook/*`、`plan/mode`…)。
只有三种事件能进入模型历史("surface"):`user/message`、`assistant/message`、`tool/result`。`assistant/chunk` 只是回放/UI 数据。
### 6.2 铁律:Model-visible ⟺ Logged
> 任何进入模型请求的内容,必须能从日志重建——而且有运行时 invariant 断言它。新增 model-visible 输入 ⇒ 必须新增 session 事件。
这条规则带来的能力:**resume/fork/转录/遥测/调试全部从同一条事件流派生**。崩溃恢复也不截断日志——发现开着的 `turn/start` 无 `turn/end`,就追加一条合成的 `turn/end {reason:'interrupted'}` 配平,保留崩溃前已持久的全部工作。
### 6.3 Compaction(上下文压缩):不改写历史,而是"遮蔽"
这是和主流实现差别最大的一处,值得单独讲:
- Claude Code 的 compaction **重写**历史;LangGraph 的消息修剪直接**改 state**;
- dsh 的 compaction 是往日志追加 `compaction/start → compaction/summary + 一条带 replace 标记的摘要消息 → compaction/end`。**旧事件仍在日志里,只是被 surface 遮蔽**:面向人类的 transcript 能看到原文,模型历史读 surface 只看到摘要。压缩后历史依然完整可回放,连"摘要生成这次 LLM 调用本身"的原始输出也落日志。
触发路径:自动(每步 `agent/pre-step` 里的压力检查,先做确定性剪枝再决定要不要生成摘要;模型上下文溢出报错 → 压缩 → 自动重试同一请求)+ 手动(`/compact` 命令,可指定压缩范围,且保持工具调用/结果配对不被拆散)。
配套还有两个实用机制:
- **Token 计量**(`ctx.tokenMeter`):按 surface 节点逐一定价,是压力判断的数据源;
- **Spill**:超大工具输出外置到私有文件,结果替换为首尾预览 + 引用,模型可用 `read`/`grep` 按需取回——节约上下文。
### 6.4 存储后端
同一抽象 `ctx.sessionPersistence` 下两个 provider:
- **JSONL**:每会话一个仅追加日志,默认带 checksum 的 Zstandard 压缩帧,崩溃安全原子写;
- **SQLite**(`node:sqlite`):每个事件一行,行字段与事件 1:1 映射,支持按 seq 定位的尾部读。
`SESSION_FORMAT_VERSION = 0`(pre-release,不做兼容承诺);未知事件类型默认**拒绝读取**该日志而非静默丢弃(除非事件信封标了 `ignorable: true`)——宁可报错也不给你一份残缺历史的幻觉。
---
## 7. 能力接缝(Capability Seam):三段式插件分工
### 7.1 模式定义
dsh 里"新增一个能力"有固定三段式(这是仓库级约定,写进了根 AGENTS.md):
1. **Service Definition**:一个抽象 Cordis 服务(如 `ctx.shell`、`ctx.fs`、`ctx.llm`),只定义词汇和契约,不含实现。**必须是抽象类,不能是 TS interface**(interface 没有运行时实体);
2. **Service Provider**:可替换的实现插件。同一上下文只允许一个实现,加载第二个直接抛错;
3. **Consumer**:面向模型的工具或其他消费方。
关键推论:**换 provider 不改工具 schema、不改模型可见行为**。对比 LangGraph(工具=函数节点,provider 耦合在节点代码里)、OpenAI Agents SDK(tool 是带 `execute` 的对象)——dsh 把「能力的协议词汇」和「执行后端」显式拆开,后端可热替换。
### 7.2 范例:shell 接缝
```ts
// Service Definition(packages/shell/shell/src/index.ts)
declare module '@deepseek-ai/cordis' {
interface Context { shell: ShellExecutor }
}
export abstract class ShellExecutor extends Service { ... }
```
- Provider:`dsh-bash-local`(本地 bash)、`dsh-bash-sandbox`(沙箱 bash)、`dsh-pwsh-local`(PowerShell)——加载哪个由 cordis.yml 的一行决定;
- Consumer:`dsh-tool-bash`(模型可见的 bash 工具)、hook 桥等。
细节设计:`ShellExecRequest`(可选 workdir/timeout)必须经 `ctx.shell.resolve()` 变成全必填的 `ShellExecSpec`——仓库级规则「包边界显式优于隐式」,seam 内不允许隐藏的 `??` 默认值。
### 7.3 为什么这样设计:一次 provider 替换改变整个产品
最佳例证是 E2B 实验包:bash 执行器、PTY、LSP 都只依赖 `ctx.fs` + `ctx.subprocess` 两个基础 seam。把这两个 seam 的 provider 换成 E2B 云沙箱(`fs-e2b`、`subprocess-e2b`)后,**所有可变状态操作自动发生在同一个远程沙箱里**——Bash、PTY、LSP、子 agent 后端全部跟着搬走,不需要 fork 任何一行代码。
更极端的是 subagent seam:同一个 `ctx.subagents` 接口后面有六个 provider——`spawn-in-process`、`fork`、`acp`、`codex`、`claude-code`、`dsh-sdk`。也就是"dsh 可以把 Claude Code / Codex CLI 当子 agent 来委派任务"。
### 7.4 能力全景速览(约 60 个 seam,挑重点)
| 能力 | 说明 |
|---|---|
| `ctx.llm` | LLM 路由注册表 + 流式抽象;`llm-deepseek`(官方 API 直连)与 `llm-pi-ai`(多 provider,OpenAI 兼容端点是配置而非代码)双适配器互相验证协议 |
| `ctx.sandbox` | `confine(argv, policy)` 包装受限命令;后端:Linux bwrap/Landlock、macOS Seatbelt、Windows ACL;**fail-closed**,无后端直接报错,绝不静默透传 |
| `ctx.fs` | 写/编辑带乐观并发版本守卫;「先读后写」是独立策略插件(`fs-observation-policy`),删掉系统照样工作只是无约束 |
| `ctx.tools` | 带作用域的工具注册表 + 受保护执行管线 |
| `ctx.subagents` | 多 provider 委派注册表(见上) |
| `ctx.mcp` 系 | MCP client(仅 client,仅 tools;`mcp__<server>__<tool>` 命名与 Claude Code 一致) |
| `ctx.skills` | 兼容 Claude Code SKILL.md 格式的分层 provider 注册表,渐进式披露(先注入目录,模型按需加载正文) |
| `ctx.workflowEngine` | 模型**写一段 JS 编排脚本**动态启动 subagent(对应 Claude Code dynamic workflows) |
| `ctx.approval` | 审批服务,`ApprovalOutcome` 封闭联合,**fail-closed**:无应答者一律拒绝(适合 CI) |
| `ctx.settings` / `ctx.credentials` | 设置按 namespace 分节、热更新;凭据每次操作重新解析(热轮换,换 key 不重启) |
| `ctx.compaction` / `ctx.tokenMeter` / `ctx.spillStore` | 上下文管理三件套 |
| `ctx.jobs` / `ctx.schedule` | 后台任务统一运行时;会话内持久提醒(`schedule_create` 等工具) |
| `ctx.invariants` | **运行时不变量检查**:每个包发布一个 `./invariant` 配套插件,在专属 fiber 里断言自己拥有的运行时关系 |
---
## 8. 配置即组合:cordis.yml / bundle / profile / preset
### 8.1 cordis.yml 长什么样
真实例子(`examples/jsonrpc-agent/minimal.cordis.yml`,精简版):
```yaml
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
config:
apiKeyEnv: DEEPSEEK_API_KEY
models:
- id: !!js process.env.DSH_MODEL ?? 'deepseek-v4-flash'
contextWindow: !!js Number(process.env.DSH_CONTEXT_WINDOW ?? 1000000)
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
- id: sessions
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: !!js process.env.DSH_SESSION_ROOT ?? './.sessions'
```
要点:
- 每行 = 一个插件 entry:`id`(组合内唯一、可被补丁寻址)、`name`(npm 包名或绝对路径)、`config`(原样传给插件);
- `!!js` 标签:配置值里内嵌 JS 表达式,挂载时求值(`process.env`、平台判定常用于 `disabled:` 行级开关);
- **行顺序没有加载语义**——激活由 `inject` 依赖驱动,顺序只是给人看的分组;
- 补丁语义:`{id: X, config: {...}}` **整体替换**该行 config(不深合并);`{insert: [...]}` 追加新行;官方建议用 `disabled: true` 而不是删行——防止将来组合顺序调整时该行"悄悄复活"。
验证命令:`dsh --profile web --dump-config` 打印实际 boot 的完整树,**任何一行都能被你自己的 patch 替换**。
### 8.2 四层组合
```
空条目列表
← bundle 的 cordis.patch.yml(按 profile 声明顺序;dsh-base 永远第一层)
← profile 的 cordis.patch.yml($DSH_HOME/profiles/<name>/)
← home 级 cordis.patch.yml($DSH_HOME/,机器级偏好,优先级更高)
← --patch 命令行 overlay
```
- **Bundle**:一个 npm 包,manifest 声明 `dsh.bundle.patch`。内置三个:`dsh-base`(所有 profile 共享的核心:约 60 行插件,含模型适配器、全套工具、持久化、沙箱/审批、遥测——遥测默认关闭)、`dsh-web-app`、`dsh-headless`;
- **Profile**:`$DSH_HOME/profiles/<name>/` 目录 = package.json(有序 bundle 列表 + 插件依赖)+ 用户 patch。`dsh plugin add <package>` 就是往这里装 npm 包——**插件生态就是 npm 生态**。两个用户层都**热重载**:改 `cordis.patch.yml` 不用重启;
- **Preset(每会话组合)**:web 组合把 base 的模型面向工具行整体 disable,改由 `ctx.agentPresets` 把选定 preset 挂到**每个 agent 自己的 scope** 下——同一进程里不同会话可以跑不同工具/persona 组合(内置 standard / minimal / code / cordis 四个)。
对比:Claude Code 用 settings.json 分层(user/project/local),LangGraph 用代码构图;dsh 是**声明式 YAML 补丁栈 + npm 分发 + 每会话 scope 组合**,热重载是一等能力。
---
## 9. 动手:写你的第一个插件和工具
### 9.1 最小插件(10 行)
```ts
// 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!')
}
```
挂载 = 写一个 overlay patch(注意 patch 里 `name` 必须绝对路径):
```yaml
# scratch-plugin/cordis.yml
- insert:
- id: hello
name: '/absolute/path/to/scratch-plugin/src/my-plugin.ts'
```
```sh
pnpm dsh web --patch ./scratch-plugin/cordis.yml
```
生命周期是自动的:通过 `ctx` 注册的监听器/工具/定时器随插件卸载自动回收;显式资源用 `ctx.effect(() => { ...; return disposer })`。
### 9.2 加一个模型可见的工具
```ts
import { defineTool } from '@deepseek-ai/dsh-tools' // 工具 DSL
export const inject = ['tools'] // 等 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 })
},
}))
}
```
契约要点:
- `defineTool` 在 `execute` 前完成参数校验(不符抛 `INVALID_ARGS`);返回值必须符合 `output.schema` 的单一规范 JSON 值,`render` 负责模型可见文本;
- 必须尊重 `exec.signal`(取消协作链);
- **策略不放工具里**,用钩子:`tools/pre-execute`(allow/deny/ask 决策瀑布)、`tools/execute`(包裹做超时/重试)、`tools/post-execute`(改写结果);
- UI 展示是工具定义的一部分:`presentCall`/`presentResult` 返回协议中立的渲染意图(`generic`/`terminal`/`diff`/`search`/`read`/`web` 卡片),必须是纯函数(流式和回放都会调用)。
---
## 10. 生态互操作:MCP、ACP、Claude Code / Codex 桥、Skills、SDK
dsh 对现有生态的姿态是"直接站在上面,不另起炉灶":
- **MCP**:做 **client**(不做 server,且只桥 tools 能力)。每个 MCP server 一个插件实例,stdio / streamable-http 两种传输;工具以 `mcp__<serverName>__<tool>` 注册(与 Claude Code/Codex 命名一致);断线指数退避重连,配置热编辑且工具名逐字节稳定(保 KV cache 前缀);
- **ACP**:做 **server**——把 dsh agent 暴露给别的 ACP 客户端(自动化场景),stdio JSON-RPC,`pnpm run demo:acp` 可跑;
- **Hooks 桥**:`dsh-hooks-claude-code` 读你的 `hooks.json`(支持 7 个事件:`SessionStart/UserPromptSubmit/PreToolUse/PostToolUse/Stop/SubagentStart/SubagentStop`),`dsh-hooks-codex` 支持 5 个——把你已有的 Claude Code/Codex hook 配置映射到 dsh 的事件扩展点上,迁移成本被刻意压低。官方态度明确:原生插件更强,桥只是兼容路径;
- **Skills**:兼容 Claude Code 的 SKILL.md 格式(连 `disable-model-invocation`/`user-invocable` frontmatter 键都同名),扫描根约定对齐 CC(`<project>/.agents/skills` 等),但做成可注册 provider(远程 registry 是同级 provider),渐进式披露(先注入只含 name+description 的目录,模型用 `skill({name})` 工具按需加载正文);
- **JSON-RPC SDK**:stdio 一行一帧的 JSON-RPC 2.0,Python SDK(免 Node)+ TS client;
- **权限/沙箱词汇对齐 Codex**:`read-only` / `workspace-write` / `danger-full-access` 三档。
另一个方向:dsh 也能**消费**别家 agent——subagent seam 的 provider 列表里有 `codex` 和 `claude-code`。
---
## 11. 与主流 Agent 框架的正面对比(重头戏)
### 11.1 抽象模型总览
| | 核心抽象 | loop 归属 | 组合发生在 | 状态模型 |
|---|---|---|---|---|
| **LangGraph** | 有向图(StateGraph:节点+边+共享状态) | **你拥有**(图是你画的) | 编译期(图拓扑固定) | checkpointer 状态快照 |
| **OpenAI Agents SDK** | Agent + Handoff + Guardrails(三个半原语) | SDK 的 `Runner` | 对象组合(Agent 持有 tools/handoffs 引用) | 内存 Session 列表 |
| **Claude Agent SDK** | Claude Code 抽出的成品 loop | 产品方固定 | 外挂式扩展(MCP/skills/hooks) | CLI 内部 |
| **Google ADK** | Agent + Runner + 层级委派;MCP+A2A 双协议 | Runner 驱动 | 代码组装 | Session 持久化 |
| **dsh** | **插件内核(Cordis)+ 事件溯源日志** | **loop 本身是可替换插件** | **运行时**(可逆注册 + 热重载) | append-only 事件日志 + surface 投影 |
一句话版:LangGraph 是**图**(显式状态机),OpenAI Agents SDK 是 **handoff**(控制权转移的隐式图),Claude Agent SDK 是**产品抽出的 loop**(loop 固定、边缘可扩展),dsh 是**插件内核**(loop 可换、扩展点深入内核,代价是 API 未稳定、生态实现尚缺)。
### 11.2 逐维度对比
**会话与状态**
- LangGraph:checkpoint 存状态,支持中断-恢复、time-travel;
- OpenAI Agents SDK:Session 是会话状态的内存/存储列表;
- dsh:append-only 事件日志是唯一真源,消息历史是投影;崩溃恢复不截断(合成 `interrupted` 配平);fork/resume/转录/遥测同源;每个请求(配置+system prompt+工具 schema 快照)都可从日志逐字节重建。**可观测性和可回放性上 dsh 最激进**,代价是实现复杂度。
**工具系统**
- LangGraph / OpenAI SDK:工具是塞给 agent 的可调用对象/函数;
- dsh:工具(Consumer)与能力(Provider)分离;工具定义强制带规范输出 schema + 纯函数渲染意图(UI 卡片是协议中立的可辨识联合);执行管线是五段 waterfall(pre-execute 决策 → guards → execute 环绕 → post-execute 改写 → result 冻结),策略全部外挂。
**扩展方式**
- Claude 系:MCP server + SKILL.md + hooks + plugin 目录——约定优于配置的"外挂式"扩展;
- dsh:内核级 DI 插件——扩展点深入 loop/session/sandbox/model 本身,同时**也**支持 MCP/skills/hooks(甚至直接桥接 Claude Code/Codex 的 hooks 配置)。可以说 dsh 把 Claude Code 的内置行为全部外化成了可替换 provider + 类型化扩展点。
**上下文管理**
- Claude Code compaction 重写历史;LangGraph 修剪改 state;
- dsh:compaction 是日志上的 surface 遮蔽(原文仍在,人类 transcript 可见),外加确定性剪枝、token 计量、spill 外置——而且整个机制是可选插件。
**多 Agent**
- OpenAI Agents SDK:handoff(控制权转移)+ agents-as-tools;
- Google ADK:层级委派 + A2A 协议;
- dsh:`ctx.subagents` 多 provider 委派(进程内/fork/ACP/Codex/Claude Code/dsh-sdk 六种后端)+ 模型自写 JS 编排脚本的 `workflow` 工具——"流程编排"在 dsh 里是模型自己写的脚本,而非开发者画的图。
**人机协作与权限**
- 都有审批/权限概念;dsh 的特点是全程 **fail-closed**:审批无应答者一律拒绝(适合 CI)、沙箱无后端直接报错、`ask` 决策没有审批通道一律拒绝。错误处理用稳定机器码(`FS_STALE_VERSION`、`WEB_PROVIDER_AMBIGUOUS`…)而非异常文本。
### 11.3 与 Claude Code / Codex CLI 的使用体验对比
相同点:都有 headless 模式(`dsh --profile headless "task"` ⇄ `claude -p` / `codex exec`)、都支持 MCP/skills/subagent/plan mode/上下文压缩、权限档位名字几乎照抄 Codex、都有家目录(`~/.dsh` ⇄ `~/.claude`/`~/.codex`)。
不同点:
1. **Web UI 是产品主入口**,没有交互式终端 TUI(CC/Codex 终端优先);
2. **配置即组合**:cordis.yml 补丁栈可寻址、可禁用、可整体替换、热重载、`--dump-config` 离线审查;vs settings.json 层级合并;
3. **每会话 preset**:同一进程不同会话跑不同工具/persona 组合;
4. **协议面更宽**:同一内核同时暴露 Web(自研 Typert RPC + SSE)、ACP server、stdio JSON-RPC 三种前端;
5. 模型生态:默认围绕 DeepSeek(`deepseek-official` 路由),经 `llm-pi-ai` 支持任意 OpenAI 兼容端点;发布日**没有** Anthropic/OpenAI 官方 provider 插件——"接口存在,实现大多还不存在"。
### 11.4 什么时候选谁(决策建议)
- 你要**精细控制编排逻辑**、把 agent 嵌入自己的产品、需要成熟的 Python 生态 → **LangGraph**;
- 你在 OpenAI 生态里、要最小心智负担做多 agent 移交 → **OpenAI Agents SDK**;
- 你要的是"Claude Code 的能力,嵌入我的程序" → **Claude Agent SDK**;
- 你在 Google Cloud/Gemini 生态、需要 A2A 跨组织 agent 协作 → **Google ADK**;
- 你在 DeepSeek 生态里做**可复现评测/benchmark**(minimal 组合就是为此设计的)、要研究或改造 harness 内核本身、想要"每个部件都能换"的实验台、或者想复用 Claude Code/Codex 的 hooks/skills 资产但换模型供应商 → **dsh**。它是目前唯一一个把 harness 内核本身当作插件系统暴露出来的开源实现。
---
## 12. 工程实践亮点:普通项目也值得抄的作业
即使你不用 dsh,这些实践也值得看:
1. **运行时不变量(`ctx.invariants`)**:每个包发布一个 `./invariant` 配套插件,在生产运行时断言自己拥有的关系(轮次编号、工具调用配对、审批审计配对……),把测试期断言搬进运行时;
2. **文档即代码**:每个包 README 必须含规定格式的 `## Model Experience`(`What the model sees`/`Token effect`/`KV Cache effect` 三个小节)和 `## Known Limitations` 节,由校验脚本强制——目的是让 LLM/agent 能可靠消费文档;tool-catalog/config-catalog/module-graph 全部从源码生成 + CI 新鲜度校验;
3. **快照测试体系**:无 key 的 ACP/headless 回放快照(`pnpm run test:snapshot`),真实 API e2e 无 key 自动跳过——评测可复现性是设计出来的(BENCHMARK.md 只提交复现路径,不提交分数);
4. **fail-closed 安全姿态**:审批、沙箱、权限、未知 session 事件——所有默认都是拒绝,宁可报错不给幻觉;
5. **遥测开关"宁可误关"**:`DSH_TELEMETRY_DISABLED` 任何非空值(包括 `'0'`/`'false'`)都算禁用。
---
## 13. 现状、短板与适用判断
**短板(2026-08,发布当日视角):**
- Developer Preview,无 tagged release,API 会有破坏性变更,不要用于严肃生产;
- 无交互式终端 TUI,终端党只能等社区或官方补;
- 模型 provider 只有两个(DeepSeek 官方 + pi-ai 多路由),生态实现大量缺失;
- Cordis 对社区是全新事物(知乎高赞:"说实话之前我根本没听说过这东西"),学习成本真实存在;
- 插件生态(`dsh-plugin` topic)刚起步。
**值得跟踪的信号(未来 90 天)**:第三方 provider 插件是否出现、首个 tagged release、`dsh-plugin` topic 规模、dsh 下的 SWE-bench 公开数字。如果第三方 provider 出现,dsh 就从"DeepSeek 配套产品"变成"基础设施"。
---
## 14. 附录:能力地图与关键默认值速查
### 14.1 仓库布局
```
vendor/ vendored Cordis 源码(18 条成文本地修改,见 vendor/README.md)
packages/ @deepseek-ai/dsh-<pkg>,约 50 个包按能力分组
core/ session / system-prompt / tools / agent / agent-loop / scope
llm/ shell/ fs/ web/ subagent/ skill/ mcp/ hooks/ … 各能力 seam
bundle/ base / web-app / headless 三个组合层
sdk/ acp/ api/ typert/ 协议与网关
apps/ cli(dsh 启动器)、web(Vite + React 前端壳)
examples/ headless-agent / jsonrpc-agent / acp-agent / mcp-memory / web-cordis / web-schedule
python/ deepseek-harness-sdk + deepseek-harness-runtime-bin
docs/ 全双语;catalog 类为生成文件
```
### 14.2 关键默认值
| 项 | 值 |
|---|---|
| Web UI | `http://127.0.0.1:3080`(demo:cordis web 面用 3081) |
| Harness home | `$DSH_HOME`,未设则 `~/.dsh` |
| `SESSION_FORMAT_VERSION` | `0`(无兼容承诺) |
| 并行工具调用上限 | `DEFAULT_MAX_PARALLEL_TOOL_CALLS = 10` |
| 每 owner 后台任务上限 | 10 |
| 定时提醒最小区隔 | 5 分钟(无 cron,只有 after/at/every) |
| DeepSeek 默认上下文 | 1,000,000 tokens;`maxTokens` 默认 256,000 |
| 权限三档 | `read-only` / `workspace-write` / `danger-full-access` |
| 遥测 | 默认关闭;`DSH_TELEMETRY_DISABLED` 任何非空值都算关 |
| API key 环境变量 | `DEEPSEEK_API_KEY`(可选 `DEEPSEEK_BASE_URL`) |
### 14.3 系统提示词组装约定
段落按 `order` 排序:**-100 = harness 身份,0 = persona(`deployment:persona`),50 = plan mode 策略,100–199 = 工具指引**。scoped 段落/变量遮蔽同名全局。每步重新组装——工具集/提示词热更新即时生效。易变运行时状态(审批策略、plan 状态等)走独立的"runtime context 快照"通道(作为 user-role 消息追加),保持 system prompt 稳定以命中 provider 侧 prompt cache。
### 14.4 内置工具一览(按包)
- `dsh-tool-fs`:`read` / `write` / `edit` / `read_image`;`dsh-tool-fs-search`:`glob` / `grep`(内置 ripgrep)
- `dsh-tool-bash` / `-pwsh` / `dsh-tool-terminal`:bash / pwsh / 持久 PTY(`terminal_open` 等)
- `dsh-tool-subagent` 系:`subagent` / `send_message` / `interrupt_agent` / `list_agents` / `report`
- `dsh-tool-web`:`web_search` / `web_fetch`;`dsh-tool-todo`:`todo_write`;`dsh-plan-mode`:`exit_plan_mode`
- `dsh-tool-ask-user`:`ask_user_question`;`dsh-tool-jobs`:`job_list` / `job_output` / `job_kill`
- `dsh-tool-workflow` / `-ralph` / `-goal` / `-schedule` / `-lsp` / `-skill` / `-session-query` / `-cordis`:编排与自省工具族
### 14.5 进一步阅读(仓库内)
- `docs/architecture.md` — 架构总纲(改 `packages/` 前官方要求必读)
- `docs/cordis-primer.md` — Cordis 入门
- `docs/capability-seams.md` — 生成版能力接缝全图
- `docs/agent-lifecycle.md`、`docs/tool-execution-pipeline.md` — 生命周期与工具管线
- `docs/cookbook/extension-cookbook.md` — "feature → 扩展点"映射表(微内核论断的可检验清单)
- `docs/cookbook/adding-a-tool.md` / `adding-an-llm-adapter.md` — 加工具 / 加模型适配器
- `docs/subsystems/*.md` — 约 40 个子系统各一份详解(全双语)
- `AGENTS.md`(根目录)— 本身就是一份高密度工程规约,值得通读
---
## 15. 实操示例集(可复制运行)
以下示例文件都在本仓库 `examples/` 目录下,配置格式均在公开发布版上核对过;标注「摘自官方」的文件来自 `deepseek-ai/deepseek-harness` 的 `examples/` 目录。
### 15.1 给 Web 组合加「定时提醒」能力([`examples/schedule-overlay.cordis.yml`](examples/schedule-overlay.cordis.yml),摘自官方)
```yaml
- insert:
- id: time-context
name: '@deepseek-ai/dsh-time-context'
- id: schedule
name: '@deepseek-ai/dsh-schedule'
```
```sh
dsh web --patch examples/schedule-overlay.cordis.yml
```
挂载后模型多出 `schedule_create` / `schedule_list` / `schedule_delete` 三个工具(支持 `after_seconds` 延时与绝对 `at` 时间)。**这就是一个完整的功能扩展——两行 YAML,零代码。**
### 15.2 接入 MCP 记忆服务([`examples/mcp-memory.cordis.yml`](examples/mcp-memory.cordis.yml),摘自官方)
```yaml
- insert:
- id: memory-mcp-reference
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: reference_memory
transport: stdio
command: mcp-server-memory
cwd: !!js process.cwd()
```
工具以 `mcp__reference_memory__<tool>` 注册(与 Claude Code 命名一致);断线指数退避重连,配置热编辑时工具名逐字节稳定(保 KV cache 前缀)。
### 15.3 最小自定义插件([`examples/my-first-plugin/`](examples/my-first-plugin/))
一个导出 `apply(ctx)` 的 TS 模块 + 一个 `insert` overlay,就能给 agent 加新工具。完整代码见目录,核心 20 行(第 9 章有逐行讲解):
```sh
dsh web --patch examples/my-first-plugin/cordis.yml # 源码检出内用 pnpm dsh
```
### 15.4 接入任意 OpenAI 兼容网关([`examples/custom-provider.settings.yaml`](examples/custom-provider.settings.yaml),摘自官方文档)
合并进 `$DSH_HOME/settings.yaml`,热生效不重启:
```yaml
llm-pi-ai:
providers:
my-gateway:
apiKeyEnv: GATEWAY_API_KEY
api: openai-completions
baseURL: https://gateway.example/v1
models:
- id: legacy-chat
- id: vision-preview
input: [text, image] # 手写模型默认按纯文本处理,多模态要显式声明
```
也可以在 **Settings → Models → Add provider** 里接 Anthropic/OpenAI 目录供应商,全程界面操作。
### 15.5 Python SDK 无人值守任务([`examples/python-sdk-demo.py`](examples/python-sdk-demo.py))
```python
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness(provider="deepseek-official", model="deepseek-v4-flash",
max_tokens=49_152, cwd="/path/to/repo") as harness:
result = harness.run("Inspect the repository and fix the failing tests.",
session_id="example-001")
print(result.final_response)
```
装 `deepseek-harness-sdk` 会自动带同版本运行时 wheel,**目标机器无需 Node.js**。官方 BENCHMARK.md 的评测复现路径就是这套 minimal 组合。
---
## 16. FAQ 高频问题速答
**Q:DeepSeek Harness 是什么?和 DeepSeek 模型是什么关系?**
A:DeepSeek Harness(`dsh`)是 DeepSeek 官方开源的 Agent Harness——跑在模型「外面」的 Agent 运行时骨架(工具、上下文管理、模型-工具循环),MIT 协议。用官方招聘 JD 的话说:「除模型本身以外的所有工作,都属于 Harness 的范畴」。它是 DeepSeek-V4 系列模型官方 Code Agent 基准测试所使用的脚手架。
**Q:DeepSeek Harness 是 Agent 框架吗?和 LangGraph 这类框架什么区别?**
A:官方自我定位是 harness 而不是 framework/SDK。区别在 loop 的归属:框架(LangGraph、OpenAI Agents SDK)给你构件、loop 是你的代码;harness 给你一个配置好的完整运行时。dsh 的特殊之处是把 harness 内核本身做成了插件系统——连 agent loop 都是可替换插件。
**Q:DeepSeek Harness 只能用 DeepSeek 模型吗?**
A:不是。默认围绕 DeepSeek(`deepseek-official` 路由),但通过 `llm-pi-ai` 适配器可以在 Settings → Models 里添加 Anthropic/OpenAI 目录供应商,或接任意 OpenAI 兼容网关(自托管 vLLM、公司网关、第三方中转),见 15.4。
**Q:DeepSeek Harness 有命令行终端交互界面(TUI)吗?**
A:截至 2026-08 公开发布版:没有。产品主入口是 Web UI(`npx @deepseek-ai/dsh web`,`http://127.0.0.1:3080`);`dsh` CLI 是启动器,支持 headless 一次性任务(`dsh --profile headless "task"`),但官方未发布类 Claude Code 的常驻终端对话界面。
**Q:DeepSeek Harness 支持 MCP 吗?**
A:支持,作为 MCP **client**(暂不做 server,且只桥接 tools 能力)。每个 MCP server 一个插件实例,stdio / streamable-http 两种传输,工具以 `mcp__<serverName>__<tool>` 命名注册(与 Claude Code 一致)。配置示例见 15.2。
**Q:DeepSeek Harness 和 Claude Code 有什么区别?**
A:体验上:dsh 是 Web UI 优先(Claude Code 终端优先);dsh 没有交互式 TUI。架构上:Claude Code 的 loop 固定在二进制里、扩展靠 MCP/skills/hooks 外挂;dsh 把一切(loop、工具、权限、压缩、模型适配器)都做成可替换插件,并且可以直接桥接复用 Claude Code 的 hooks.json 与 SKILL.md 生态资产。能力词汇(权限档位、skill 格式、动态 workflow)刻意与 Claude Code/Codex 对齐。
**Q:DeepSeek Harness 和 LangGraph 怎么选?**
A:要精细控制编排逻辑、把 agent 嵌入自己的产品、要成熟 Python 生态 → LangGraph。要用 DeepSeek 模型做可复现评测、研究或改造 harness 内核、要「每个部件都能换」的实验台 → dsh。两者抽象不同:LangGraph 是显式状态图(你拥有 loop),dsh 是事件溯源日志 + 插件内核(loop 是可替换插件)。
**Q:如何给 DeepSeek Harness 写插件?**
A:插件就是一个导出 `apply(ctx, config)` 的 TypeScript 模块(也支持类/对象形态),通过 `ctx.tools.register()`、`ctx.on()` 等 effect 注册贡献,卸载时自动清理。挂载方式是写一个 `insert` overlay YAML 后用 `dsh web --patch` 叠加。最小完整例子见第 9 章和 `examples/my-first-plugin/`。发布到 npm 并打 `dsh-plugin` topic 即可被生态发现。
**Q:DeepSeek Harness 的上下文压缩(compaction)是怎么工作的?**
A:事件溯源方案:压缩不是改写历史,而是向 append-only 会话日志追加 `compaction/*` 事件 + 一条带 replace 标记的摘要消息;旧事件仍在日志里(人类 transcript 可见原文),模型历史读 surface 投影(看到摘要)。支持自动压力触发(含确定性剪枝优先)、上下文溢出自动压缩重试、手动 `/compact` 指定范围。详见第 6 章。
**Q:DeepSeek Harness 可以商用吗?**
A:可以,MIT 协议。但注意当前是 Developer Preview,官方明确承诺会有破坏性变更,生产使用需自行评估。
**Q:什么是 Cordis?**
A:dsh 的底层插件框架(vendored 在 `vendor/cordis`),源自聊天机器人框架 Koishi 久经验证的插件内核,设计依据论文《A Programming Paradigm for Spatiotemporal Composability》——时间可组合性(插件副作用可完全撤销)+ 空间可组合性(依赖声明式表达、反应式管理)。详见第 4 章。
---
*教程完。如有事实性修正(这个项目迭代极快),以仓库最新文档为准。*
连接信息
猜你喜欢
暂无推荐服务器