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, 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.

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.mddocs/ 为准。


目录

  1. 它是什么:先搞懂「Agent Harness」这个概念
  2. 五分钟跑起来(含真实界面截图)
  3. 核心心智模型:一切皆插件
  4. Cordis 框架速成:五个概念读懂 dsh 的地基
  5. 架构总览:一次请求从出生到落盘的完整旅程
  6. 事件溯源会话:dsh 最硬核的设计
  7. 能力接缝(Capability Seam):三段式插件分工
  8. 配置即组合:cordis.yml / bundle / profile / preset
  9. 动手:写你的第一个插件和工具
  10. 生态互操作:MCP、ACP、Claude Code / Codex 桥、Skills、SDK
  11. 与主流 Agent 框架的正面对比(重头戏)
  12. 工程实践亮点:普通项目也值得抄的作业
  13. 现状、短板与适用判断
  14. 附录:能力地图与关键默认值速查
  15. 实操示例集(可复制运行)
  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(产品主入口)

# 只需要 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.yamlllm-deepseek: 段,密钥本体存 $DSH_HOME/.credentials.yaml);
  2. 选择一个 workspace(工作目录);
  3. 开会话,跑任务。

实拍:启动后的首页(本教程全部截图均为本机真实运行截取,npx @deepseek-ai/dsh web,macOS):

DeepSeek Harness Web UI 首页:New Session 卡片、workspace 选择器、preset(Standard mode)、权限档位(Workspace Write)与模型选择器(DeepSeek-V4-Pro)

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

Settings → Models:DeepSeek 供应商卡片与 Add provider / Add a custom provider 入口

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

Settings → Plugins:部署中已安装插件的配置与检查界面

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

Settings → General:默认 agent preset、默认权限模式、语言与外观设置

Settings → Agent presets:可选的每会话 agent 组合(Standard mode 等)

注意一个和直觉相反的点是:dsh 没有 Claude Code 那种终端交互式 TUIdsh CLI 只是个启动器,官方模板只有 webheadless 两个 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 typecheckpnpm 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):

新建会话卡片:选择 workspace、agent preset、权限档位与模型

运行中(第 8 秒抓拍)。注意图里的几个细节,每一个都对应后文的一个架构概念:

  • 两条 Context injection@deepseek-ai/dsh-system-promptskill-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——会话遥测从同一条事件流派生。

Agent 运行中:context 注入、模型重试、工具卡片与实时遥测

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

任务完成:完整对话流(思考、工具调用、最终回答与遥测页脚)

失败测试输出展开:terminal 渲染卡片与修复说明

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

Trajectory 视图:token 构成条与 Turn 内 SYSTEM/USER/CONTEXT/ASSISTANT/TOOL 事件序列


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-agentAgent 接口和 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.tsContext 构造时返回 new Proxy(this, ReflectService.handler)。你写的 ctx.tools.register(...),属性读取走的是服务解析。

关键操作:

  • ctx.extend() / ctx.isolate(name) / ctx.intercept():创建原型继承的子 context,不改父级。isolate 为某个服务名开辟独立解析域——两个会话可以各挂各的 provider 实现而不污染根组合(per-session preset 靠的就是它);
  • 内置四个核心服务:ctx.eventsctx.loggerctx.reflectctx.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/resultsession/event
