从马具到微内核:DeepSeek Harness 架构白话拆解
这两年 AI 从"聊天"慢慢变成"干活",帮你改代码、查资料、订机票。很多人以为是模型变聪明了,其实背后还有一套很少被提到的骨架。最近 DeepSeek 开源了一个叫 Harness 的东西,英文原意是"马具"——再好的马,不套上缰绳和挽具也拉不了车。AI 模型就是那匹有力气但没方向的马,Harness 就是那副马具。套上它,模型负责"聪明",Harness 负责"靠谱":一个让 AI 会想,一个让 AI 能把活干完。再进一步说,模型是引擎,Harness 是整车,车好不好开,看的从来不只是发动机。
这套马具具体管什么?给 AI 配上"手"(能调用的工具)、“记忆”(对话上下文)、“护栏”(安全审批),再包办它怎么思考干活的循环流程:想、动手、看结果、再想,直到做完。Harness 就像管家,把 AI 的每一项能力协调起来。它的进化也很有意思,可以看成五步:最早是写死的单文件脚本,AI 循环逻辑全写死在代码里,改一点就要动源码;后来有了框架,能把工作流画成图,但被框架绑得太死;再往后变成工程产品,安全、沙箱成了标配;接着变成开放平台,允许接各种渠道;最后到了 DeepSeek Harness,干脆把所有东西都拆成可随意装卸的插件。
从架构上看,这套"一切皆插件"的实现方式是一个微内核运行时——一圈能力插件,围着一个薄薄的内核:
整体架构 · 无特权内核 + 能力插件层
┌────────────────────────────────────────────────────────────┐
│ 可替换 · 能力插件层 │
│ Agent Loop 思考循环 │ Tools 工具 │ Sessions 会话 │
│ LLM 模型适配器 │ Approval 审批 │ UI / Headless │ 日志 │
├────────────────────────────────────────────────────────────┤
│ 无特权内核(Cordis 微内核) │
│ ① Service —— 能力按名字注入,不可替换 │
│ ② Typed Events —— 插件通信契约,不可替换 │
│ ③ Side Effects —— 注册即副作用,卸载即清理,不可替换 │
└────────────────────────────────────────────────────────────┘
注意"无特权"三个字。思考循环、日志、UI 这些在别的系统里是内核自带的,在这里统统只是插件,可以被替换。真正钉死在内核里的只有三个原语:Service 负责能力注入,Typed Events 规定插件之间只能通过类型化事件通信,Reversible Side Effects 管理外部资源——注册了什么,卸载时就自动清理什么。内核不做任何业务,只提供这三样机制。扩展能力的方式是"旁挂",而不是"打补丁"。
既然插件之间靠事件通信,事件系统就是整个系统的骨干。AI 干活的每一轮被定义成一条事件流水线,会话日志是一个只追加、不修改的事件数组,作为全系统的单一事实来源(SSOT):
轮次事件流 · turn pipeline
turn/start 轮次开始
→ agent/pre-step 代理步骤前处理
→ llm/stream 模型流式输出
→ tool/call 模型请求调用工具
→ tools/pre-execute 工具执行前(把关)
→ tools/execute 工具实际执行
→ tools/post-execute 工具执行后(把关)
→ tool/result 工具结果回填
→ step/end → turn/end 步骤结束 / 轮次结束
这条流水线有两个设计要点。一是事件溯源:AI 看到的历史不是单独存的副本,而是从日志增量投影出来的,只投影 user/message、assistant/message、tool/result 三类消息。分支、断点恢复、审计回放全部零成本派生自同一份日志,不存在第二份状态可以漂移——用一句话说就是"模型所见 = 日志所录"。二是把关位:审批、危险拦截、大结果替换、遥测埋点,全部挂在 tools/* 固定的三个事件上,横切策略不需要改任何插件代码:
tools/* 三个把关事件
tools/pre-execute 可拒绝 · 可改写 → 挂审批 / guard 守卫
tools/execute 实际执行点 → 注入点
tools/post-execute 结果拦截 → spill 溢出替换 / 遥测
三个事件各司其职:执行前能拦、能改,执行中是注入点,执行后可以处理超大结果(把大对象替换成引用 locator,防止撑爆上下文),还能顺手埋点。这种"统一把关位"让安全策略真正做到了零侵入——想加一条审批规则,只需要挂到对应事件上,不用碰任何插件代码。
能力怎么被替换?Harness 把每个能力拆成"声明—实现—使用"三段,叫 seam 三位一体。声明定义接口(schema 不变),实现可以任意换(本地文件系统、远程沙箱都是同一个 schema 的 Provider),使用方只依赖接口、不感知后端。把本地 Provider 换成远程沙箱,调用方一行不改:
seam 三位一体 · Definition / Provider / Consumer
# ① Definition —— 声明能力接口(不变的部分)
schema: 'fs.write'
input:
path: string
content: string
// ② Provider —— 实现接口(可热替换)
// 本地文件系统 / 远程沙箱共用同一 schema
const provider = await loadProvider('remote-sandbox');
// ③ Consumer —— 使用接口(不感知实现,换后端零迁移)
ctx.tools.call('fs.write', { path, content });
最后是配置和插件怎么生效。配置分四层叠加:bundle 层 → profile 用户层 → home 层 → --patch,后层整体替换前层(不是深合并);配置变更走 HMR 热更新,进程不重启,旧 fiber 卸载、新 fiber 创建。插件则分两条通道:host 插件(工具类)写入用户层 cordis.patch.yml 热加载;ui 插件(面板类)进 bundle 层 package.json + node_modules 静态组合。两路最终汇入 boot 组合,交给 Loader 挂载,改动即刻生效。
把架构图收起来看,这套设计的核心判断就一句:能换的都是能力,不能换的只有机制。事件通道、服务注入、副作用管理被钉死为内核,其余全部开放替换。这就是它敢喊"一切皆插件"的底气——不是把一切都做成插件,而是把"什么是不可替换的"想清楚了。对普通人来说,只要记住一点就够:AI 越来越能干,不只是模型在进步,更是有人把这匹马训练得越来越懂规矩——而 Harness 这类骨架,正是那副让它既跑得快、又跑得稳的马具。