← 返回首页
"Everything is a Plugin"

"Everything is a Plugin"

发布于 2026年8月15日 17:55👁 12

DeepSeek Harness 完全详解:一切皆插件的 AI-Agent 框架

版本说明:本文基于 DeepSeek Harness v0.1(开发者预览版,npm 包 @deepseek-ai/dsh v0.1.0-rc.6)编写,所有命令、架构与插件清单均对照官方发布包源码与官方文档核实。

一句话定位:DeepSeek Harness(简称 dsh)不是"开箱即用的成品 Agent",而是用来组装 Agent 的底层运行时框架。官方核心理念只有一句话——"一切皆插件"(Everything is a Plugin)



一、基本介绍

1.1 它是什么?

DeepSeek Harness 是 DeepSeek 于 2026 年 8 月开源的首款 Agent 框架(v0.1 开发者预览版),代码托管在 GitHub 的 deepseek-ai/deepseek-harness 仓库,采用 MIT 许可证,npm 上以 @deepseek-ai/dsh 发布,核心构建在 Cordis v4 插件框架之上。

传统 Agent 框架通常把"模型调用、工具执行、循环控制、记忆管理、执行环境"等环节焊死在一个整体里;而 Harness 的做法是把这些环节全部拆成可插拔的插件

  • 模型(LLM)是插件 —— 通过适配器(Adapter)机制,可接 DeepSeek、OpenAI 兼容接口、Anthropic Claude、Codex 等多种 provider,甚至支持运行中动态切换;
  • 工具(Tool)是插件 —— 文件系统、终端、网页、子代理、任务清单等全部以 dsh-tool-* 插件形式存在,按需挂载;
  • Agent 循环(Loop)是插件 —— 官方文档明确"它不依赖循环,因此循环可以替换",你可以替换思考-行动循环策略;
  • 执行环境是插件 —— Bash / PowerShell / 沙箱 / 本地文件系统 / MCP 客户端,各自独立成包;
  • 甚至连 Agent 本身、会话、提示词、人设(Persona)、技能(Skill)都是插件

1.2 为什么说它是"Agent 界的 Android"?

这个比喻来自社区(发布后 GitHub 星标一度冲到 5 万+):就像 Android 提供内核 + 可定制 ROM,Harness 提供可拼装的 Agent 运行时,而"ROM"就是它的 Profile(配置档案) —— 通过组合不同的插件包(bundle)与配置补丁(patch),可以拼出完全不同的 Agent 形态:

Profile 形态组成典型用途webdsh-base + dsh-web-app浏览器 GUI 交互式编码 Agentheadlessdsh-base + dsh-headless一次性任务:跑完打印结果退出自定义dsh-base + 任意插件组合特定场景的专属 Agent

1.3 与主流方案的区别

方案定位与 Harness 的差异LangChain / LlamaIndex高层编排库Harness 是底层运行时,不绑架你的编排方式Codex / Claude Code成品编码 AgentHarness 不做特定领域的成品应用,而是给你"可编程工具台"MCP工具互通协议Harness 内置 MCP 客户端插件dsh-mcp-client),两者是互补关系


二、AI-Agent 架构详解

2.1 总体架构图

graph TB
    subgraph CLI["dsh 命令行(@deepseek-ai/dsh)"]
        A1["dsh --profile <name>"]
        A2["dsh web(= --profile web)"]
        A3["dsh --profile headless \"task\""]
        A4["dsh plugin(pnpm 插件管理)"]
    end
 
    subgraph BOOT["启动器(Launcher)"]
        B1["解析自有 flag(--profile / --patch / --dump-config)"]
        B2["加载 profile 组合包(bundle)"]
        B3["叠加配置层(patch)"]
    end
 
    subgraph CORE["Cordis 内核(cordis v4)"]
        C1["插件加载器 cordis-plugin-loader"]
        C2["热更新 cordis-plugin-hmr"]
        C3["include / timer 等基础插件"]
    end
 
    subgraph AGENT["Agent 核心服务(dsh-agent / dsh-session / dsh-llm)"]
        D1["Agent 注册表 ctx.agents<br/>(创建 / 恢复 / 事件 / 发起方作用域)"]
        D2["会话存储 ctx.sessions<br/>(事件溯源 + surface 压缩层)"]
        D3["LLM 运行时 ctx.llm<br/>(适配器注册 / 模型发现 / 流式调用)"]
    end
 
    subgraph TOOLS["工具插件 dsh-tool-*"]
        E1["fs / fs-search 文件系统"]
        E2["bash / pwsh / terminal 终端"]
        E3["web 网页工具"]
        E4["subagent 子代理"]
        E5["goal / todo / jobs 任务管理"]
        E6["skill / ask-user / ralph 等"]
    end
 
    subgraph ENV["执行环境"]
        F1["dsh-fs-local 本地文件"]
        F2["dsh-terminal-bash / dsh-pwsh-local"]
        F3["沙箱:bash-sandbox / pwsh-sandbox<br/>(Windows ACL 权限控制)"]
        F4["dsh-mcp-client MCP 客户端"]
    end
 
    subgraph SURFACE["表现层组合包"]
        G1["dsh-web-app(浏览器 GUI)"]
        G2["dsh-headless(一次性任务)"]
    end
 
    CLI --> BOOT
    BOOT --> CORE
    CORE --> AGENT
    AGENT --> TOOLS
    TOOLS --> ENV
    CORE --> SURFACE
 

