DeepSeek Harness 深度解析:从一切皆插件到用基座构建自己的 Agent 应用

2026 年 8 月,DeepSeek 开放了 DeepSeek Harness 的开发者预览与源代码。它不是“又一个 DeepSeek 模型”,也不是只把聊天框套在模型 API 外面;它是一套让模型能够读取环境、调用工具、维持会话、接受审批并持续完成任务的 Agent 运行时。
官方给出的公式很直接:
Agent = Model + Harness
模型负责推理与决策,Harness 负责把推理接到真实世界:上下文从哪里来、工具如何注册、命令在哪里执行、状态怎样恢复、危险动作由谁批准、失败以后能否重放。本文会从“能跑起来”一直讲到“如何基于它开发自己的应用”。
DeepSeek Harness 当前仍处于 Developer Preview,官方明确提示核心插件与 API 会快速演进并可能产生不兼容变更。本文基于 2026-08-24 的官方文档与主分支;生产项目应固定版本、保留迁移测试,不要直接追随 master。
一、它解决的不是“模型不聪明”,而是“模型无法可靠工作”
单次模型调用通常只有三样东西:输入消息、模型参数、输出文本。一个可用 Agent 至少还需要:
| 能力 | 单次模型调用 | DeepSeek Harness |
|---|---|---|
| 上下文 | 调用者临时拼接 | 系统提示、历史与注入信息统一装配 |
| 工具 | 手写函数调用循环 | 工具注册表、Schema、执行管线与权限钩子 |
| 状态 | 由应用自行保存 | 追加式 Session Event Log |
| 执行 | 应用直接运行命令 | 文件系统、Shell、沙箱等可替换后端 |
| 生命周期 | 请求成功或失败 | Turn、Step、取消、恢复、分叉与重放 |
| 可观测性 | 日志靠自己补 | 模型可见事实与工具轨迹天然可追踪 |
| 扩展方式 | 修改主循环 | 挂载插件、监听事件、替换能力提供者 |
这也是 Harness 最重要的价值:把模型能力变成一个有边界、有状态、有反馈的执行系统。
如果只是做 FAQ 聊天,直接调用 API 更简单;如果任务要跨多轮读取代码、修改文件、运行测试、等待工具结果并接受人工审批,Harness 才开始体现价值。
二、“一切皆插件”到底是什么意思?
DeepSeek Harness 建立在 Cordis 之上。Cordis 内核本身只负责三类事情:
- 装载和卸载插件;
- 解析插件之间的依赖;
- 跟踪副作用,使插件卸载时能够撤销注册和监听。
模型适配器、工具、Session、Agent Loop、存储、沙箱、UI 都不是不可替换的“内核特权代码”,而是挂载在同一个 Context 上的插件。这与常见的“核心框架 + 少量扩展点”不同:DeepSeek Harness 试图让核心执行链本身也可组合。
1. Service:插件向系统提供什么
一个插件可以提供服务,例如:
ctx.llm:模型请求与流式输出的统一接缝;ctx.sessions:会话创建、加载、分叉与事件日志;ctx.tools:模型可见工具的注册与受控执行;ctx.agents:Agent 创建、恢复和运行时句柄;ctx.agentLoop:默认的 Turn/Step 驱动器。
消费者依赖的是接口而不是具体实现。因此,本地文件系统可以换成远程工作区,默认模型适配器可以换成兼容端点,Agent Loop 也可以被另一种调度策略替代。
2. Event:插件怎样介入正在发生的事
官方架构把事件分为三层:
| 事件域 | 用途 | 是否持久化 |
|---|---|---|
| Session Event | 用户消息、模型输出、工具调用与结果等事实 | 是 |
| Agent Event | 请求改写、Step 状态、取消、继续等运行中控制 | 通常否 |
| Capability Event | 文件、工具、遥测等能力的策略与适配 | 视实现而定 |
例如,企业想在执行工具前检查权限,无须复制 Agent Loop,只要在 tools/pre-execute 处挂一个策略插件;想给模型添加仓库规则,可以注册系统提示片段或向 Agent 注入上下文。
3. Reversible Effects:为什么“卸载插件”很重要
传统插件注册完事件监听、定时器或服务后,很容易留下悬挂状态。Cordis 要求副作用归属当前插件的生命周期:插件卸载时,相关服务、监听器与注册项一起撤销。
这使“运行时换能力”从一句口号变成架构约束,也为 Creator Mode 的动态试验提供了基础。
三、一次任务如何流过 Turn、Step 与 Session Log

