











本文面向第一次接触 DeepSeek Harness 的开发者,按“先建立整体模型,再进入实现细节”的顺序说明它的定位、架构、运行方式、适用场景与可能的发展方向。
内容以仓库当前公开实现为依据,版本背景为 0.1.2-alpha 系列开发预览版(核对时仓库 package.json 为 0.1.2-alpha.2,版本以仓库为准)。文中“当前实现”与“发展判断”会明确区分;社区讨论中的想法不等同于官方路线图。
第一次阅读时把它当作词典:遇到不认识的词回来查;每个词在正文中都有更完整的解释。
| 术语 | 一句话定义 |
|---|---|
| Harness | 围绕大模型构建可运行 Agent 的基础运行时,负责模型调用、上下文、工具、会话、权限与扩展的组合 |
| Plugin(插件) | 注册服务、监听事件、声明依赖的 Cordis 单元;Agent 的能力由一组插件共同组成 |
| Seam(能力缝) | 一个可替换能力的三段式结构:Service Definition(定义)+ Provider(实现)+ Consumer(接入 Agent) |
| Scope(作用域) | 注册的可见范围:贡献要么全局可见,要么只属于某个 Agent;子代理不继承父代理的作用域 |
| Profile | 一套命名的运行时组成,例如 web、headless、sdk、acp |
| Bundle | 一组可安装的 Cordis 配置行与代码,可作为基础包或 patch 层叠加到 Profile |
| Turn / Step / Round | step = 一次模型请求及其引发的工具执行;turn = 零个或多个 step;round = 外层策略的一次迭代(如目标轮) |
| Session Event Log | 会话的追加式事件日志,是运行时事实来源;模型上下文、UI、恢复、分叉、遥测都从它派生 |
| Projection(投影) | 从事件流派生的只读视图,例如模型消息历史、Web Transcript、持久化状态 |
| Compaction | 接近上下文上限时对旧历史做摘要压缩,并裁剪过大的工具输出 |
| Goal(目标) | 附着在会话上的持久化完成目标,带阶段与轮次上限,可驱动自动续跑 |
| Human Command | 以 / 开头的命令(如 /plan、/compact、/goal),由人触发、不经模型回合直接执行 |
DeepSeek Harness 是 DeepSeek AI 开源的通用 Agent Harness。这里的 Harness 可以理解为“围绕大模型构建可运行 Agent 的基础运行时”,它负责把模型调用、上下文、工具、会话、权限、子代理、工作流、Web UI 和 SDK 组合成一个可扩展系统。
它不是一个只提供聊天窗口的应用,也不是一个只封装 HTTP 请求的模型 SDK。它更接近一个“可配置的 Agent 操作系统”:模型是决策者,Harness 负责提供能力、保存状态、执行动作、承接扩展,并把运行过程投影到用户界面或外部协议。
项目的核心定位可以概括为三点:
官方仓库仍将项目标注为开发预览版,接口和存储格式可能发生不兼容变化。项目的整体说明见 官方 README。
从外部看,用户提交一个任务,模型思考并调用工具,最后返回结果。从内部看,DeepSeek Harness 会把这个过程拆成多个相互协作的层:
用户 / Web UI / TypeScript SDK / Python SDK / ACP
|
API 与连接层
|
Profile + Bundle + Cordis Context
|
Session | Agent Loop | System Prompt | Tool Runtime
|
LLM Provider | Shell | FS | Web | LSP | Sandbox | Subagent
|
JSONL / SQLite / 文件系统 / 外部进程
可以把它理解成四个方向的组合:
仓库的架构总览、包分组、启动规则和 Agent Loop 语义集中写在 docs/architecture.md。如果只读一份源码文档,优先读它。
用一个具体任务把上面的分层串起来。假设用户通过 Web UI 提交“帮我看看项目里哪个测试失败了”:
dsh web 启动后,Web Profile 组合出包含 Agent Loop、工具、Session 持久化的运行时。turn/start 打开一个 turn。assistant/chunk → assistant/message),UI 实时显示。bash 工具运行测试:tools/pre-execute 先做权限与审批检查,tools/execute 执行,tool/result 把输出写回事件流。turn/end 关闭。DeepSeek Harness 使用 Cordis 作为插件框架。一个 Cordis 插件可以注册服务、监听事件、声明依赖,并通过可撤销的 effect 管理生命周期。
这意味着 Agent 不是把所有逻辑硬编码在一个巨大的主类中,而是由一组插件共同组成。例如:
插件之间不是通过大量全局变量互相引用,而是通过 Context 中的服务和事件通信。Cordis 的服务、依赖注入、事件模式和生命周期语义见 Cordis Primer。
一个完整能力通常由三类角色构成:
| 角色 | 责任 |
|---|---|
| Service Definition | 声明稳定的类型、方法和事件 |
| Service Provider | 提供具体实现,例如本地进程、远程服务或持久化后端 |
| Consumer | 把能力接入 Agent,例如注册模型、暴露工具或驱动 UI |
例如,Shell 能力可以拥有统一的 Service Definition,然后分别接入本地 Shell、PowerShell 或受控执行环境。Agent 只依赖能力定义,不需要把每一种底层实现写死在循环里。
它主要解决的是“同一个 Agent 主干,如何在不同环境中拥有不同能力”:
代价是理解成本更高。阅读一个功能时,通常要同时寻找定义、实现、消费者、配置行和事件,而不是只打开一个文件。
插件组合解决“系统由哪些能力构成”,作用域解决“同一个能力对不同 Agent 呈现什么”。注册到共享 Context 的贡献——工具、提示词片段、变量、监听器——要么是全局的,要么属于某个 Agent 的作用域;约定是“一个存活中的 Agent 就是它自己作用域的 key”。
几个必须理解的行为:
tools.restrict 按交集过滤全局工具集,被过滤掉的工具对模型既不可见也拒绝执行,与“不存在的工具”没有区别。作用域语义的官方说明见 Scope 子系统 与 glossary。
DeepSeek Harness 不把“启动应用”理解为直接执行某个包的 bin,而是通过 dsh 启动一个命名 Profile。仓库当前的主要 Profile 包括:
这些 Profile 共享一部分基础插件,再按用途叠加不同能力。常见的公共层是 dsh-base;Web、Headless、SDK 和 ACP 在此基础上分别添加自己的入口和连接方式。
Bundle 是一组可安装的 Cordis 配置行和代码。它可以作为基础能力包,也可以作为 patch layer 叠加到某个 Profile 上。
配置合成大致遵循以下顺序:
Bundle 默认配置
↓
Profile 补丁
↓
用户目录补丁
↓
命令行 --patch
↓
最终 Cordis 配置
一个 patch 通常针对完整配置行,而不是隐式地修改某个深层字段。这种方式让“当前运行了哪些插件、每个插件使用什么配置”可以被检查和复现。
Profile 和启动约束的具体说明见 架构文档中的 Application Launch 与 Profiles,基础配置可以参考 dsh-base 的 Cordis patch。
项目把应用启动集中到 dsh,是为了让 Profile、配置层、生命周期、构建产物和运行环境保持一致。单独执行某个包的 bin,可能绕过这些组合规则,导致“源码能启动但正式 Profile 行为不同”的问题。
因此,理解 DeepSeek Harness 时应把 dsh 看成应用启动器,把各个 npm workspace 包看成可装配的运行时部件。
Agent Loop 的核心不是“调用一次模型然后输出文本”,而是反复执行“读取上下文、请求模型、执行工具、记录结果、继续请求”的循环。
典型流程如下:
turn/start
→ 获取下一条用户输入和队列消息
→ agent/pre-step
→ step/start
→ 写入 user/message
→ 从 Session 派生模型历史
→ agent/request
→ LLM 流式响应
→ assistant/chunk*
→ assistant/message
→ tool/call*
→ tools/pre-execute
→ tools/execute
→ tools/post-execute
→ tool/result*
→ step/end
→ 继续下一步,或 agent/turn-stopping
→ turn/end
星号表示可能出现多次。模型没有工具调用时,一步可能直接结束;模型产生工具调用时,工具结果会被记录,并成为下一步模型请求的一部分。
Agent Loop 的实现位于 agent-loop 的 README 和 agent.ts。
Agent Loop 需要处理的不只是正常成功路径,还包括:
这也是它与简单的“while 循环调用模型”之间的主要差异:循环本身是一个带生命周期、事件和可恢复状态的运行时组件。
在构造模型请求时,Agent Loop 会组合:
模型请求不是独立的临时变量,而是 Session 记录和当前插件状态的投影。这为恢复、审计、UI 展示和 Snapshot 测试提供了共同基础。
官方 glossary 用三个词定义循环的层级:
Ralph 循环值得单独解释:它是把同一个目标交给“全新会话的模型”反复执行的前台工作流;每轮子会话不携带父会话与上一轮会话的对话种子,跨轮状态通过共享 workspace 与一份有界的结构化交接报告传递。它不是 session 内的 goal,也不是调度器。
“用户提交一个任务,模型做完就停”只是基础形态。Goal 机制让一个 session 拥有一个持久化的完成目标:目标带 active / paused / blocked / complete 阶段和轮次上限,模型工具可以创建和更新目标,/goal 命令让人不经过模型回合直接控制,自动续跑驱动会把 active 目标变成一轮轮自动工作。
三个容易误解的点:
Session 保存的是事件序列,而不是简单的 messages 数组。事件可能包括:
事件流是运行时事实来源,其他视图都可以从它派生:
事件流
├─→ 模型消息历史
├─→ Web UI Transcript
├─→ 恢复与继续执行
├─→ 会话分叉
├─→ 工具审计与遥测
└─→ 测试 Snapshot
其中,模型真正看到的内容必须能够由 Session 事件重建。这个原则可以避免 UI 显示了一些模型无法看到的隐式状态,也避免恢复时缺少影响决策的输入。
流式响应通常会先产生多个 assistant/chunk 事件,随后形成完整的 assistant/message。这样做有两个目的:
因此,事件流既服务于实时体验,也服务于事后重建。它不是为某一个消费者定制的日志格式。
项目提供 JSONL 和 SQLite 两种持久化方向。JSONL 适合透明的追加写入和调试;SQLite 适合结构化查询、压缩流式块和更稳定的本地存储。
持久化层会处理写入延迟、崩溃恢复和逻辑事件流重建。崩溃恢复的目标不是伪造一条完整成功记录,而是明确记录中断状态,让后续恢复能够识别未完成的 turn。
会话类型、事件词汇和持久化语义见 Session 源码 与 持久化子系统说明。
模型上下文有上限,长会话不可能永远原样增长。Compaction 能力族解决这个问题,包含三个层次:
/compact 命令手动触发。另一条缓解路径是 Spill:当单个工具结果超过字节上限时,完整文本被保存为 artifact,模型只看到有界预览加一个可后续读取或搜索的定位符。
压缩不是删除:压缩结果仍然作为事件写回日志,恢复与审计依旧可以追溯。官方说明见 Compaction 子系统 与 Spill 子系统。
工具系统不仅负责“注册一个函数”。一个工具通常包含名称、描述、参数 JSON Schema、执行逻辑、结果以及可选的 UI 展示信息。
执行过程可以被多个阶段拦截:
模型产生工具调用
↓
tools/pre-execute 权限、审批、策略
↓
tools/execute 实际执行与包装器
↓
tools/post-execute 收尾、指标、清理
↓
tool/result 写入结果并反馈给模型
Tool Runtime 还负责并发上限、执行包装器、错误处理、结果归一化和工具可见范围。源码见 packages/core/tools/src/index.ts。
工具不一定要在每次请求中全部暴露给模型。运行时可以限制当前 Agent 能看到的工具,或者使用 ToolSearch 一类机制,让模型先搜索工具再按需加载详细 Schema。
这能减少上下文开销,也能把大量能力以插件方式安装而不必一次性塞进每个模型请求。
工具可以访问文件、Shell、网络、进程和凭据,因此“能运行”不等于“安全”。官方 SAFETY.md 明确提醒:项目没有完成安全审计,不应被视为生产安全系统;模型生成的代码和命令、第三方插件以及宿主机访问都可能带来风险。
审批、沙箱和权限控制可以降低误操作概率,但不应被理解为绝对隔离。运行不受信任任务时,应使用最小权限、无敏感凭据的临时环境,并优先使用一次性虚拟机或容器。
这一点会长期影响项目发展:工具数量越多、插件越丰富、Agent 权限越高,插件供应链、能力隔离、审计、恢复和权限策略就越重要。
仓库提供了与上一节原则对应的具体机制:
allowed-once 只放行被询问的那一个动作;缺失、拒绝、取消或应答方不可用一律 fail-closed,不会开门。UI 通道提供人工应答,ACP 自动化桥为自身 Agent 提供机器决策。见 Approval 子系统。ctx.sandbox 后端约束;除本地后端外还有实验性的 E2B 远程 Linux 沙箱,可以把文件、命令与终端整体搬进远端临时环境,宿主进程、模型调用与 Session 状态都不迁移。见 Sandbox 子系统 与 E2B 包组。这些机制降低误操作概率,但正如上一节所说,它们不等于绝对隔离。
Subagent 允许一个 Agent 把工作交给另一个 Agent。子代理通常拥有独立的子 Session 和一次激活过程,父 Agent 通过工具或 Provider 管理子任务。
它适合以下任务:
重要的是,Subagent 不是简单的函数递归。它涉及子会话持久化、激活生命周期、深度限制、取消、父子关系和冷恢复。
Workflow 更像程序化的 Agent 编排。它允许开发者用代码表达 agent、parallel、pipeline、phase 和 log 等结构,也可以实现 Ralph 风格的迭代循环(Ralph 的定义与 turn/step/round 层级见 5.4)。
可以用下面的方式区分二者:
| 机制 | 决策主体 | 更适合 |
|---|---|---|
| Agent Loop | 当前模型 | 动态决定下一步和工具 |
| Subagent | 父 Agent 与子 Agent | 委派、分工、隔离上下文 |
| Workflow | 开发者编写的流程 | 固定阶段、并行、流水线和重复执行 |
Workflow 可以改善可观测性和可复现性,但它本身不是安全边界。工作流中调用的工具仍然需要独立的权限和隔离策略。
仓库还包含实验性的 Agent Teams 方向。它反映出项目正在探索多个 Agent 之间的协作、消息传递和角色分工,但实验目录中的能力不应视为稳定公共 API。
除核心循环外,仓库还按能力族组织了一批可选包,dsh 基础组合默认启用其中一部分,其余按需挂载。理解它们的方式与理解工具相同:先看 Service Definition 定义了什么,再看 Provider 怎么实现、Consumer 如何接入 Agent。
| 能力 | 一句话说明 | 官方文档 |
|---|---|---|
| Session Query | 对实时与持久会话做精确查询、关系 trace 与全文搜索;Web 端可通过 /export 导出会话 | session-query 子系统 |
| Jobs | 后台任务注册为 job,归属发起它的 Agent,完成以会话内消息通知,而不是阻塞轮询 | jobs 子系统 |
| Schedule | 会话内定时提醒:到点以普通消息回到同一会话;提醒跨重启存活,但没有邮件或推送 | schedule 子系统 |
| Webhook | 接收经过认证的外部事件,由受信任规则创建新的根 Session | webhook 子系统 |
| Terminal | 持久、归属 Agent 的 PTY 会话:cwd、环境变量、已激活环境跨工具调用存活(进程内,不跨重启) | terminal 子系统 |
| Code Runtime | 模型写一个程序调用宿主提供的函数,运行时在隔离的 worker 线程或 CPython 子进程执行,失败作为结果的一部分返回 | code-runtime 子系统 |
| Skills | 可复用的任务指令:Provider 贡献 → 注册表合并 → 会话目录 + skill 工具按需加载完整指令 | skills 子系统 |
| Guard | 循环卫生:检测模型重复调用同一工具并提醒改变策略;为声明了超时的工具调用设置时间上限 | guard 包组 |
| Hooks | 桥接已有 Claude Code / Codex 的 hooks.json,让旧配置在 Agent 运行的关键时刻照常触发 | hooks 包组 |
| MCP | 把外部 Model Context Protocol 服务器的工具作为原生工具接入;只桥接工具,不支持 resources/prompts,默认全关 | MCP 包组 |
/plan、/compact、/goal、/export 这类命令构成独立的交互层:human command 由人触发,通过 ctx.commands 由 UI 适配器解释执行,不经过模型回合,也不等于 shell 命令。命令输出属于 UI 状态,除非处理器另行写入持久化领域。理解这一层,Web UI 上的许多交互才不会与“模型工具”混淆。见 commands 子系统。
/plan 进入计划模式:模式激活时,Agent 先探索和设计,把完整计划呈现给用户审批,批准后再执行。计划模式是引导而非限制——所有工具仍然可用,沙箱与审批等限制单独配置。见 plan 子系统。
Web Profile 提供浏览器 UI、会话列表、设置、实时输出和工具交互。浏览器看到的内容主要来自 Session 事件和持久化结果,而不是直接读取 Agent 内部对象。
这种设计使 Web UI 成为 Agent 运行时的一个投影,而不是 Agent Loop 的唯一使用方式。未来可以用命令行、SDK、自动化协议或其他客户端连接同一类运行时。
SDK 通过 JSON-RPC 和 NDJSON 通信。TypeScript Client 与 Python SDK 都可以启动对应版本的 dsh SDK Profile,然后通过标准输入输出交换请求和事件。
这种方式的优点是客户端不必复制 Agent Loop,也不必直接依赖内部 TypeScript 类。客户端只依赖协议和生成的类型投影,从而保持运行时实现与调用方解耦。
远程 API 使用 Typert 相关的类型图和 RPC 网关,把 TypeScript 类型、服务方法和连接层组合起来。它的目标不是单独提供一个 REST CRUD 后端,而是把插件化服务投影到远程客户端。
这也解释了项目为什么同时维护 Host 和 Client 两个编译面:Host 运行插件和 Agent,Client 负责浏览器或 SDK 侧的类型与交互。
在受控环境中,它可以执行代码、搜索文件、运行测试、调用 LSP、访问网页,并把每一步保存在可恢复的 Session 中。
如果要快速验证一个“模型 + 工具 + 会话 + UI”的产品,插件和 Profile 机制可以减少从零搭建运行时的工作。
Subagent、Workflow 和 ACP 使它能够承载代码审查、资料整理、任务分解、定时工作和长流程自动化。
它特别适合研究 Agent 的基础设施问题,例如:
一句话评价:DeepSeek Harness 的重点不是“让模型回答得更像人”,而是“把模型变成可以被配置、观察、恢复和扩展的任务执行运行时”。
从当前仓库的模块组织和公开文档,可以确认以下方向已经进入实现范围:
运行时扩展的约束尤其值得注意:动态定义的包是进程内版本,重启后不会自动保留,也不会替模型写入仓库文件或 Cordis 配置。可参考 extensions README 和 tool-cordis README。
下面是基于现有实现的工程判断,不是官方承诺的路线图:
社区已经出现关于 Harness 自我学习、反思机制和可评估 Plugin Packs 的讨论,例如 Harness Intelligence 提案 与 任务条件化 Harness 演化提案。这些内容代表社区探索,不应当当作官方路线图。
官方早期讨论也明确把项目定位为快速演进中的预览版本,可参考 v0.1 讨论 和 CONTRIBUTING.md。
建议按下面顺序阅读,避免一开始就陷入大量包源码:
带着三个问题阅读源码会更有效:
仓库根目录的常用命令包括:
pnpm install
pnpm run build
pnpm run test
pnpm run typecheck
pnpm run lint
从源码构建后,直接运行:
pnpm dsh web
pnpm run build 准备仓库产物,pnpm dsh web 直接使用这些产物而不重新构建。如果只想快速体验,也可以不克隆仓库:
npx @deepseek-ai/dsh web
默认在 http://127.0.0.1:3080 启动 Web UI 并打开浏览器;SSH 启动只打印宿主机 URL,因为本地端口转发由 SSH 客户端或编辑器负责。其他 Profile(headless、sdk、acp)的用法见官方 README 或 dsh --help。
实际使用时,优先通过 dsh Profile 启动应用,而不是绕过 Profile 直接运行内部包。
项目要求 Node.js 版本为 ^22.19.0 || >=24.0.0。如果当前是 Node.js 22.16.0,pnpm 会给出 Unsupported engine 警告;这不代表电脑必须安装 nvm,而是说明当前 Node 版本低于项目声明的最低 22.x 版本。
nvm 只是切换 Node 版本的一种工具,不是项目的必需依赖。可以使用 Homebrew、fnm、asdf 或其他方式安装满足要求的 Node.js;关键是让终端中的 node --version 达到 22.19.0 及以上,或使用 24.x 版本。
本文中的仓库文件引用均指向 GitHub 上的 deepseek-ai/deepseek-harness,便于在 GitHub、Markdown 阅读器或聊天工具中直接打开。由于项目仍在快速迭代,指向 master 的链接可能随仓库更新;需要固定阅读版本时,可将链接中的 master 替换为对应 tag 或 commit。
DeepSeek Harness 的核心价值可以归纳为一条链:
Cordis 插件组合
→ Agent Loop 驱动
→ 工具与外部能力执行
→ Session 事件持久化
→ Web / SDK / ACP 多端投影
→ Subagent / Workflow / 动态扩展
如果把普通 LLM 应用看成“模型加几个函数”,DeepSeek Harness 则是在研究“如何把模型、函数、状态、权限、生命周期和多客户端组织成一个可长期运行的系统”。它当前更适合开发者、研究者和需要深度定制 Agent 的团队;在用于生产环境之前,应先完成版本固定、安全隔离、权限审计、故障恢复和针对真实任务的评测。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。