2.2 分层模型:base → 表现层组合包

Harness 采用"基础层 + 表现层"的组合包设计,全部通过 cordis.patch.yml 补丁文件叠加:

  1. @deepseek-ai/dsh-base(基础组合包) 每个 profile 的 dsh.profile.bundles 列表中的第一层。它在一个空的 profile 根之上插入全部基础插件行:
  • 模型适配器与共享的 agent-default-model(默认模型)选择
  • 工具集合、持久化、策略(重试等)、settings、credentials(凭据)、遥测
  • 子代理(subagent)provider
  • Codex 与 Claude Code 的 provider 以休眠(dormant)状态加载,需要时再激活
  1. 表现层组合包
  • dsh-web-app:叠加在 base 之上,设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件注册表、客户端插件热重载链,以及 web-runtime 组合插件(printUrlsurfaceContexttrustedHosts 等配置项)。
  • dsh-headless:同样叠加在 base 之上,但不挂载任何 Host、HTTP server、Web runtime 或浏览器插件,禁用 HMR,把 Code Mode 的 worker 作为核心执行能力,并插入 headless-runner 插件用于一次性任务。
  1. 用户 Profile:在组合包之上再叠加你自己的 cordis.patch.yml,按 id 覆盖任意一行配置。

⚠️ 工程细节:patch 会替换整行的 config,不存在深度合并层。也就是说 profile 覆盖某一行时,必须把需要保留的每个字段都重写一遍。

2.3 六大核心子系统(对照源码)

以下均来自官方包的真实插件清单(@deepseek-ai/dsh 的依赖)与各包 README:

(1)Agent 运行时 —— dsh-agent