官方将一次用户任务称为 Turn,一次模型请求及其工具调用称为 Step。一个 Turn 可以包含多个 Step:
Turn 开始
├─ Step 1:拼装上下文 → 请求模型 → 模型调用工具
├─ Step 2:带上工具结果 → 再请求模型 → 继续调用工具
└─ Step 3:模型确认目标完成 → 输出最终回答
Turn 结束
更精确的执行链是:
读取 Inbox
→ 拼装 System Prompt、历史与 Tool Schema
→ agent/pre-step(允许插件改写或拒绝)
→ 将输入写入 Session Log
→ 从日志派生模型历史
→ llm/stream
→ 写入 assistant/chunk 与 assistant/message
→ tools/pre-execute
→ tools/execute
→ tools/post-execute
→ 写入 tool/result
→ 判断继续下一 Step,或结束 Turn
这里有一个非常关键的设计原则:
凡是模型看见过的事实,都必须能从 Session Log 重建。
因此,会话恢复、轨迹回放、分叉、搜索、遥测不是额外挂在旁边的功能,而是同一条事件流的不同投影。相比只保存最终聊天文本,这种事件溯源方式可以回答更细的问题:模型为何调用这个工具、当时看到了什么结果、审批发生在第几步、恢复以后上下文是否一致。
四、四种模式不是四套产品,而是四种插件组合
| 模式 | 适合场景 | 主要特点 |
|---|---|---|
| Standard | 日常编码与通用 Agent | 文件、Shell、搜索、Skills、计划、目标、子 Agent 等完整能力 |
| Code | 多工具编排 | 在 Standard 基础上,将工具暴露给 Code Mode SDK,由模型生成 TypeScript 组合多步操作 |
| Minimal | 模型评测、最小实验 | 只保留持久 Bash 与 str_replace_editor,减少 Harness 变量 |
| Creator | 开发新 Harness 组合 | 运行时检查、内存插件试验、Preset 构建指导 |
理解这张表的正确方式不是“选择哪个 UI”,而是理解 Profile = 一棵有顺序的插件树。web 与 headless Profile 都从基础 Bundle 开始,再叠加各自的 UI 或一次性运行能力,最后应用用户自己的 cordis.patch.yml。
可以查看机器实际启动的组合:
dsh --profile web --dump-config
这条命令很适合学习源码:先看到真实运行树,再沿着每个配置行找到对应插件,比从 packages/ 根目录盲读更有效。
五、第一条使用路径:先用 Web UI 建立正确心智模型
1. 启动
安装 Node.js 后运行:
npx @deepseek-ai/dsh web
默认会启动本地 Web UI。进入 Settings → Models,配置 DeepSeek API Key;也可以按官方模型配置指南接入兼容端点。然后选择一个允许 Agent 操作的工作区。
2. 不要一开始就给真实主仓库最高权限
第一次建议使用临时仓库或 disposable checkout,并从类似任务开始:
只读分析这个仓库:列出主要包、入口文件、构建命令和潜在风险。
不要修改文件,不要安装依赖。
观察 Trajectory 时重点看四件事:
- 系统提示由哪些来源拼装;
- 模型拿到了哪些工具 Schema;
- 每个工具结果如何进入下一 Step;
- 审批策略在哪些操作上触发。
确认边界以后,再允许它在隔离分支上修改和测试。
3. 从源码运行
要研究或贡献 Harness 本身,可以使用官方仓库流程:
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
开发者预览期最好记录当前 commit,并在升级前对自己的插件、Preset 与 Session 兼容性做回归测试。
六、第二条使用路径:用 Python SDK 把 Harness 作为应用基座
如果 UI 只是你产品的一部分,或者任务来自 API、队列、CI,而不是聊天页面,应使用 SDK 驱动 Harness。
1. 安装
官方 SDK 当前要求 Python 3.10+:
python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk
发布包包含固定版本的 Harness 运行时,应用侧不需要另装系统 Node.js。准备好凭证:
export DEEPSEEK_API_KEY=sk-your-key-here
# 使用兼容代理时再设置:
# export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1
2. 最小可运行应用
以下代码直接采用官方 SDK 的核心调用方式:
from pathlib import Path
from deepseek_harness import DeepSeekHarness
config = Path("./minimal.cordis.yml").resolve()
workspace = Path("./workspace").resolve()
sessions = Path("./sessions").resolve()
with DeepSeekHarness(
provider="deepseek-official",
model="deepseek-v4-flash",
max_tokens=49_152,
cwd=str(workspace),
session_root=str(sessions),
cordis=str(config),
) as harness:
result = harness.run(
"检查仓库中的失败测试,解释原因并给出最小修复。",
session_id="repo-doctor-001",
)
print(result.final_response)
这里真正构成“应用基座”的不是 run() 这一行,而是四个你必须主动设计的边界:
cordis:应用究竟装载哪些能力;cwd:Agent 的工作区在哪里;session_root:轨迹与状态怎样持久化;session_id:何时延续上下文,何时创建独立任务。
复用同一个 Harness 实例与 Session ID,会继续原会话及其持久 Shell 状态;新任务应使用新 ID,避免历史和环境变量串入。
官方 jsonrpc-agent 最小组合使用 danger-full-access,文件编辑器可访问运行时进程能看到的路径。它适合 disposable checkout 或容器,不应原样放入处理真实用户输入的服务。
七、实战:把它做成“仓库诊断服务”
假设我们要构建一个内部应用:用户选择仓库与 CI 失败记录,Agent 分析原因,生成修复建议;只有用户批准后才允许修改文件。
1. 应用与 Harness 的责任划分
产品层
├─ 身份、仓库选择、任务队列、审批 UI
├─ 将 CI 日志和业务规则整理成上下文
└─ 展示 Session Events 与最终结果
Harness 层
├─ Agent Loop、上下文拼装、工具调用
├─ Session 持久化、恢复、分叉
└─ 沙箱、工具策略、模型适配器
基础设施层
├─ 临时工作区 / 容器
├─ Git、测试命令、制品缓存
└─ 凭证代理与遥测系统
2. 最小能力集
不要把 Standard 模式所有工具直接暴露给业务任务。第一版只需要:
- 只读文件搜索;
- 受限 Bash:只允许测试、类型检查与 Git diff;
- 精确文件编辑;
- 一个
request_approval或等价审批接缝; - Session JSONL 存储与任务级日志。
“工具越多越智能”通常是错的。工具越多,Schema 占用越大,错误选择面和安全面也越大。
3. 两阶段运行
建议把任务拆成:
阶段 A:read-only diagnosis
→ 输出根因、证据、拟修改文件、验证命令
人工审批
阶段 B:workspace-write remediation
→ 应用补丁、运行验证、返回 diff 与测试结果
即使模型可以一次完成,也不要省略边界。Harness 的目标不是最大化自治,而是让自治发生在可解释、可撤销的范围内。
4. 状态模型
业务数据库至少保存:
type AgentTask = {
taskId: string;
sessionId: string;
repositoryRevision: string;
workspaceLeaseId: string;
phase: "diagnose" | "waiting_approval" | "apply" | "done" | "failed";
requestedBy: string;
createdAt: string;
};
不要只存 sessionId。如果仓库 revision、工作区租约或权限主体改变,恢复旧 Session 可能让模型基于过期世界继续执行。
八、第三条开发路径:插件、Preset 与 SDK 应该怎样选
| 目标 | 最合适的扩展层 |
|---|---|
| 从后端启动、继续一个 Agent 任务 | Python SDK |
| 替换模型、文件系统、Shell 或存储实现 | Service Provider 插件 |
| 给模型新增一个业务动作 | Tool 插件 |
| 在工具前做权限、审计、限流 | Capability Event / Hook 插件 |
| 给某类任务固定一组能力和提示 | Agent Preset / Profile Patch |
| 给 Web UI 增加业务节点或视图 | Client/UI 插件 |
| 改变 Turn/Step 的根本语义 | 最后才考虑替换 Agent Loop |
最常见的错误是直接修改 packages/core/agent-loop。官方架构已经提供工具、事件、服务接缝时,修改主循环会放大升级成本,也更难验证状态与重放不变量。
一个业务工具插件在概念上只做三件事:
export const plugin = {
inject: ["tools"],
apply(ctx) {
const dispose = ctx.tools.register({
name: "query_incident",
description: "Read one incident by id",
inputSchema: {
type: "object",
properties: { id: { type: "string" } },
required: ["id"],
},
async execute({ id }) {
return await loadIncident(id);
},
});
return dispose;
},
};
上面是帮助理解边界的简化伪代码,不应当作当前预览 API 的可复制模板。真正开发时必须以仓库内对应包的类型、官方 Extension Cookbook 与当前版本示例为准。
九、如何高效读懂 DeepSeek Harness 源码
这个仓库包很多,按目录从 A 读到 Z 会很快迷失。建议使用下面的顺序:
第 1 天:先跑 Minimal Mode
只观察 Bash、编辑器、模型与 Session Log。目标是回答:“一次工具调用怎样进入下一次模型请求?”
第 2 天:读六个 Spine 包
按调用顺序阅读:
scope
→ session
→ system-prompt
→ tools
→ agent
→ agent-loop
重点不是记住类型名,而是画出每个包“提供什么服务、发出什么事件、依赖谁”。
第 3 天:追一条真实 Turn
从 agent-loop 的输入领取开始,跟踪到:
agent/pre-step
→ session append
→ deriveMessages
→ llm/stream
→ tool pipeline
→ step/end
用 Session JSONL 对照源码,比只看静态代码更容易理解。
第 4 天:研究一种 Capability Seam
选择文件系统、Shell、LLM 或 Subagent 中的一种,分别找出:
- Service Definition;
- Service Provider;
- Model-facing Consumer。
理解这三个角色,就理解了“一切皆插件”如何落地。
第 5 天:写最小外部插件
先注册只读工具或遥测监听,不要一开始改 UI、持久化和 Agent Loop。验证插件卸载以后,所有注册是否消失。
十、生产化清单
安全
- 工作区使用容器、临时 VM 或明确的 writable roots;
- Shell 命令按语义和参数审批,不只按命令名前缀;
- API Key 不进入 Prompt、Session Event 或工具输出;
- 来自网页、Issue、日志的文本全部视为不可信输入;
- 写文件、发请求、提交代码等高影响动作设置显式审批。
可靠性
- 固定 Harness、SDK、插件与 Cordis 版本;
- 每个 Turn 配置最大 Step、时间、Token 与工具调用预算;
- 工具返回结构化错误,让模型区分可重试、权限拒绝和永久失败;
- 恢复 Session 前验证仓库 revision 与工作区租约;
- 对取消、超时、进程退出和部分工具成功设计补偿路径。
可观测性与评估
- 以 Task、Turn、Step、Tool Call 四级关联日志;
- 保存模型、配置、Prompt 版本与插件组合摘要;
- 指标至少包含成功率、人工接管率、平均 Step、工具失败率、Token 与耗时;
- 使用真实但脱敏的任务集做回归,不只评最终文本,还评副作用是否正确。
十一、什么时候不该用 DeepSeek Harness
以下场景直接使用模型 API 往往更合适:
- 一问一答、摘要、分类等无工具任务;
- 延迟要求极低且只需要一次推理;
- 团队暂时无法维护沙箱、审批与轨迹存储;
- 产品流程完全确定,用普通工作流引擎即可精确表达;
- 不能接受开发者预览期的 API 变化。
Harness 是运行复杂 Agent 的基础设施,不是所有 LLM 功能的默认起点。
十二、总结:真正值得学习的是“可替换的控制面”
DeepSeek Harness 最值得研究的地方并不是工具数量,而是四个架构判断:
- 能力插件化:模型、工具、会话、沙箱乃至循环都从内核解耦;
- 事件即扩展点:观察、策略与拦截不必侵入主循环;
- 日志即事实源:模型可见内容可以恢复、重放和审计;
- 组合优于分支:面向不同产品,用 Profile、Bundle、Preset 和 Patch 组装,而不是长期维护 Fork。
如果要以它为基座构建自己的应用,最稳妥的路线是:
Web UI 跑通并观察轨迹
→ Minimal Mode 理解 Turn/Step
→ Python SDK 嵌入业务流程
→ 以最小工具集建立安全边界
→ 用插件与 Preset 扩展
→ 最后才考虑替换核心 Loop
这样做,你构建的就不只是“能调用 DeepSeek 的聊天应用”,而是一套能在真实环境中工作、被人类控制、也能持续演进的 Agent 系统。