DeepSeek Harness 专栏开篇:学习路径总览

专栏:DeepSeek Harness · 第 1 / 14 篇
DeepSeek HarnessAgent源码学习

这是 DeepSeek Harness 专栏的第 1 篇,也是整个专栏的路线图:先讲清楚 dsh 是什么、为什么值得读它的源码,然后给出一条由浅入深的六阶段学习路径。后续文章会沿着这条路径一篇篇展开。

dsh 是什么

DeepSeek Harness(简称 dsh)是 DeepSeek 开源的 agent harness(智能体框架)——就是驱动 coding agent 那类产品的”骨架”:负责会话管理、prompt 组装、工具执行、权限审批、沙箱隔离、subagent 委托这些模型之外的全部脏活。

它有两个让我决定开这个专栏的特质:

  1. 一切皆插件。dsh 构建在 Cordis 框架之上:模型适配器、工具注册表、会话日志、甚至 agent loop 本身,都是可替换的插件。不存在”需要打补丁的特权内核”——扩展它的方式是把新插件挂载到旧插件旁边。这套架构的论文背景是 A Programming Paradigm for Spatiotemporal Composability
  2. 文档质量罕见地高。仓库里 50 个包每个都有 README 契约,docs/ 下还有架构总览、事件时序图、能力 seam 图、扩展实操手册,中文齐全。这意味着它是我见过最适合用来学习”agent 产品如何被工程化”的开源代码库之一。

另一个阅读理由:agent harness 是当前 AI 应用工程里模式最密集的一层。读透一个 dsh,再看同类产品的公开资料(Claude Code、Codex 等)会有强烈的”原来都一样”的既视感——dsh 的 hooks 包甚至在字面意义上桥接了 Claude Code / Codex 的线协议。

:::note 专栏定位与新手须知

本专栏是进阶源码拆解:逐行分析一个生产级系统的实现。前置课程:① 没接触过 agent 的读者,请先读「Agent 工程」专栏的前六篇(特别是第 4 篇手写循环);② TypeScript 工程基础薄弱的读者,请先读「TypeScript 与 Node 地基」专栏;③ 想彻底读懂”一切皆插件”的机制,请读「Cordis 插件框架」专栏——逐行讲解 vendored 源码。前置课完成后,这里会事半功倍。

先解释几个贯穿全专栏的名词:

术语大白话解释
Harness(鞍具)给模型套上的”工程骨架”——会话、工具、审批、沙箱这些模型之外的全部设施
Cordisdsh 底层的插件框架:每个功能都是可插拔的插件
ctx插件之间共享的”上下文对象”,服务都挂在它身上(如 ctx.tools)
fiber一次插件运行的实例,卸载时自动撤销它注册的一切
seam(接缝)可替换能力的设计模式:接口/实现/消费三方分离,换实现不动调用方
waterfall 事件一层层”洋葱式”监听器,可以改写结果也可以直接拦截
仅追加日志(append-only)只往日志末尾写、永不修改删除——历史可完整回放
profile / patch启动配置的组装方式:基础配置 + 你的覆盖层,改配置不改代码
TUI终端里的图形界面(Cursor 式的键盘操作体验)

:::

