DeepSeek Harness(dsh)保姆级理解教程:架构、插件体系与主流 Agent 框架对比
August 13, 2026 · View on GitHub
English: A hands-on, source-code-level guide to DeepSeek Harness (
dsh) — DeepSeek's open-source, MIT-licensed agent harness where everything is a plugin (built on the vendored Cordis framework). Covers the event-sourced session log, the capability-seam plugin pattern, thecordis.ymlcomposition 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.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/为准。
目录
- 它是什么:先搞懂「Agent Harness」这个概念
- 五分钟跑起来(含真实界面截图)
- 核心心智模型:一切皆插件
- Cordis 框架速成:五个概念读懂 dsh 的地基
- 架构总览:一次请求从出生到落盘的完整旅程
- 事件溯源会话:dsh 最硬核的设计
- 能力接缝(Capability Seam):三段式插件分工
- 配置即组合:cordis.yml / bundle / profile / preset
- 动手:写你的第一个插件和工具
- 生态互操作:MCP、ACP、Claude Code / Codex 桥、Skills、SDK
- 与主流 Agent 框架的正面对比(重头戏)
- 工程实践亮点:普通项目也值得抄的作业
- 现状、短板与适用判断
- 附录:能力地图与关键默认值速查
- 实操示例集(可复制运行)
- 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(产品主入口)
# 只需要 Node.js(^22.19 或 >=24)
npx @deepseek-ai/dsh web
浏览器打开 http://127.0.0.1:3080,然后:
- Settings → Models 填入你的 DeepSeek API Key(热生效,不重启;写入
$DSH_HOME/settings.yaml的llm-deepseek:段,密钥本体存$DSH_HOME/.credentials.yaml); - 选择一个 workspace(工作目录);
- 开会话,跑任务。
实拍:启动后的首页(本教程全部截图均为本机真实运行截取,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 一次性任务
dsh --profile headless "fix the failing test"
不开任何监听端口,stdout 打印最终回答;任务完成退出码 0,否则 1。适合 CI 和脚本。
2.3 方式三:Python SDK(目标机器无需 Node.js)
python -m pip install deepseek-harness-sdk
装 SDK 会自动带上同版本的 deepseek-harness-runtime-bin 平台 wheel(内置单文件可执行 dsh-jsonrpc-agent,自带全部插件,不需要装 Node;支持 Linux x64/arm64、macOS 14+ arm64):
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 方式四:从源码跑(想改代码/读源码的话)
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:
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:
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> 的基类
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 中间件
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)
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 的
SessionEventlog)是唯一事实源;模型消息历史是从日志派生的投影,从不单独存储。
这是事件溯源(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):
- Service Definition:一个抽象 Cordis 服务(如
ctx.shell、ctx.fs、ctx.llm),只定义词汇和契约,不含实现。必须是抽象类,不能是 TS interface(interface 没有运行时实体); - Service Provider:可替换的实现插件。同一上下文只允许一个实现,加载第二个直接抛错;
- Consumer:面向模型的工具或其他消费方。
关键推论:换 provider 不改工具 schema、不改模型可见行为。对比 LangGraph(工具=函数节点,provider 耦合在节点代码里)、OpenAI Agents SDK(tool 是带 execute 的对象)——dsh 把「能力的协议词汇」和「执行后端」显式拆开,后端可热替换。
7.2 范例:shell 接缝
// 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,精简版):
- 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 行)
// 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 必须绝对路径):
# scratch-plugin/cordis.yml
- insert:
- id: hello
name: '/absolute/path/to/scratch-plugin/src/my-plugin.ts'
pnpm dsh web --patch ./scratch-plugin/cordis.yml
生命周期是自动的:通过 ctx 注册的监听器/工具/定时器随插件卸载自动回收;显式资源用 ctx.effect(() => { ...; return disposer })。
9.2 加一个模型可见的工具
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-invocablefrontmatter 键都同名),扫描根约定对齐 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)。
不同点:
- Web UI 是产品主入口,没有交互式终端 TUI(CC/Codex 终端优先);
- 配置即组合:cordis.yml 补丁栈可寻址、可禁用、可整体替换、热重载、
--dump-config离线审查;vs settings.json 层级合并; - 每会话 preset:同一进程不同会话跑不同工具/persona 组合;
- 协议面更宽:同一内核同时暴露 Web(自研 Typert RPC + SSE)、ACP server、stdio JSON-RPC 三种前端;
- 模型生态:默认围绕 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,这些实践也值得看:
- 运行时不变量(
ctx.invariants):每个包发布一个./invariant配套插件,在生产运行时断言自己拥有的关系(轮次编号、工具调用配对、审批审计配对……),把测试期断言搬进运行时; - 文档即代码:每个包 README 必须含规定格式的
## Model Experience(What the model sees/Token effect/KV Cache effect三个小节)和## Known Limitations节,由校验脚本强制——目的是让 LLM/agent 能可靠消费文档;tool-catalog/config-catalog/module-graph 全部从源码生成 + CI 新鲜度校验; - 快照测试体系:无 key 的 ACP/headless 回放快照(
pnpm run test:snapshot),真实 API e2e 无 key 自动跳过——评测可复现性是设计出来的(BENCHMARK.md 只提交复现路径,不提交分数); - fail-closed 安全姿态:审批、沙箱、权限、未知 session 事件——所有默认都是拒绝,宁可报错不给幻觉;
- 遥测开关"宁可误关":
DSH_TELEMETRY_DISABLED任何非空值(包括'0'/'false')都算禁用。
13. 现状、短板与适用判断
短板(2026-08,发布当日视角):
- Developer Preview,无 tagged release,API 会有破坏性变更,不要用于严肃生产;
- 无交互式终端 TUI,终端党只能等社区或官方补;
- 模型 provider 只有两个(DeepSeek 官方 + pi-ai 多路由),生态实现大量缺失;
- Cordis 对社区是全新事物(知乎高赞:"说实话之前我根本没听说过这东西"),学习成本真实存在;
- 插件生态(
dsh-plugintopic)刚起步。
值得跟踪的信号(未来 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/reportdsh-tool-web:web_search/web_fetch;dsh-tool-todo:todo_write;dsh-plan-mode:exit_plan_modedsh-tool-ask-user:ask_user_question;dsh-tool-jobs:job_list/job_output/job_killdsh-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,摘自官方)
- insert:
- id: time-context
name: '@deepseek-ai/dsh-time-context'
- id: schedule
name: '@deepseek-ai/dsh-schedule'
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,摘自官方)
- 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/)
一个导出 apply(ctx) 的 TS 模块 + 一个 insert overlay,就能给 agent 加新工具。完整代码见目录,核心 20 行(第 9 章有逐行讲解):
dsh web --patch examples/my-first-plugin/cordis.yml # 源码检出内用 pnpm dsh
15.4 接入任意 OpenAI 兼容网关(examples/custom-provider.settings.yaml,摘自官方文档)
合并进 $DSH_HOME/settings.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)
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 章。
教程完。如有事实性修正(这个项目迭代极快),以仓库最新文档为准。