Agent 接口、注册表与进程内发起方(initiator)作用域,定义 agent/* 事件词汇。

  • 注册表服务键:ctx.agents
  • 核心 API:ctx.agents.register(agent)create(options)resume(options)list()roots()
  • 工厂机制:ctx.agents.setFactory(factory) 注册 AgentFactory —— 创建功能留在接口上,消费方(UI、ACP 桥接层)面向 ctx.agents 编程,不依赖具体循环包,这是"循环可替换"的架构基础
  • 发起方作用域:withInitiator(agent, op) / requireInitiator() / withoutInitiator(op),用于父子 Agent 关系的追踪
  • Agent 生命周期:enter(强制 agent.id === session.id、ID 冲突检查)→ announce(发出 agent/created)→ dispose

(2)会话存储 —— dsh-session

事件溯源(event sourcing) 的会话日志与内存存储。这是 Harness 记忆系统的根基:

  • Session 是 Agent 全部交互历史的唯一追加写入(append-only)真源LLM 消息历史是"派生"出来的,而不是直接存储的
  • 在原始日志之上维护一个 surface 层(产生消息事件的有序投影),用于高效派生消息与压缩(compaction)
  • 核心 API:ctx.sessions.create(id, {seed, meta})fork(source, boundary)(子会话分叉)、flush(session)(持久化检查点)、get(id)list()
  • 会话头(SessionHeader)携带版本、id、创建时间、cwd、父会话、seedLength、delegationDepth(委托深度)等元数据
  • 配套压缩插件:dsh-compaction-basic(基础压缩)、dsh-compaction-tool-result-pruner工具结果裁剪——把冗长的工具输出修剪掉,这是省 token 的关键机制)

(3)LLM 运行时 —— dsh-llm

Provider 无关的大模型调用词汇与抽象服务,服务键 ctx.llm

  • ctx.llm.registerAdapter(providers, adapter) —— 为一条或多条 provider 路由注册适配器
  • ctx.llm.stream(options) —— 把一次模型调用流式输出为原始分片(token 级增量)
  • ctx.llm.resolveModelInfo(provider, model) —— 精确模型身份解析(上下文长度、输出上限、reasoning 元数据)
  • 模型发现:registerModelDiscovery(settingsNs, discover) + discoverModels(),让 UI 能查询端点发布了哪些模型
  • 事件:llm/stream(waterfall 模式),可被中间件拦截/包装,用于缓存、日志或路由
  • 重试策略:适配器注册时携带 provider 自有的 providerRetryPolicy,随产品交付的 agent 重试走 agent/request-error 事件

(4)工具插件体系 —— dsh-tools + dsh-tool-*

工具不是硬编码的,而是一包一个工具的插件体系(详见第六章)。工具通过 ctx.agents 的作用域上下文注册,只对注册它的 Agent 生效,dispose 时全部撤销。

(5)执行环境 —— 终端 / 沙箱 / 文件系统

  • dsh-terminal + dsh-terminal-bash:终端抽象与 Bash 终端实现
  • dsh-pwsh-local / dsh-pwsh-sandbox:PowerShell 本地执行器与沙箱执行器
  • dsh-fs-local:本地文件系统服务(挂载 ctx.fs
  • dsh-tmux-context:tmux 上下文(多会话复用)

(6)Agent 配置预设 —— Agent Preset

官方包自带 4 个预设目录(config/agent-presets/):codecordisminimalstandard。每个预设决定自己的 Agent 是否向模型贡献面向模型的工具,即"这个 Agent 长什么样、能用哪些工具"由 preset 决定。

2.4 子代理、Goal 与技能

  • 子代理(Subagent)dsh-subagent + dsh-tool-subagent(创建子代理)+ dsh-tool-subagent-control(控制),支持多 Agent 并发执行与结果回收;dsh-workflow-worker-thread 提供工作流的工作线程实现
  • Goal 系统dsh-goal + dsh-goal-round-driver(目标轮次驱动,支持多轮自动续跑)+ dsh-tool-goal + dsh-command-goal,用于"长跑型"任务目标管理
  • 技能(Skill)dsh-skill + dsh-skill-filesystem + dsh-tool-skill,把可复用的操作指令打包成技能,按需加载
  • Personadsh-persona 提供人设提示词基础;dsh-agent-instructions / dsh-agent-tool-presentation 负责指令与工具对模型的呈现方式

2.5 记忆与上下文管理

Harness 对上下文的处理非常有特色:

  1. 事件溯源 + surface 投影:原始事件永不丢失,模型看到的只是按需投影出来的消息序列;
  2. 增量投影deriveMessages() 只对每个新 surface 条目做一次增量投影,避免全量重算;
  3. 分层压缩dsh-compaction-basic 负责常规压缩,dsh-compaction-tool-result-pruner 专门裁剪工具结果——工具输出往往占据上下文大头,裁剪后 token 显著下降;
  4. 会话分叉session.fork(boundary) 从某个事件序号切出子会话,适合分支探索;
  5. KV Cache 友好:官方包在提示词设计上刻意保证"提示词段落在进程生命周期内稳定",避免跨轮次缓存失效。

三、安装与快速开始

3.1 环境要求

  • Node.js(建议 ≥ 18,包本身是 ESM 模块)
  • pnpm(用于插件管理与 monorepo 开发)
  • 一个 DeepSeek API Key(或其他兼容 provider 的凭据)

3.2 方式一:npm 全局安装(推荐,最快)

# 1. 全局安装 dsh CLI
npm install -g @deepseek-ai/dsh
 
# 2. 启动浏览器版(web profile 首次使用会自动从随附模板初始化)
dsh web
 
# 3. 启动后终端会打印形如 "dsh web: http://127.0.0.1:<port>" 的 URL
#    用浏览器打开即可开始对话
 

webheadless 两个 profile 在首次使用时会从随附模板自动初始化,其余任何 profile 都必须通过 dsh plugin 创建。

3.3 方式二:一次性运行(不安装)

npx @deepseek-ai/dsh web
 

3.4 方式三:从源码运行(开发模式)

# 克隆仓库
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
 
# 安装依赖
pnpm install
 
# 构建所有包与前端产物(生产运行需要已构建的包)
pnpm run build
 
# 使用 TypeScript 入口运行,转发所有参数
pnpm dsh <args...>
 

3.5 Headless(无头一次性任务)

# 运行一个全新的持久化会话,打印最终答案并退出
dsh --profile headless "帮我总结这个项目的架构"
 
# 退出码:turn/end 完成 → 0;失败 → 1
# 成功时 stderr 保持为空;失败时把 code 与 message 写入 stderr
 

适合做自动化:脚本调用 → 拿 stdout 结果 → 按退出码判断成败。

3.6 配置模型与凭据

Harness 通过 settingscredentials 两套机制管理配置(均由 dsh-base 提供):

  • settings:profile 内的结构化配置(模型路由、默认模型 agent-default-model、预设等),按 settings namespace 组织;
  • credentials:API Key 等敏感凭据,独立存储;
  • 模型发现:UI 的模型设置页会通过 ctx.llm.discoverModels() 查询端点实际发布了哪些模型,选定后写入 settings;
  • Codex 与 Claude Code 的 provider 以休眠状态随 base 包加载,在 profile 或 home 的 cordis.patch.yml 中按需激活。

四、Profile 与配置体系

4.1 Profile 目录结构

Profile 位于 $DSH_HOME/profiles/<name>$DSH_HOME 是 Harness 的配置根目录),包含:

profiles/<name>/
├── package.json        # 记录树外(out-of-tree)插件依赖
├── dsh.profile         # profile manifest(元数据清单):按顺序列出 bundles
└── cordis.patch.yml    # 用户自己的补丁层
 

4.2 配置分层(自底向上)

配置树以空根为起点,依次叠加:

  1. dsh.profile.bundles 中各组合包的 patch(bundle 先从 dsh 安装目录解析:dsh-basedsh-web-appdsh-headless,再从 profile 自己的 node_modules 解析;pnpm 会把树外插件安装到该目录)
  2. profile 自身的 cordis.patch.yml
  3. home 级的 $DSH_HOME/cordis.patch.yml
  4. --patch 指定的覆盖层(可重复:--patch a.yml --patch b.yml

4.3 检查合并后的配置

# 查看默认配置树(不启动)
dsh --profile web --dump-default-config
 
# 查看叠加全部补丁后的最终配置树(不启动)
dsh --profile web --dump-config
 

4.4 创建自定义 Profile

# 通过转发给 pnpm 来管理某 profile 的插件依赖
dsh plugin --profile my-agent add @deepseek-ai/dsh-tool-web
 
# 之后启动
dsh --profile my-agent
 

⚠️ 注意:启动器(launcher)只解析自己的 flag,其后的所有内容会原样交给被启动的 profile 内的应用插件解析。所以启动器 flag 必须写在最前面,第一个无法识别的 token 标志着应用参数的开始:

dsh --profile web --port 8080     # --port 属于 web 应用
dsh --profile web --help          # 打印 web 应用的帮助,不是启动器的
dsh --help                        # 打印启动器自己的帮助
 

五、常用命令速查

命令用途dsh --profile <name>启动位于 $DSH_HOME/profiles/<name> 的指定 profiledsh --profile headless "job"运行一个全新的持久化会话,打印最终答案并退出dsh web--profile web 的别名(浏览器 GUI)dsh plugin --profile <name> <pnpm args>通过转发给 pnpm 管理该 profile 的插件dsh --profile <name> --patch <file.yml>追加覆盖层(可重复)dsh --profile <name> --dump-default-config不启动,输出默认配置树dsh --profile <name> --dump-config不启动,输出合并后的最终配置树dsh --help启动器帮助(每个应用有自己的 --help

Web 应用自己的 flag--host--port、可重复的 --trusted-host。当前版本有意拒绝 --host 0.0.0.0(不支持绑定所有网卡接口)。


六、工具插件全景图

以下工具插件全部随 @deepseek-ai/dsh 官方包发布(v0.1.0-rc.6 实测依赖清单):

类别插件包说明文件系统dsh-tool-fsdsh-tool-fs-search文件读写、搜索终端dsh-tool-bashdsh-tool-bash-persistentdsh-tool-pwshBash / 持久化 Bash / PowerShell 执行网页dsh-tool-web网页抓取/搜索类工具子代理dsh-tool-subagentdsh-tool-subagent-control创建与控制子代理任务管理dsh-tool-tododsh-tool-jobsdsh-tool-goal待办清单、后台任务、目标交互dsh-tool-ask-user向用户提问确认技能dsh-tool-skill加载技能文本编辑dsh-tool-str-replace-editor字符串替换式编辑器(精确小改动)系统dsh-tool-cordisdsh-tool-ralphdsh-tool-workflow框架内省、Ralph 循环、工作流编排

配套基础设施插件:dsh-token-meter(token 计量)、dsh-schedule(定时任务)、dsh-time-context(时间上下文)、dsh-plan-mode(计划模式)、dsh-jobs-local(本地任务)、dsh-session-projection / dsh-session-reference(会话投影与引用)、dsh-command-compact / dsh-command-goal(命令)。


七、平台支持与安全沙箱

7.1 Windows / POSIX 差异

官方包对平台差异做了显式处理(来自 dsh-base 的 patch 设计):

  • Bash 没有 Windows runnerbash-sandbox / tool-bash 携带 disabled: !!js process.platform === 'win32';在 Windows 上由 pwsh-sandbox / tool-pwsh 以相反的表达式接替。同一份 patch 文件,每个宿主恰好挂载一个 shell 栈
  • 反过来,POSIX 主机看到的是被禁用的 pwsh 行;
  • 想在自己机器上用 Bash:必须在 profile 或 home 的 cordis.patch.yml完整覆盖这两行(禁用 pwsh 栈、重新启用 bash 栈),因为两个执行器族注册同一个 bash 服务,配方不完整会在加载时直接报错。

7.2 沙箱权限面

  • 权限面与 POSIX 完全对齐:sandbox / sandbox-policy 通过 Windows ACL 受限令牌 runner(dsh-sandbox-windows-acl)执行文件生效策略,权限切换器与 approval 服务原样运行;
  • dsh-fs-local 挂载 ctx.fs,沙箱写操作由 fs-sandbox 围栏;
  • Windows 临时目录授权是按会话的私有子目录workspace-write 把写入限制在工作区与会话自己的 temp 子目录(<temp>\dsh-<hash>,受限子进程的 TMP/TEMP 被改写);read-only 不授予任何临时目录写入权。

八、生态、社区与二次开发

8.1 官方仓库结构

monorepo 主要目录(对应 npm 包组织):

  • apps/cli@deepseek-ai/dsh(CLI 启动器)
  • packages/core/*dsh-agentdsh-sessiondsh-llmdsh-tools 等核心
  • packages/boot/*dsh-basedsh-web-appdsh-headlessdsh-cmdline 等组合包
  • packages/host/* → webserver、apiproxy、frontend-static 等宿主
  • packages/client/* → 浏览器端 UI 与 HMR
  • packages/tools/* → 各 dsh-tool-* 插件

8.2 社区资源

  • Awesome 列表0xsline/awesome-deepseek-harness(中文)
  • 拆解教学onychen/learn-dsh(含简单教学版实现)
  • 深度手册Electricitysheep/dsh-handbook(安装/插件开发/性能调优/实测案例)
  • 桌面版封装LisiChen0/DeepSeek-Harness-Desktop

8.3 如何写一个自己的插件

插件本质是 Cordis 插件 + 一个 cordis.patch.yml 补丁。最小步骤:

  1. 继承你需要的服务接口(如 ctx.agentsctx.llmctx.sessions);
  2. registerAdapter / register / on(event) 等 API 挂载你的能力;
  3. 把插件声明进 profile 的 bundles 或 patch 层;
  4. dsh plugin --profile <name> add <你的包> 安装;
  5. --dump-config 验证合并结果。

九、已知限制与注意事项

  1. patch 是整行替换,不是深度合并:覆盖配置时必须重写需要保留的每个字段;
  2. 前端 dist 必须已构建dsh-web-app 对 dist 的 require.resolve 在激活时明确报错并给出构建提示,没有从源码直接服务的回退路径;
  3. lanAddresses 是启动期快照:启动后的网卡变化不会重新公告,打印的 LAN URL 始终与配置的信任栏一致;
  4. headless 只提交一个任务:runner 没有用于交互式后续输入的 surface,它会等 Agent 返回 idle 前完成的所有工作,打印该区间内最后一条非空 assistant 消息;
  5. ctx.appExit 由启动器持有:在 dsh 启动器之外启动 headless profile 会在激活时明确报错;
  6. Web 版当前拒绝 --host 0.0.0.0,CLI 有意不支持绑定所有网络接口;
  7. 仍处于 v0.1 开发者预览版:API 与配置格式在正式版前可能调整。

十、参考资料


本文架构描述基于 @deepseek-ai/dsh v0.1.0-rc.6 官方发布包源码逐项核实,引用命令与配置均可在该版本复现。

评论 (0)

还没有评论,来写第一条吧~

写评论