DeepSeek Harness 深度解析:Agent 运行时与插件开发指南

DeepSeek Harness 是基于 Cordis 插件树的开源 agent 运行时,v0.1.7-rc.2 新增 Electron 桌面版,一切能力均可插拔替换。
DeepSeek Harness 以「agent = model + harness」为核心公式,将 agent 的工具、会话、权限、调度和执行拆解为可插拔的插件树。底层 Cordis 框架通过 fiber 状态机和 effect 机制实现依赖感知的热重载与自动资源清理,使 LLM 适配器、shell、文件系统、审批策略等能力在运行时动态替换而不丢失会话上下文。Web、headless、SDK、ACP 和 Electron 桌面版共享同一套运行时,换入口无需重写 agent。新发布的 Electron Desktop v0.1.7-rc.2 将本地服务与凭据交接纳入应用生命周期,提供插件、定时任务和运行记录的可视化管理。项目仍处于开发者预览阶段且未完成安全审计,官方建议在独立目录、最小权限环境下使用,第三方插件应锁定 commit 并先审阅源码再授权构建。
DeepSeek Harness 到底是什么
DeepSeek广告 Harness 是 DeepSeek AI 开源的 agent 运行时,官方给出的定义公式很直白:agent = model + harness。模型负责理解任务、生成下一步,harness 则把环境、工具、会话、权限和执行过程连接起来。据 B 站 UP 主核验,最新公开候选版本是 DSH v0.1.7-rc.2,官方仍将整个项目定位在开发者预览阶段——功能已经可用,但兼容性和安全边界都还在变动。
打开 Web 工作台,你会看到工作区文件读写、代码编辑、终端、任务计划、审批和运行轨迹已经全部连在一起。agent 可以在项目目录里读文件、改代码、执行命令,并把每一步的工具调用和文件变化记录到会话里。这意味着工作区不只是左侧一棵文件树——它决定了 agent 能看到什么、能改什么,也决定了你能不能复盘一次失败的运行。会话可持久化,后台任务和计划任务都有独立记录,不会只剩聊天框里的最后一句话。