parallel并发等待全部落盘检查点(session/flush
serial顺序 await,首个有效返回值即终止决策类(agent/turn-stopping
waterfallaround 中间件:listener 收 (...args, next),调 next() 委托下游,不调则短路拦截改写(agent/pre-stepagent/requestllm/streamtools/pre-execute

dsh 硬规则:waterfall listener 必须调 next(),除非该 listener 就是决策者(比如审批插件决定 deny)。模式是事件公共契约的一部分,JSDoc @mode 标注,静态校验。

类型安全靠 TypeScript declaration merging:插件往 @deepseek-ai/cordisEvents 接口 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.tsReactLoopAgent

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|endstep/start|enduser/messageassistant/chunk|messagetool/call|resultrequest/header|contextsession/end-seed。插件可通过 declaration merging 扩展(compaction/*hook/*plan/mode…)。

只有三种事件能进入模型历史("surface"):user/messageassistant/messagetool/resultassistant/chunk 只是回放/UI 数据。

6.2 铁律:Model-visible ⟺ Logged

任何进入模型请求的内容,必须能从日志重建——而且有运行时 invariant 断言它。新增 model-visible 输入 ⇒ 必须新增 session 事件。

这条规则带来的能力:resume/fork/转录/遥测/调试全部从同一条事件流派生。崩溃恢复也不截断日志——发现开着的 turn/startturn/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 压缩帧,崩溃安全原子写;
  • SQLitenode: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.shellctx.fsctx.llm),只定义词汇和契约,不含实现。必须是抽象类,不能是 TS interface(interface 没有运行时实体);
  2. Service Provider:可替换的实现插件。同一上下文只允许一个实现,加载第二个直接抛错;
  3. 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-e2bsubprocess-e2b)后,所有可变状态操作自动发生在同一个远程沙箱里——Bash、PTY、LSP、子 agent 后端全部跟着搬走,不需要 fork 任何一行代码。

更极端的是 subagent seam:同一个 ctx.subagents 接口后面有六个 provider——spawn-in-processforkacpcodexclaude-codedsh-sdk。也就是"dsh 可以把 Claude Code / Codex CLI 当子 agent 来委派任务"。

7.4 能力全景速览(约 60 个 seam,挑重点)

能力说明
ctx.llmLLM 路由注册表 + 流式抽象;llm-deepseek(官方 API 直连)与 llm-pi-ai(多 provider,OpenAI 兼容端点是配置而非代码)双适配器互相验证协议
ctx.sandboxconfine(argv, policy) 包装受限命令;后端:Linux bwrap/Landlock、macOS Seatbelt、Windows ACL;fail-closed,无后端直接报错,绝不静默透传
ctx.fs写/编辑带乐观并发版本守卫;「先读后写」是独立策略插件(fs-observation-policy),删掉系统照样工作只是无约束
ctx.tools带作用域的工具注册表 + 受保护执行管线
ctx.subagents多 provider 委派注册表(见上)
ctx.mcpMCP 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-appdsh-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 })
    },
  }))
}

契约要点:

  • defineToolexecute 前完成参数校验(不符抛 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;
  • 权限/沙箱词汇对齐 Codexread-only / workspace-write / danger-full-access 三档。

另一个方向:dsh 也能消费别家 agent——subagent seam 的 provider 列表里有 codexclaude-code


11. 与主流 Agent 框架的正面对比(重头戏)

11.1 抽象模型总览

核心抽象loop 归属组合发生在状态模型
LangGraph有向图(StateGraph:节点+边+共享状态)你拥有(图是你画的)编译期(图拓扑固定)checkpointer 状态快照
OpenAI Agents SDKAgent + Handoff + Guardrails(三个半原语)SDK 的 Runner对象组合(Agent 持有 tools/handoffs 引用)内存 Session 列表
Claude Agent SDKClaude Code 抽出的成品 loop产品方固定外挂式扩展(MCP/skills/hooks)CLI 内部
Google ADKAgent + 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_VERSIONWEB_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 ExperienceWhat 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 UIhttp://127.0.0.1:3080(demo:cordis web 面用 3081)
Harness home$DSH_HOME,未设则 ~/.dsh
SESSION_FORMAT_VERSION0(无兼容承诺)
并行工具调用上限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-fsread / write / edit / read_imagedsh-tool-fs-searchglob / 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-webweb_search / web_fetchdsh-tool-todotodo_writedsh-plan-modeexit_plan_mode
  • dsh-tool-ask-userask_user_questiondsh-tool-jobsjob_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.mddocs/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-harnessexamples/ 目录。

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 webhttp://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 章。


教程完。如有事实性修正(这个项目迭代极快),以仓库最新文档为准。