环境与前置知识

  • 语言:TypeScript 为主(约 2500 个源码文件),另有 Python SDK(python/sdk
  • 框架:Cordis(插件化运行时),pnpm monorepo
  • 运行npx @deepseek-ai/dsh web 即可体验,默认起在 http://127.0.0.1:3080;从源码跑则是 pnpm install && pnpm run build && pnpm dsh web
  • 源码https://github.com/deepseek-ai/deepseek-harness(MIT,开发者预览阶段,接口可能破坏性变更)

不需要你是 Cordis 专家——阶段二专门补这块。但建议你对 agent 的基本工作方式(模型 + 工具循环)有直觉。

源码地图

读源码前先认清地形。packages/ 下的包按能力分组,每组 README 是该系列的权威地图:

位置内容
packages/core/产品主干:session(事件日志)、system-prompt(提示词组装)、tools(工具注册与执行流水线)、agent + agent-loop(agent 抽象与默认循环)、scope
packages/llm/LLM 消息/流式词汇表 + 各模型提供方适配器
packages/shell/ fs/ sandbox/ subprocess/ terminal/执行世界:shell、文件系统、进程限制(bwrap/Landlock/Seatbelt)、PTY
packages/subagent/ skill/ web/ lsp/ compaction/ todo/ plan/ jobs/面向模型的能力工具包系列
packages/interaction/ credentials/ settings/人机协作平面:审批、权限预设、凭据、设置
packages/host/ client/Web GUI 的两半:宿主 API 网关 + 浏览器端
packages/bundle/ preset/ boot/组装层:profile、组合包、启动粘合
apps/cli/ apps/web/两个可执行应用
docs/架构文档、子系统说明、cookbook(本文的路线大量参考这里)

两篇必读文档贯穿全程:架构总览包分组地图。读代码卡住时先回这两篇。

学习路径总览

整条路径按”先跑起来 → 打地基 → 读主干 → 抓设计思想 → 看产品化 → 动手改”推进,规划 6 个阶段约 14 篇:

图表(deepseek-harness-learning-path.md)

阶段一:跑起来,建立直觉(第 2~3 篇)

目标:不读任何核心代码,先会用、会看。

  • 第 2 篇 · 10 分钟跑通 dshnpx 起服务、Web UI 各功能区、headless 一次性运行、dsh --profile web --dump-config 看启动配置树。产出:一个能玩的本地环境。
  • 第 3 篇 · 从源码构建pnpm install / pnpm run build 的产物结构、apps/cli 的入口做了什么、调试怎么挂。产出:能改一行代码并看到效果。

阶段二:地基——Cordis 与组装机制(第 4~5 篇)

目标:看懂”插件如何变成一个产品”。

  • 第 4 篇 · Cordis 入门:插件向共享上下文贡献服务、类型化事件、可逆副作用;ctx 键是什么;对照 docs/cordis-primer 读最小例子。
  • 第 5 篇 · Profile 与组合包dsh-basedsh-web-app 的分层叠加、patch 文件如何按 id 替换条目、五种随附 profile(web/headless/sdk/sdk-minimal/acp)的差异。产出:用 --dump-config 解释你机器上实际生效的插件树。

阶段三:核心主干——一个轮次的完整旅程(第 6~9 篇)

这是专栏的重头戏。跟着轮次流程图把一次用户输入到回复落地的路径走通:

  • 第 6 篇 · Session:仅追加的事件日志SessionEventMap、“模型可见即已记录”不变量、deriveMessages() 如何从日志投影出模型历史、会话格式与迁移。
  • 第 7 篇 · agent-loop:循环本体:turn/step 生命周期、事件瀑布(agent/pre-step / agent/request / llm/stream / tools/*)、inbox 与唤醒。对照源码 packages/core/agent-loop/src/agent.ts 读。
  • 第 8 篇 · system-prompt:提示词组装:片段注册、工具 schema 如何进入 prompt、上下文注入(agent.inject())。
  • 第 9 篇 · tools:带把关的执行流水线:作用域化注册表、pre-execute → execute → post-execute、取消与错误恢复。产出:能徒手画出一次工具调用的完整时序。

阶段四:设计思想——能力 seam(第 10~11 篇)

目标:从”读懂”升级到”会欣赏”。

  • 第 10 篇 · seam 三角色:Service Definition / Service Provider / Consumer 的分工;为什么”换一个文件系统提供方 = 换掉整个执行世界”;ctx.shellctx.fsctx.sandbox 实例拆解。
  • 第 11 篇 · LLM 适配器与流式ctx.llm 的消息/流式词汇表、适配器 seam、assistant-stream 的提交语义、模型可见的 wire 扩展。

阶段五:产品化——模型之外的一切(第 12~13 篇)

  • 第 12 篇 · 人机协作平面:审批流、权限预设、凭据与 ask_user;沙箱后端(bwrap/Landlock/Seatbelt)如何限制进程。
  • 第 13 篇 · 三种产品形态:Web GUI 的 host/client 分工、headless 与 SDK(TypeScript JSON-RPC + Python SDK)、subagent 与后台任务(jobs)。

阶段六:实战——写自己的插件(第 14 篇收尾)

  • 第 14 篇 · 扩展实操:对照 docs/cookbook(adding-a-tool / adding-an-llm-adapter / adding-a-package)从零写一个工具插件并挂进 profile。走到这里,这个专栏的目标就完成了:你能自信地改它,而不只是读它

学习方法建议

  1. 文档先行,代码验证。dsh 的文档可信度很高(CI 里有文档新鲜度门禁),先读文档建立预期,再去代码里找对应实现,效率远高于直接扎进 2500 个文件。
  2. --dump-config 当导游。任何”插件树现在长什么样”的疑问,dump 一下就有答案;再配合 ctx 键表反查包,几乎不会迷路。
  3. 沿着一条事件走。读循环类代码最忌横向铺开。选定”用户发一条消息”这条主线,从 turn/start 一路追到 turn/end,中途遇到的每个包只记录职责、不展开。
  4. 笔记输出成专栏。我自己就是按这个路径边读边写——每篇的草稿都是阅读笔记的整理。如果你也在读,欢迎用 RSS 订阅本专栏同行。

dsh 处于开发者预览阶段,本文基于 2026-09 的 main 分支(d347e70)。接口后续可能变动,思路不变。

参考资料索引

← 返回文章列表