多入口共享同一套运行时
DSH 提供了 web、headless、sdk、sdk-minimal、plugin 等多种 profile 或命令形态。headless 从标准输入接收任务、用 session id 串联,再把过程按 JSONL 输出给自动化程序;sdk 和 ACP 用来接入其他客户端;plugin 则负责给 profile 安装、移除和更新能力包。
这套设计的核心价值在于:浏览器、脚本、编辑器和桌面端可以共用同一套运行时,换入口不需要重写 agent。能力层面同样是插件化的——MCP 接外部工具和资源,SSH 把远程目录变成工作区,浏览器后端和 computer use 面向网页与视觉交互,agent-team 可以拆分子 agent 协作,PTC runtime 在受控环境里组织多次工具调用。此外还有文件预览(覆盖 Markdown、PDF、Office)、技能、工作流、LSP、Webhook、语音转写等对应能力包。
仓库反复强调的理念是「一切皆插件」:LLM 适配器、shell、文件系统、存储后端、agent loop、审批策略、调度器乃至客户端模块都可以替换。官方能力图里的 ctx.llm、ctx.tools、ctx.agents、ctx.sessions、ctx.schedule 都是可被插件提供或消费的服务。
MCP(Model Context Protocol)是由 Anthropic 提出的开放协议,旨在标准化 LLM 与外部工具、数据源之间的通信方式。它定义了 host、client 和 server 三层角色:host 是运行 LLM 的应用(如 Harness),server 是暴露工具和资源的外部服务,client 在 host 内部负责与 server 通信。通过 MCP,任何按规范实现的外部服务(数据库查询、API 调用、文件系统等)都可以被 LLM 以统一方式调用,而不需要为每个 LLM 框架单独适配。DeepSeek Harness 将 MCP 作为接入外部工具的标准插件,意味着整个 MCP 生态的工具服务器可直接接入,降低了工具扩展的集成成本。ACP(Agent Communication Protocol)则是 agent 间通信的协议层,用于编排多 agent 协作场景。
Cordis 生命周期与热重载机制
Harness 底层由 Cordis 负责加载依赖、管理生命周期和资源回收,具体的 agent 能力则由挂载进来的插件贡献。每个插件拿到一个 ctx,通过它注册服务、工具、事件和子插件;loader 再从配置文件把这些插件组合成一棵运行时树。
每个已加载实例都有一个 fiber 状态,会在 pending、loading、active、unloading、disposed 之间流转,也可能进入 failed。值得区分的是,pending 不代表悄悄坏掉,通常表示 inject 声明的服务还没出现——服务回来后插件才会继续加载;服务提供方消失时,依赖它的插件会先卸载,服务恢复后再重新加载。这正是「能力可替换还能保持一致性」的原因。
加上 effect 机制,监听器、工具注册、定时器、连接和子插件都能在卸载时自动清理。所以热重载不是简单地重新 import 一遍文件,而是先拆掉旧实例、再按依赖关系装回新实例。
Cordis 是一个通用的依赖注入与插件容器框架,最初在 Koishi(聊天机器人框架)生态中发展成熟,后被 DeepSeek Harness 采用作为底层运行时。它的核心思想是将应用程序分解为相互独立的插件单元,由框架统一管理它们的依赖关系和生命周期,而不是让插件之间直接相互引用。这与 Node.js 传统的 require/import 模式有本质区别——传统方式中模块一旦加载便常驻进程,Cordis 则维护着每个插件的状态机,可以在运行时动态卸载、替换和重载某个插件,而不影响其他插件的运行。这种架构在长期运行的服务场景中尤其重要:开发者可以热更新单个工具插件或切换 LLM 适配器,而不必重启整个 agent 进程、丢失所有会话上下文。
手写第一个插件
官方 Cordis 教程从最小示例开始:在临时目录创建 hello.ts,不需要 CLI,也不需要先搭一个完整 agent。代码只要导入 context、导出一个可选的 name,再导出 apply。apply 里打印一句「hello from my first plugin」即可。然后在 cordis.yml 里以 - name: hello.ts 挂载,loader 创建 context 读取这份 yml、挂载子插件,再调用你的 apply。插件文件不负责启动框架,它只描述自己的贡献。
更接近真实用途的是工具插件示例:从 @deepseek-ai/cordis 引入 context,从 dsh-tools 引入 defineTool 并声明 inject: ['tools']。在 apply 里调用 ctx.tools.register(defineTool(...)):工具名叫 greet,参数是必填字符串 name,description 告诉模型什么时候用它,parameters 生成输入约束,execute 返回规范值,output.schema 描述值的形状,output.render 把它变成模型和会话可读可存的内容。
这里的分工很关键——参数校验、执行逻辑、结果规范和展示不是同一个函数里随便拼的字符串。启动后在 Web 里输入「use the greet tool to greet Ada」,模型就能调用这个工具。教程还展示了不走模型也能触发真实执行流水线:给调用填一个 callid,直接 ctx.tools.execute,再监听 tools.result。

服务、事件与配置
服务是挂在 ctx 上的具名能力,比如 ctx.llm、ctx.tools、ctx.agents。提供方用 service 注册名字,消费方写 inject,Cordis 会等服务就绪后再执行 apply,因此消费方不需要 import 某个具体实现。配置里换掉 shell 或 LLM 的提供方,消费方就能重新启动。
事件让插件在不知道监听者是谁的情况下通信,典型的有 tools.result 和 session.event。监听器本身也是 effect,插件卸载时会自动移除,不会把旧回调留在已经失效的会话上。
配置方面,插件导出 config 类型和 schema,为 greetingTimeout、重试次数等字段写默认值和约束。用户在 cordis.yml 里传配置,加载时先校验;改配置后 HMR 会卸载旧实例,再把新配置挂载起来。
发布插件的坑与建议
发布时,本地源码可以用 patch overlay 临时挂载,正式交付则做成组合包。组合包的 package.json 声明 dsh.bundle,cordis.patch.yml 把包里的插件横插入 profile。用户执行 dsh plugin 命令即可安装,profile 会记录已安装的 bundle。
启动顺序按层叠展开:base bundle、已安装组合包、profile 自己的 patch、home 及 patch,最后才是命令行 overlay。后应用的层会覆盖前面的层,而且 patch 覆盖的是整行 config,不是深度合并。
从 GitHub 安装有一个限时坑:拿到的是源码,不会自动跑 build,所以包需要 prepare 脚本生成可加载入口,pnpm 可能要求用户在 allow-builds 里明确授权——这等于允许第三方代码在本机安装时执行。最稳妥的做法是只信任源码并锁定 commit;不想让用户处理构建权限,就发布带 lang 的 npm 包,或用 Turbo 交付。

