刚刚,DeepSeek Harness震撼开源:一切皆插件
今天凌晨,
当然,这并不意外,毕竟该项目之前已经铺垫了很久了,比如
我们也在 8 月初获得了
开源地址:https://github.com/deepseek-ai/deepseek-harness
比如这里,我们让配置了官方
考虑到近日 Andrej Karpathy 用 AI 生成 3D 世界的思路非常火爆,我们也让
整体来看,虽然离完美距离还很远,但这个动画的故事剧情大体还原,人物关系也大体能看出。相较之下,我们使用同样提示词,用配置了 GPT-5.6 sol-xhigh 的 Codex 制作出来的动画就差多了:
要知道,
今天随着
效果确实好一些了。
接下来,看看项目结构,非常惊人:仓库已经包含超过 230 个 workspace 成员,代码分布在 packages/、apps/、examples/、python/、native/、vendor/、website/ 等区域。文件系统、终端、子进程、PTY、语言服务器、网页访问、技能、子智能体、工作流、计划模式、会话持久化、设置、凭据、遥测,几乎每一项能力都有自己的包。
如果把普通的 Agent 项目比作一台已经装好的电脑,那么
它提供了一套默认组装方案,但看得出来,
DeepSeek Harness 是什么?
先厘清一个容易混淆的问题:
当今的 AI 社区对 Harness 这个词已经不陌生了。其原本的含义是马具、线束、约束装置等,向上抽象一下,其作用是把力量连接到可以工作的机构上,同时又不让这股力量脱缰。具体到 AI 上,Harness 负责的是把模型接到文件系统、Shell、代码编辑器、网页和其他 Agent 上,同时记录它做了什么、限制它能做什么,并在出错时决定是重试、取消、压缩上下文,还是把问题交还给用户。
这或许也能解释为什么这个项目的代码量和包数量会如此庞大,毕竟这其中涉及的任务和工具选择非常多,包括工具调用是否可并行,取消命令能否真正停止子进程,工具结果是否会污染上下文,用户在模型运行中发来的新消息应该插到哪里,会话恢复后怎样重建当时的模型输入,子智能体拥有哪些工具,文件写入是否越过工作区,界面回放时看到的内容能否和实时运行一致。
一切皆插件
项目建立在 Cordis 微内核之上,运行中的 Harness 本质上是一个 Cordis Context。不同包向 Context 注册服务、事件和能力,最终由配置文件把它们组合成一套可以运行的智能体。
packages/core/ 是整个系统的核心,其中包含 Session、System Prompt、Tools、Agent 和 Agent Loop。它们解决的是最基本的问题:会话是什么,系统提示词如何组装,工具如何注册和调用,Agent 如何创建,以及一轮对话怎样从用户输入走到模型请求、工具执行和最终回答。
核心之外是大量能力包:
- packages/llm/ 负责模型适配器和流式输出;
- packages/shell/、packages/subprocess/ 与 packages/terminal/ 负责一次性命令、进程树和持续终端;
- packages/fs/ 负责文件读写、编辑、搜索与策略限制;
- packages/lsp/ 连接语言服务器,让 Agent 不只能用文本搜索,也能获得语义级代码导航;
- packages/web/ 负责搜索与网页抓取;
- packages/skill/ 管理可复用技能;
- packages/subagent/ 和 packages/workflow/ 则把单个 Agent 扩展为可以委派和编排的多智能体系统。
再往外看,计划、目标、待办事项、后台任务、上下文压缩、会话查询、会话标题、凭据、用户设置、审批机制和遥测同样被拆成独立能力。这个结构最有意思的地方,是它体现了一种近乎执拗的边界意识:谁拥有接口,谁负责实现,谁把能力呈现给模型,尽量不要混在一起。
项目文档把典型能力拆成三层:接口、实现和消费者。
以 Bash 为例,接口定义「执行命令」是什么,本地实现负责真正创建进程,而面向模型的工具包负责把这项能力变成模型可理解的 schema 和结果。将来如果本地 Shell 要换成远程容器、云端沙箱或企业执行平台,理论上只需替换实现层,而不必重写模型工具和 Agent Loop。
这是一种典型的框架思维。它会让仓库在早期显得庞大,却也说明
在这里,我们也看到了
cordis.yml
一份配置组装出不同的 Agent
插件化架构最终通过 cordis.yml 落到开发者手里。配置文件列出插件名称、稳定 ID 和参数,决定当前 Agent 究竟拥有哪一组能力。
同一套代码可以被组装成完全不同的产品形态。加入
配置还支持覆盖层。TUI 和 Web UI 可以共享一份基础配置,再叠加各自的界面插件和参数;个人配置则位于最后一层。这样,部署方不必复制整棵配置树,只需要对指定插件做替换。不过这里也有一个需要留意的细节:配置补丁替换的是目标插件的整个 config,不是深度合并。如果只写一个新字段,原有的 API Key、基础地址或其他参数可能会一起消失。它很明确,但并不一定符合初次使用者的直觉。
项目还允许在 YAML 中通过 !!js 读取环境变量和运行时表达式,例如从 DEEPSEEK_API_KEY 获取密钥。配置只引用凭据名称,密钥在实际调用时解析。Web UI 会把密钥写入 $DSH_HOME/.credentials.yaml,而环境变量和 .env 可作为自动化或本地开发中的回退来源;密钥不应直接写入 cordis.yml 或进入会话日志。
Agent Loop
不是一个循环,而是一套交通规则
许多早期 Agent 项目的核心代码可以简化成几行:把消息发给模型,如果模型返回工具调用,就执行工具,再把结果发回模型,直到模型输出文本。
一次用户输入会开启一个 Turn,一个 Turn 中可以包含多个 Step;一个 Step 对应一次模型请求及其后续工具执行。请求前,系统会组装稳定的系统提示词、当前运行环境、工具 schema 和会话消息;请求后,模型的流式 chunk、完整消息、工具调用、工具结果和结束原因都会进入事件流。
上述丧尸射击游戏执行了 3 turn,127 setp
工具也不是「拿到函数名就调用」。它会经过前置策略、不可逆的安全守卫、实际执行、后置处理、内容整理和结果通知。允许或拒绝、超时、重试、指标统计、附加上下文,都可以从流水线的不同位置接入。工具可以声明某类参数下的调用是并发安全的,调度器便会让连续的只读任务并行;一旦碰到修改状态或无法确定安全性的调用,就把它当作屏障,等待前面的任务结束后独占执行。
这种设计看起来有些像在一条乡间小路上安装航空管制系统,但当 Agent 开始同时搜索十个文件、运行测试、接受用户追加指令,并且还要允许随时取消时,这些规则很快就会从「过度设计」变成「事故调查报告里最想早点拥有的东西」。
它还认真处理了运行中消息的去向。用户在 Agent 工作时发送的新内容,可能是下一轮任务,也可能是对当前工作的转向指令。系统区分排队消息、注入上下文和 Steering,并通过回执确认某条转向指令是否真正进入了某次模型请求。换句话说,它不只关心「消息收到了」,还关心「模型究竟在哪一步看到了它」。
Session Log
整个系统真正的权威来源
项目规定,凡是模型看见的内容,都必须能够从日志中重建。用户消息、运行环境上下文、模型请求信息、流式输出、工具调用和结果、压缩事件、权限切换、取消原因,都会以事件形式进入追加式会话流。界面、持久化、恢复、Fork、遥测和回放,不应该各自维护一份「差不多正确」的状态,而应从同一个事件源派生。
这项原则解决了 Agent 系统里一个非常棘手的问题:当一次任务出错时,我们究竟能不能知道模型当时看到了什么?
如果系统只保存最终聊天文本,许多关键因素会丢失。也许模型请求前刚刚注入了工作区状态,也许工具结果被裁剪过,也许系统自动切换了模型路由,也许用户在流式输出中途改变了方向。
会话持久化本身仍然是插件。项目提供 JSONL 和 SQLite 等后端,查询能力可以优先访问实时会话,也可以通过 SQLite 全文检索历史记录。Resume 会沿用原会话继续工作,Fork 则从一个确定的历史边界派生新会话。对开发者而言,这能为调试、评估、审计和自动化提供了统一基础。
从一个 Agent 到一群 Agent
主 Agent 可以把任务委派给子 Agent,子 Agent 可以是全新创建的实例,也可以从已有会话的完成边界 Fork,或者通过 ACP 连接外部子进程。
上述丧尸射击游戏创建了 5 个并行执行的子智能体
这里的作用域设计很重要。每个 Agent 拥有自己的上下文层,可以看到特定的工具、提示词和命令。某个子 Agent 可以被限制为只做搜索和分析,另一个则被允许修改文件。注册在 Agent 作用域里的能力会随 Agent 生命周期自动清理,不必依赖全局名称约定维持隔离。
工作流则更进一步:它允许用脚本驱动多智能体编排,把多个子任务、结构化输出和继续执行连接起来。项目同时提供目标、计划、待办事项和后台任务,它们并不是四个名称相近的 UI 小组件,其实是不同生命周期的协作状态。计划模式记录当前协作阶段,目标可以跨同一会话持续存在,待办事项为模型提供轻量任务清单,后台任务则负责管理仍在运行的实际工作。
这说明 Harness 想覆盖的不只是「一问一答式编程」。它希望支持长任务、并行调查、自动化运行和外部系统协调。至于模型能否稳定驾驭如此多的机制,是另一场测试;至少框架先把方向盘、仪表盘和刹车做了出来。
Web、TUI、Headless 与 SDK
面向普通用户,项目推荐 Web UI,默认监听 http://127.0.0.1:3080。它提供对话、会话侧栏、权限选择、计划模式、工具卡片和工作区交互。
Web UI 还提供了四种 Agent 预设模式。它们并非四套彼此独立的 Agent,也不只是改变提示词风格,而是基于同一套 Harness 宿主,为当前会话装配不同的工具、提示词和运行时能力:
标准模式:功能最完整的通用编码 Agent,提供文件编辑、Shell、文件与网页检索、Skills、计划、目标、子 Agent 和工作流,适合绝大多数日常开发任务;
PTC 模式:保留标准模式的全部能力,同时通过 Code Mode SDK 向模型呈现工具。模型可以编写一段 TypeScript 程序,在一次 run_code 中组合多步操作,减少模型与工具之间反复往返的开销,更适合调用链较长的复杂任务;
极简模式:只提供持久 Bash 与 str_replace_editor 两项工具。较小的工具集合减少了选择和上下文负担,适合路径明确、希望 Agent 直接动手的编码任务;
创造模式:在标准模式之上加入 Cordis 运行时检查、临时插件实验和 Agent preset 创作指导。Agent 不仅可以使用现有工具,还能探索并重新组合自己的运行时,进而创建新的自定义预设。由于它能够运行模型编写的插件代码,这是一个面向高级用户的高信任模式。
这组预设或许是「一切皆插件」最直观的产品化表达:底层的模型路由、会话持久化、沙箱和审批仍由共享宿主提供,预设只决定一个 Agent Context 中具体装入哪些能力。同一个 Web UI,因此可以从双工具的极简 Agent,切换成能够编排子 Agent 的标准模式,甚至进一步变成可以改装自身的创造模式。
举个例子,这里我们在创造模式下,让接入了
Web UI 之外,TUI 则面向喜欢留在终端中的开发者。
Headless 模式适合脚本和 CI:它接受一个任务,等待 Agent 完全停稳,输出最后一条有效回复后退出。如果程序需要结构化事件和持续控制,则应使用 ACP 或 JSON-RPC/Python SDK。
自动化方面,项目提供 ACP 服务和 JSON-RPC 入口。Python SDK 驱动随附的 JSON-RPC 运行时,让 Python 应用可以启动会话、发送任务、接收通知,而不必直接嵌入 Node 内核。仓库还包含 Code Mode、自指 Cordis、MCP 记忆服务等示例。
值得注意的是,这些入口并不是四套各自演化的 Agent。它们共享核心能力模型、会话事件语义和大部分基础插件,但并非简单替换一层 UI,而是通过不同 bundle 组装出 Web、一次性任务和自动化服务等产品形态。这正是「一切皆插件」最直观的成果。
Agent 可以检查甚至改装自己
这听上去有点像让汽车在高速公路上给自己换发动机,因而项目没有默认打开它。它适合研究或高级自动化场景:模型可以临时编写事件监听器、注册新工具、提供一个服务,再在任务完成后卸载。
自修改式 Agent 很容易沦为概念演示,但 Harness 至少把它放进了已有插件生命周期中。动态插件仍然运行在 Cordis 的 Context 和 Effect 机制下,注册项有明确的清理路径。
它还远谈不上安全无忧,却展示了这套架构真正想抵达的地方:智能体不只使用能力,也能在受控边界内重新组合自己的运行时。
Cordis 背后的设计,可以参考官方同步发布的论文《A Programming Paradigm for Spatiotemporal Composability》:
论文地址:https://github.com/cordiverse/paper
安全策略
编程智能体一旦获得文件系统和 Shell 权限,就可以修改代码、安装依赖、启动进程,甚至触碰工作区之外的主机环境。
项目默认采用 workspace-write 模式,将命令执行和文件修改限制在当前工作区及允许的临时目录中,并配合 ask 审批策略处理需要扩大权限的操作。更宽松的 danger-full-access 模式也存在,但必须由部署方明确选择;它不会被包装成一个看似无害的兼容选项。
工具调用还要经过前置策略、单调安全守卫、执行包装和后置处理。被守卫拒绝的操作不能被后续插件重新放行;需要扩大权限的命令必须说明原因,并通过审批机制重试。文件系统、Bash 和子进程共享同一套沙箱策略,避免出现「命令受限制,但文件工具可以绕过去」的割裂边界。
更值得肯定的是,
这套设计并不能消除智能体执行本地操作的全部风险,但它体现了一种难得的工程态度:安全是贯穿配置、执行、审批、日志与恢复机制的系统约束。模型可以提出行动,真正决定行动能否发生的,仍然是 Harness。
DeepSeek 想做的不止是「又一个 Codex」
如果只看 Web UI 或 TUI,很容易把
默认应用当然重要,它让开发者可以直接获得一个能读写项目、运行命令、规划任务和调用子 Agent 的工具。但真正占据项目中心的,是可替换的能力接口、事件驱动的生命周期、权威会话日志和声明式组合。换言之,成品 Agent 更像这套 SDK 的第一位客户。
这也给
因此,
本文来自微信公众号“机器之心”(ID:almosthuman2014),作者:关注DSH的机器之心,36氪经授权发布。















