DeepSeek Harness (dsh) 执行管线全解剖
从「模型开口说跑一条命令」到「这条命令真的落地」——中间隔着七拍和两道闸。10张图讲透 dsh 的权限为何可预测:理论 · 逻辑 · 架构 · 技术细节
1一句话本质:dsh 是什么
dsh = DeepSeek AI 官方 2026-08-13 发布的 MIT 开源 Agent Harness(TypeScript),核心哲学「一切皆插件(Everything is a plugin)」,运行于 Cordis 插件框架之上。官方公式:Agent = Model + Harness——模型负责思考,Harness 负责把思考接入文件系统、终端、网页、工具链,让 AI 真正能干活。
这是 2026 年最完整的「Agent 工具调用权限治理」公开拆解——从事件级管线(七拍)到能力级闸门(两道闸)到结果级窗口(post-execute 四动作),给出了一套可预测权限的完整工程范式。天枢生态、Hermes、任何自建 Agent 系统的工具执行层都能直接对标。
知微已有生产级 Hermes v0.20.1(9 个月/20+ 轮升级/NRestarts=0)+ 天枢三通道派发。dsh 不是替代品,而是「执行安全层」的参考实现——它的七拍管线/单调守卫/意图闸正是天枢工具执行层缺失的。
2七拍执行管线:一次 tool call 的完整旅程
一次工具调用走的是固定七拍:先落 tool/call 事件,再进 pre-execute 处理 hooks、permission、sandbox,然后 guard 评估,接着才轮到 execute,随后 post-execute、finalizeContent 定稿,最后回档。
逐拍详解
| 拍 | 事件 | 职责 | 权限语义 |
|---|---|---|---|
| 1 | tool/call | 调用意图落事件日志,进入受管管线 | 启动执行;日志开始记录 |
| 2 | pre-execute | 处理 hooks、permission、sandbox 前置策略 | 第一道闸:可重排的 allow/deny/ask 闸门 |
| 3 | guard | 单调守卫:注册的 guard 只能 deny 或 abstain | 🔑 无 allow 出边——任何 no 就是 no;可执行面单调收缩 |
| 4 | execute | 真正执行:超时、重试、指标环绕 | 执行体运行(文件系统守卫在写盘事件上再拦一次) |
| 5 | post-execute | 四动作:accept / block / replace / add-context | 最后能改结果的窗口;再往下同步冻结谁都改不了 |
| 6 | finalizeContent | 定义方最后的内容不变量(同步且全量) | 结果规范化,不可再改 |
| 7 | tools/result | 只读观察;随后 loop 追加持久 tool/result 事件 | 不可变结果通知,入会话日志 |
3两道闸:写盘不是「过了工具级放行就算」
原文核心警告:写盘过了工具级放行还不算,得单独走 fs/write-intent 或 fs/edit-intent,这是第二道独立的闸。
read-only 帮你断网。受限策略要么真生效要么报错,静默降级永远非法(fail-closed 铁律)。
4guard 汇判与单调收缩:权限为何可预测
多个 guard 注册进来,各自表态 deny 或 abstain(弃权)。因为没有 allow 出边,任何一个说 no 就是 no——这就是「可执行面单调收缩」:装的插件越多,可执行面只会收缩或持平,永远不会扩大。
5沙箱三模式(只管文件效果)
| 模式 | 文件副作用 | 网络/进程 | 典型场景 |
|---|---|---|---|
read-only | 禁止写入 | ❌ 不受控(不在这套词汇表里) | 只读分析、代码审查 |
workspace-write | 限制写入到工作区和临时目录(默认) | ❌ 不受控 | 日常编码任务 |
danger-full-access | 放开限制 | ❌ 不受控 | 需要全盘操作的明确授权任务 |
SANDBOX_UNAVAILABLE)。
6审批四果与 callId 集成缝
approval 四种结果
| 结果 | 语义 | 处置 |
|---|---|---|
rejected | 用户/策略拒绝 | 按拒 |
cancelled | 审批流程取消 | 按拒 |
unavailable | 审批通道不可用(如无人响应) | 按拒(超时 deny 降级) |
allowed-once | 唯一的授予形态 | 🔑 只授被问到的那一个动作(one-shot),非一次性放行整类操作 |
callId:集成那条缝(原文工程判断二)
7完整架构:一切皆插件(Cordis 内核)
dsh 最核心的架构思想:没有特权核心——模型适配、工具、技能、会话、沙箱、存储、循环、调度、UI 全部是插件,连 agent 主循环本身都是插件(配置树里的一行,可被上层 patch 替换)。改任何能力只换插件,不动源码。
Profile / Bundle / Patch 三层配置组合
| 层 | 含义 | 例子 |
|---|---|---|
| Profile | 档案:列出要叠加的 bundles + 用户覆盖层 | ~/.dsh/profiles/,web/headless 自带模板 |
| Bundle | 组合包:配置行 + 装载代码的发行格式 | dsh-base(第一层基础)、dsh-web-app、dsh-headless |
| Patch | 补丁:按行 id 整行替换 config(不做深合并) | cordis.patch.yml、--patch 覆盖层 |
pnpm dsh --profile web --dump-config 打印本机组合出的整棵配置树——任何一行都可被 patch 替换。这就是「没有特权核心」的落地方式。
核心服务(ctx.*)
| 服务 | 职责 | 关键机制 |
|---|---|---|
ctx.llm | LLM 适配器 | provider 中立流式协议;所有失败归一为 finish {kind:'error'|'aborted'};replace() 原子换路 |
ctx.tools | 工具注册表+执行管道 | 七拍管线;scope 作用域(agent 级工具);Code Mode 确定性 SDK |
ctx.sessions | 会话事件日志 | append-only;deriveMessages() 投影模型历史;zstd 压缩 |
ctx.agentLoop | Agent 主循环 | Turn/Step 模型;并行工具有界滚动池(默认 10);协作式取消 |
ctx.systemPrompt | 系统提示组装 | 有序 section + 命名 variable + toolOrder 显式排序 |
ctx.fs / shell / sandbox | 执行能力三件套 | 共享沙箱策略;fs 意图闸写前检查 |
ctx.subagents | 子代理 | spawn(全新)/ fork(继承历史);one-shot / continuable |
ctx.approval | 审批服务 | one-shot 提示;never/ask 策略;ask→超时 deny 降级 |
ctx.jobs | 后台任务 | job id + owner 隔离 + 流式读取/等待/取消 |
ctx.workflowEngine | 工作流 | 模型写编排脚本(agent/pipeline/parallel hooks),worker-thread 隔离执行 |
8能力缝三角:换一个 provider 换掉整个产品面
dsh 第二大架构思想:一个可替换能力拆成三份——Service Definition(声明接口)→ Service Provider(实现)→ Consumer(通常是模型可见工具)。「一个缝 = 三角齐全」;一个 provider 替换可以换掉整个产品面的行为。
| 能力缝 | Definition | Provider | Consumer(工具) |
|---|---|---|---|
| 文件系统 | dsh-fs | dsh-fs-local(+远程/e2b) | tool-fs(read/write/edit) |
| Shell | dsh-shell | dsh-bash-local / sandbox;win32→pwsh | tool-bash / persistent |
| 沙箱 | dsh-sandbox | bwrap/Landlock/Seatbelt/ACL | bash-sandbox 包装 argv |
| 子代理 | dsh-subagent | in-process(fork/spawn)、ACP | tool-subagent / -control / -report |
| 技能 | dsh-skill | dsh-skill-filesystem | tool-skill + skill-badge |
| 代码执行 | dsh-code-runtime | worker-thread(+Python) | Code Mode(run_code) |
| Web | dsh-web | search: Exa/Perplexity;fetch: HTTP | tool-web(search/fetch) |
9事件源会话日志:模型可见 ⟺ 已入日志
dsh 最具标志性的设计:Session 是一个 append-only 的事件日志,是 agent 全部交互历史的唯一事实来源;模型消息历史是从日志派生的(deriveMessages())。
- user/message
- assistant/chunk
- assistant/message
- tool/call
- tool/result
- turn/start|end
- step/start|end
- compaction/*
- goal/change
| 机制 | 说明 |
|---|---|
| surface 投影层 | 只有 user/message、assistant/message、tool/result 三种事件可携带 surfaceOp 进入模型可见面 |
| compaction | 追加一条带 surfaceOp:{op:'replace'} 的摘要消息,把旧区间从派生历史「遮住」——原始日志保持不变,重放完全确定 |
| 崩溃修复 | 每条 assistant/message 记录 provider/model + 精确 sourceEventSeqs;崩溃可合成 TOOL_NOT_STARTED / TOOL_OUTCOME_UNKNOWN |
| fork() | 按边界切分带血缘的子会话;flush() 显式持久化屏障 |
10部署与上手
四行命令跑起来
| 模式 | 命令 | 用途 |
|---|---|---|
| Web UI | npx @deepseek-ai/dsh web | 浏览器 GUI,默认本机 3080 端口,选工作区→开聊 |
| Headless | dsh --profile headless "把失败的测试修好" | 无界面一次性执行,适合 CI/脚本化/服务器无人值守 |
| ACP 服务 | pnpm run demo:acp | JSON-RPC stdio 暴露 Agent 能力,编辑器/CI 集成 |
| Python SDK | pip install deepseek-harness-sdk | 自带 Node 运行时,目标机器不用装 Node |
环境要求
- Node.js ^22.19 || >=24(奇数版本不支持);pnpm 11.7.0(corepack enable)
DEEPSEEK_API_KEY:硬依赖,缺失直接MISSING_CREDENTIAL退出- 可选:
DEEPSEEK_BASE_URL、DSH_PERMISSION_MODE(默认 workspace-write)
关键配置(cordis.yml 节选)
# DeepSeek 模型适配器
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
config:
thinking: enabled # 启用思考模式
reasoningEffort: max
models:
- id: deepseek-v4-pro # contextWindow: 128000
- id: deepseek-v4-flash
# Bash 执行器
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
timeoutMs: 60000 # 命令超时 60 秒
# 会话持久化
- id: persistence
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: './.sessions'
compression: zstd
# 上下文压缩
- id: compaction-basic
name: '@deepseek-ai/dsh-compaction-basic'
config:
thresholdRatio: 0.8 # 窗口用 80% 触发压缩
retainRatio: 0.16 # 保留最近 16%
maxTokens: 8192
dsh-fs-local 和 dsh-fs-sandbox 会因 ctx.fs 重复注册 fail-loud 报错;SESSION_FORMAT_VERSION 保持 0 不承诺向后兼容(升级可能无法加载旧会话)。
11三方架构对比:dsh vs opencode vs pi
| 维度 | dsh | opencode | pi |
|---|---|---|---|
| 定位 | 平台化 agent harness「一切皆插件」 | 终端 coding agent 产品 | 极简 harness + 终端工具链 |
| 规模 | ~219 包 / ~45 万行 TS | 25+ 包 / ~66.7 万行 TS | 10 包(极简) |
| 核心框架 | Cordis 插件框架(vendored) | Effect 全栈 DI/并发(V2) | 自研分层(依赖倒置) |
| 会话事实来源 | 事件源日志(append-only + surface 投影) | SQLite(WAL,part 粒度流式) | JSONL 会话树(id/parentId 分支) |
| 工具管线 | pre-execute→guard→execute→post-execute→finalize→result | Tool.define + Effect Schema + 权限规则 | AgentTool 接口 + TypeBox 校验 |
| 权限/审批 | 沙箱模式 + 审批服务 + 权限预设 + fs 观察 | permission 规则(allow/deny/ask 通配符) | 无内置(默认信任、边界外置) |
| 沙箱 | bwrap/Landlock/Seatbelt/ACL,fail-closed | 无进程沙箱(tree-sitter 命令树分析) | 无(Gondolin/容器扩展) |
| 多代理 | 一等公民:子代理/jobs/workflow/goal | task 工具(parentID 链) | 官方不做子代理 |
| 自我修改 | ✅ 支持(cordis_* 工具挂载/卸载插件) | ❌ | ❌ |
12天枢生态对标:我们能借鉴什么
| dsh 机制 | 天枢现状 | 差距 | 借鉴动作 |
|---|---|---|---|
| guard 单调守卫(无 allow 出边) | 工具执行无守卫层(Hermes CLI/curl 直接执行) | 🔴 高危 | 天枢工具执行加「单调守卫」:任何插件 deny 即拒,执行面单调收缩 |
| fs/write-intent 意图闸 | 文件写入无独立意图检查 | 🟡 中 | 关键路径(写盘/删文件)加第二道独立意图闸 |
| post-execute 四动作 | 执行结果直接返回 | 🟡 中 | 结果出口加 accept/block/replace 拦截窗口 |
| 审批四果 + allowed-once | Hermes approvals.mode=auto(全免审批) | 🟡 风险面 | 高危操作改 one-shot 授权(allowed-once 语义) |
| callId 集成(显示=执行) | 看板/论坛展示与执行分离 | 🟡 中 | 执行回执携带 callId 回挂原展示 |
| 模型可见 ⟺ 已入日志 | 记忆系统三层(L1/L2/L3)+ 证据链铁律 | ✅ 同源 | 已对齐,继续强化 session 事件源化 |
| 能力缝三角(Def/Provider/Consumer) | 天枢技能市场 complete-package 规范 | 🟢 部分对齐 | 技能包拆分 Definition/Provider/Consumer 三层 |
| fail-closed(静默降级永远非法) | 健康检查已 fail-closed(⚠️→自愈) | ✅ 已对齐 | 保持 |
13采纳判断(玄机 L9 决策)
developer preview + 兼容性破坏警告 vs 款多多 100% 稳定红线 = 冲突;Hermes 已有同级实测(50% vs 53.3%)+ 9 个月生产验证;生产环境不允许试验性系统。
在知微工作区搭 dsh 跑同任务集,与 Hermes 实测对比(任务完成率/成本/稳定性三指标),为演进保留数据。
①插件化架构哲学(无特权核心+可逆热重载)②七拍执行管线(工具执行安全层)③单调守卫模型 ④能力缝三角 ⑤事件源会话日志。
14十条设计原则(工程启示)
15局限与风险(批判性视角)
Cordis、scope 链、能力缝三角、事件领域四选一、schemastery 配置——新贡献者要消化大量概念才能动手;215 篇文档本身就是一座山。
0.1.0-rc 明示破坏性变更随时来;SESSION_FORMAT_VERSION 停在 0、无兼容承诺——不适合急于上生产/存长期数据。
219 个 npm 包,依赖图复杂;「一切皆插件」带来大量间接层,阅读调用链成本高。
沙箱只约束文件副作用,网络/进程/syscall 不在词汇内;容器/microVM 才覆盖,E2B 目前是 POC。
initiator scope、scope 注册、子代理 Activation 都是进程内的——跨进程/分布式仍需未实现协议。
16证据链与参考文献
🎯 一句话总结
dsh 用「七拍执行管线 + 两道独立闸 + 单调守卫」把 Agent 的工具调用变成可预测的权限机器——guard 只有 deny/abstain 没有 allow,任何 no 就是 no,插件越多可执行面越小。这是 2026 年最值得抄的「工具执行安全层」范式:不学它的 219 个包,学它的拍序即权限、能力缝三角、模型可见⟺已入日志。