「patch 覆盖整行 config 而非深度合并」这一行为源自层叠配置(layered config)的设计取舍。深度合并在处理嵌套对象时直觉上更友好,但会导致「无法通过上层配置删除下层某个键值」的问题——你只能添加或覆盖,却无法表达「移除」语义。整行覆盖虽然要求上层配置写全该节点的完整值,但语义明确,避免了合并顺序引发的隐式行为。实际编写组合包时,这意味着如果你的 cordis.patch.yml 覆盖了某个已有插件的 config 节点,需要把该节点下所有字段都写出来,否则未写的字段会被清空而不是保留原值。调试配置层叠问题时,可以先用 dsh config 或 Web 工作台的配置面板查看展开后的最终配置,再逐层对照各 patch 文件定位覆盖来源。
Electron 桌面版更新了什么
以前没有客户端时,常见路径是终端执行 npx @deepseek-ai/dsh web,等本地服务起来再打开 3080 端口的 Web 页面。这种方式透明、适合开发,但端口、进程、工作区、插件和配置都得自己记着。
Electron Desktop 把完整的 dsh web 应用包进了一个桌面壳。首次打开有引导登录、API key、插件和任务的可视化入口。你不再需要判断哪个 host 在跑、手动找 profile 目录,插件列表、启停、配置状态和运行中的任务都能在界面里看到——这是这次更新最直观的变化。
架构上它并没有另写一份 agent:Electron 主进程启动独立的 dsh Desktop host 子进程,host 运行共享的 dsh web profile;渲染器通过 dsh-app:// 协议加载打包入口,HTTP 转发到经过认证的本地 web host,实时流走 WebSocket,启动关闭通过 node-ipc。Web 默认端口 3080,Desktop host 默认端口 19387。桌面版只是把本地服务和凭据交接纳入应用生命周期,Electron 负责窗口、菜单、托盘和更新,agent 的模型、工具、会话和插件仍来自同一颗 profile。

rc.2 补的更多是日常使用的顺手度:首次引导会解释额度、用途和过程;账号登录与 API key 入口分开;额度不足时提示更具体;自动审阅可按需开启;Inspector 不再默认塞进每次安装;新启用的工具能直接服务当前会话;定时任务支持创建提醒、查看运行记录,重启后仍保留,重复间隔可按分钟设置;快捷键有了可查看、搜索、自定义和恢复的页面;本地 Markdown 图片可预览放大;插件安装失败会给出提示;关闭主窗口默认隐藏,host、会话和运行任务继续留在后台,Windows 还能从托盘找回窗口。真正退出前,桌面端会检查活动任务和已启用的定时提醒,先给确认再打断工作。
安全边界与选型建议
Harness 与普通聊天式智能体的差异,本质在运行边界。普通聊天产品更像完成一轮问答,Harness 还要处理连续步骤、工具结果、会话恢复、后台任务、审批、沙箱和插件生命周期。
官方安全说明明确指出:项目尚未完成安全审计,沙箱和审批是降低风险而非绝对隔离。模型生成的代码、第三方插件和本地 host 都可能触碰文件、进程、网络和凭据,别直接放进带生产密钥的工作区。更稳妥的做法是——独立目录、最小权限、定期备份、先读插件源码再授权安装构建脚本。
结论很清晰:DeepSeek Harness 的主角不是又一个聊天窗口,而是一棵可观察、可卸载、可替换的 agent 插件树。Electron 桌面版把这棵树收进了更易上手的应用,Web、CLI、SDK 和 ACP 仍共享同一底座。研究 agent 工程的开发者,建议按仓库的 profile、Cordis 教程、工具定义和能力分层一路读下来,再亲手做一个 greet 插件;只想尝鲜的话,就在无敏感数据的独立工作区里,先验证桌面任务、定时任务和插件卸载是否符合预期。
相关推荐

AI智能体的真实风险:被夸大的"黑客"与被忽视的隐患
AI智能体"黑客"事件频发,但真实风险究竟是什么?本文剖析OpenAI训练暂停、DNS隧道漏洞、Meta Muse隐私泄露,以及智能体消除摩擦可能引发的银行挤兑与医疗成本上涨,提出"AI现实主义"的理性视角。

OpenAI Dev Day 全盘点:20+ 发布背后的三大趋势
OpenAI Dev Day 一次性发布 20+ 产品,涵盖个人智能体 DOTS、GPT-6.1 Sol、Decisions API、Space 协作区与模型市场。本文全面盘点并解读其揭示的三大 AI 趋势。

只想要一个自定义域名邮箱,为何如此艰难?
拥有一个自定义域名邮箱看似简单,实则涉及 SPF/DKIM/DMARC 配置、IP 信誉、托管服务成本等诸多难题。本文梳理自建与托管方案的权衡,并给出实用建议。