DeepSeek Harness 深度评测 · Ep1DEEP DIVE
领域 Agent 与框架
DeepSeek Harness:从协议到内核,拆一台能改装的智能体引擎
视频版:B站 公开投稿中无对应视频(已核对全部 16 个投稿) 视频总览 →
本期要点POINTS
本期要点
关键实测数据DATA
关键实测数据
| 被测项 | 指标 | 值 | 实测日期 | 原始记录 |
|---|---|---|---|---|
| dsh(DeepSeek Harness) | 首字响应 TTFT | 0.8 s | 2026-08-14 | 未收录 |
| dsh(DeepSeek Harness) | 输出速度 | 135 tok/s | 2026-08-14 | 未收录 |
| dsh(DeepSeek Harness) | 上下文缓存命中率 | 93 % | 2026-08-14 | 未收录 |
口径:本地与云不混评(每条读数标了运行环境,两边数字不放在一起比); 一行 = 一条可核读数;论文与第三方数字不进本表(见上方来源表)。 「原始记录」指向公开仓 cnopens/ruiowl-evidence 的固定链接(带 commit SHA,防漂移);标「未收录」者为本地从未留存原始数据文件,不补造。
锐Owl · 解构系列 · DeepSeek Harness(Ep 1/4) 素材:2026-08-14 本地安装运行 + 真实会话实测 + 源码深挖(clone 后逐层拆解,全部论断带文件路径/行号)
一、四万星背后,先看账
2026 年 8 月 13 日,DeepSeek 开源智能体框架 Harness(dsh),24 小时 GitHub 四万星 [1]。热度是入场券,工程成色才是我们要拆的东西——「一切皆插件」是口号还是实现,拆完源码才能下结论。
实测从安装开始:一条 npm install -g @deepseek-ai/dsh,dsh web 启动后浏览器打开 3080 端口,完整中文界面,默认模型 DeepSeek-V4-Flash [2]。跑一轮真实会话(5 turns · 19 steps),账目如下:
| 指标 | 实测值 | 含义 |
|---|---|---|
| 首字响应 TTFT | 0.8s | 感知延迟 |
| 输出速度 | 135 tok/s | 吞吐 |
| 上下文缓存命中 | 93% | 长会话成本关键 |
← 表格可左右滑动查看
93% 缓存命中是这组数字里最值得注意的——智能体长会话中,重复读取历史上下文是最贵的开销,命中率高意味着长任务的钱包压力被压到最低 [3]。这是模型层的账,接下来进内核。
二、内核一:「一切皆插件」的源码真相
「一切皆插件」不是口号,是两层机制,全部有源码证据。
2.1 上下文是代理对象
读任何服务属性都走反射层,沿着一条叫 fiber 的链向上找实现——Context 是一个 Proxy(vendor/cordis/src/context.ts:74)[4]。这意味着「取一个服务」这件事本身是动态的、可拦截的。
2.2 注册即效果
每个插件注册的能力都带一个「撤销器」,插件卸载时它注册的一切按逆序自动解除(vendor/cordis/src/fiber.ts:427-442),整个框架没有一处改不动的特权核心 [5]。
2.3 事件五模式,waterfall 是关键
事件系统五种派发模式:emit / parallel / serial / bail / waterfall(vendor/cordis/src/events.ts:234-243)[6]。waterfall 的实现最值得看:它把最后一个参数当「下一个处理者」,链上每个监听器拿到它——调用 next,把结果传下去;不调用,直接否决。拦截、改写、短路,全在这一行里。
有个硬核细节:这些事件模式不是运行时检查,是编译期类型契约(scripts/jsdoc.ts:62)——写错模式,代码过不了 TypeScript 编译 [7]。也就是说,「一切皆插件」的安全感,一部分来自编译器。
三、内核二:智能体的循环与记忆
3.1 turn/step 状态机
主循环把一次对话拆成两层:一次 turn 包含零个或多个 step,一个 step 就是一次模型请求加它调用的工具。模型每次请求发出前都过一道 pre-step 拦截——监听器可以改写消息,也可以直接否决(不调用 next 即否决)(packages/core/agent-loop/src/agent.ts:234-242)[8]。
3.2 只追加的会话日志
整个系统的记忆是一条 append-only 的会话日志:每个事件带连续序号、被冻结成不可变对象(packages/core/session/src/index.ts:627-643)[9]。模型下一轮看到什么,不是直接读聊天记录,而是从日志做增量投影——只处理新增节点,旧结果缓存(index.ts:726-735)。
3.3 SQLite 的生产级容错
持久化用 SQLite:SCHEMA_VERSION=15,打开时校验文件标识,版本不匹配直接拒绝加载而非冒险迁移(packages/session/session-persistence-sqlite/src/schema.ts)[10]。连崩溃都做了容错:日志尾部没写完的部分识别为「撕裂尾巴」物理删除,已提交部分完好。这是冲着生产环境去的工程标准。
四、协议层:自研三件套,MCP 只剩一扇门
协议层是这期最见战略的部分。
JSON-RPC 极简:外部接口整条线只有 initialize / session / prompt / shutdown 四个请求,报文是换行分隔的一行 JSON(packages/sdk/protocol/src/types.ts)[11]。
Typert:类型即协议:用 TypeScript Compiler API 直接分析源码里的类型定义,生成编译器无关的类型图,再自动产出运行时校验器和 RPC 契约(packages/typert/generator/src/emitter.ts:257)[12]——协议由编译器生成,不是人手写的文档。自动化场景走 ACP,且刻意只上报「已提交的最终文本」,推理过程、工具调用全部不上线(packages/acp/acp/src/index.ts)[13]。
MCP 只剩一扇兼容门:MCP 还在,但只是一个客户端桥接插件——把外部 MCP 服务器的工具接进来用,工具名格式 mcp_服务器名_工具名,默认不启用,要自己改配置(packages/mcp/mcp-client/src/tools.ts:96)[14]。实测验证:问它有没有 MCP 工具,它说没有。核心链路全自研,这是「兼容但不依赖」的标准打法——协议定义权,不交出去。
五、安全边界:实测那条报错,代码里写着
我们实测里撞到的报错——查进程被拒,operation not permitted——在源码里有精确对应(packages/sandbox/sandbox-local/src/profiles.ts:51 + index.ts:205)[15]。
沙箱接口只做一件事:把要执行的命令「包装」一遍。macOS 上用系统自带的 Seatbelt,默认拒绝所有文件写入,只放行工作区、临时目录等白名单路径;系统内核拒绝白名单外写入时返回的正是 operation not permitted——错误签名按平台区分(Linux 上是只读文件系统)。
权限分三档(packages/sandbox/sandbox/src/index.ts:29)[16]:
| 档位 | 权限 |
|---|---|
| read-only | 只读 |
| workspace-write | 工作区可写(默认) |
| danger-full-access | 完全访问 |
← 表格可左右滑动查看
模型想升权限?可以,但要走审批,而且只能逐级升——跳级请求直接 throw,连问都不会问你(packages/sandbox/src/escalation.ts:157)[17]。所有沙箱后端不可用时,系统直接报错关门,绝不降级裸跑(fail-closed)。能力边界不是文档里的承诺,是内核级的强制。
六、设计架构:经典模式的现代组装
换架构师的眼光把前面的机制重新组装,每个核心设计都对应经典架构模式:
| 机制 | 架构模式 |
|---|---|
| 所有能力都是插件、无特权核心 | 微内核 |
| 会话日志只追加、永不修改 | 事件溯源 |
| 模型上下文从日志增量投影 | CQRS 读模型 |
| waterfall 的 next 链 | 洋葱式中间件(Koa 家族) |
| seam 三件套:接口/实现/消费分离 | 依赖倒置 |
| Typert 类型生成校验与契约 | 契约驱动 |
← 表格可左右滑动查看
两个权衡值得单独说:
日志为什么选只追加而不是原地更新? 只追加才可回放、可审计、可恢复,代价是存储增长——它用增量投影把这个代价抵消了。
沙箱为什么失败即关门? 因为它要守住的是安全下限——宁可不可用,不可不可控。
这套组合说明:它不是一个框架换皮,而是把二十年架构实践装进了 TypeScript [20]。
七、格局:模型、框架、协议,三位一体
这周国产智能体框架集体爆发——腾讯、阿里、字节、DeepSeek,外加社区双雄(trpc-agent-go 1.7K / AgentScope 28.9K / qwen-code 27K / Eino 12.7K / CowAgent 46.5K / CodeWhale 40.7K,GitHub 2026-08-14 拉取)[18]。怎么读这个局面?看三件事:生态绑定、持续投入、协议定义权。dsh 三项全占:背后是自家模型,官方快速迭代,协议全自研。它的打法是三位一体——模型、框架、协议绑成一套,这是要建生态,不是做一个工具。
风险也要说:开发者预览版,官方写明会有破坏性变更;模型适配目前只支持 DeepSeek 和 Pi AI,接本地模型得自己写插件(packages/llm/ + README)[19]。
判断:这是这一波里工程成色最接近生产级的信号——值得盯、值得研究,但别急着把生产依赖押上去。
参考来源
| # | 数据/论断 | 来源 |
|---|---|---|
| [1] | 40,117★ / 3,134 forks / 24h / MIT | GitHub API(2026-08-14 拉取) |
| [2] | 版本 0.1.0-rc.6、Node ^22.19\ | \ |
| [3] | TTFT 0.8s / 135 tok/s / Cache hit 93% / 5 turns·19 steps | dsh Web UI 会话统计(2026-08-14 实测会话) |
| [4] | Context 是 Proxy、fiber 链服务解析 | vendor/cordis/src/context.ts:74 + reflect.ts |
| [5] | effect 逆序 dispose / fiber 并行卸载 | vendor/cordis/src/fiber.ts:427-442, 675-686 |
| [6] | 事件五模式 emit/parallel/serial/bail/waterfall | vendor/cordis/src/events.ts:234-243 |
| [7] | @mode 类型级契约(非运行时断言) | scripts/jsdoc.ts:62 + 事件声明签名 |
| [8] | agent-loop idle/running 相位机、pre-step reject | packages/core/agent-loop/src/agent.ts:234-242 |
| [9] | SessionEvent append-only、deepFreeze、增量投影 | packages/core/session/src/index.ts:627-643, 726-735 |
| [10] | SQLite SCHEMA_VERSION=15、application_id、崩溃尾容错 | packages/session/session-persistence-sqlite/src/schema.ts |
| [11] | JSON-RPC 仅 initialize/session/prompt/shutdown | packages/sdk/protocol/src/types.ts |
| [12] | Typert:TS Compiler API → 类型图 → zod schema + RPC 契约 | packages/typert/generator/src/emitter.ts:257 |
| [13] | ACP 5 方法、automation-only(只发已提交文本) | packages/acp/acp/src/index.ts |
| [14] | MCP client:mcp__server__tool 命名、默认不启用 | packages/mcp/mcp-client/src/tools.ts:96 |
| [15] | Seatbelt deny file-write* + subpath 白名单;EPERM | packages/sandbox/sandbox-local/src/profiles.ts:51 + index.ts:205 |
| [16] | 三档权限 read-only/workspace-write/danger-full-access | packages/sandbox/sandbox/src/index.ts:29 |
| [17] | 变宽表逐级升、跳级 throw、fail-closed | packages/sandbox/src/escalation.ts:157 |
| [18] | 国产 harness 版图热度 | GitHub API(2026-08-14 拉取) |
| [19] | 模型适配仅 DeepSeek + Pi AI、开发者预览版警告 | packages/llm/ + README |
| [20] | 架构模式对照与权衡归纳 | 分析层:由 [4]-[17] 机制证据归纳 |
← 表格可左右滑动查看
锐Owl · 观察者 · 解构者 · 传播者
信号来源SIGNALS
信号来源
这一期从哪条雷达长出来(雷达 → 产出的双向可追溯):
node_links/radar_items.intent 的 feeds 指向关系当前为 0(M2 首轮回填统一先落 standalone,待人工指认)——回填后此处显示「雷达 YYYY-Www 条目 ③ → 已成为本期」。
来源表SOURCES