DeepSeek Harness Creator 模式:让 Agent 给自己写插件
生命不息,折腾不止。DeepSeek Harness 最反直觉的一招:Agent 不只能「用」工具,还能在运行时给自己「造」工具——Creator 模式配七个
cordis_*工具,就是这套「自进化」的总开关。
前两篇我们把 dsh 跑起来、接上了自定义 Provider(想接 Claude/GPT 的话,中转站 ai.aklibk.com 国内直连、免绑卡、人民币按量付费,上一篇文章有完整步骤)。今天聊点更野的:让 Agent 在跑的时候,自己查运行时、自己写插件、自己热插拔。这就是 Creator 模式。
一、Creator 模式到底是什么
dsh 一共四个运行模式,切模式切换的不是模型,而是「这台 Agent 被允许拥有什么手脚」:
- Standard(标准):完整工具组合——文件编辑、shell、搜索,默认的编码 Agent 就是它。
- Code(代码,也叫 PTC):让模型生成一段代码来编排多轮工具调用,而不是一次只吐一个工具调用。
- Minimal(极简):只留一个 shell + 一个文件编辑工具,专给模型做基准测试用,是最诚实的「框架本身贡献了多少」的测法。
- Creator(创造):在 Standard 全套能力的基础上,额外开放一组操作 Cordis 插件系统的专属工具。
Creator 模式特别在哪?官方原话:它能「检查当前运行时、在内存里试验 Cordis 插件,并据此组合和创作新的模式」。翻译成人话,Agent 可以:
- 看现在这台 dsh 里到底有哪些插件在跑;
- 在内存里直接试验新的插件组合;
- 生成一个全新的 preset(
agent.cordis.yml)固化下来。
所以它不是一个「一键写插件」的魔法按钮,而是一个高信任的本地试验场。插件本身的写法还是 Cordis 统一规范(一会儿第六节讲),Creator 模式的价值是让 Agent 帮你查、帮你试、帮你生成骨架,把「需要熟读 Cordis API」这件事,降级成「用自然语言描述需求」。
二、七个 cordis_* 工具:三读四写
这七个工具由 @deepseek-ai/dsh-tool-cordis 包注册,就是 Agent「自进化」的全部弹药。先记住一句话:三个读的在前,四个写的在后——动手之前先看清楚现场。
| 工具 | 作用 | 改状态吗 |
|---|---|---|
cordis_inspect_list |
列出 Host 与 Client 已知的 Inspect Provider、方法和 schema | 否 |
cordis_inspect_query |
调一个 Provider 声明的只读查询 | 否 |
cordis_inspect_self |
查看当前会话拥有的动态插件、Package、版本与诊断 | 否 |
cordis_define |
记录一个新的不可变 Package;只校验,不运行 | 是 |
cordis_run |
首次运行、重启、回滚或更新到指定 Package | 是 |
cordis_stop |
停止当前运行,保留插件、Package、授权和版本指针 | 是 |
cordis_undefine |
永久删除插件及其所有 Package、授权和指针 | 是 |
注意:旧的 cordis_inspect / cordis_mount / cordis_unmount 三件套已经被这套版本化生命周期取代了。网上老教程还在讲 mount/unmount 的,过时了。
这套机制背后是四个包在协作,知道分工有助于理解审批逻辑:
@deepseek-ai/dsh-tool-cordis:注册七个工具 +@pluginId引用注入;@deepseek-ai/dsh-cordis-host-runner:保存动态插件、Package、版本指针,以及 Host 半部的运行状态;@deepseek-ai/dsh-cordis-client-runner:在浏览器侧授权并运行 Client 半部;@deepseek-ai/dsh-client-ui-cordis:在会话里渲染定义、启动和状态卡片。
记住「Host 半部 / Client 半部」这对词,第五节的审批机制全靠它。
三、完整生命周期:查 → 定义 → 运行 → 收尾
官方推荐的动作顺序,跟「进厨房先看配料再动火」一个道理:
1 | 1. cordis_inspect_list 先看有哪些 Provider、方法可用 |
cordis_inspect_query 只能用 cordis_inspect_list 返回的精确名字,瞎猜是要报错的。参数长这样:
1 | platform: host |
Host 查询在本地执行;Client 查询会等浏览器页面响应。这里有个硬约束:Inspect 只能读——读契约、服务、事件、Builtin、Slot、token 或当前树,不能代替业务 Service 调用,也改不了运行时。
cordis_inspect_self 三种用法,越具体信息越多:
1 | cordis_inspect_self # 当前会话的插件摘要 |
最后一种会返回这个不可变 Package 的 Host/Client 源码和运行诊断,出故障排查就靠它。注意 packageId 不能脱离 pluginId 单独查。
四、定义一个会说话的插件
cordis_define 是「写」的第一步,也是最容易误解的一步:它只校验、只保存,不运行、不申请授权、不移动版本指针。定义完系统会回你「已定义,尚未运行」。
新插件只提交一个 3–6 位小写英文语义前缀(idPrefix),Host 负责生成唯一 id:
1 | plugin: |
更新已有插件时,改成 kind: existing 并带上 pluginId,就会追加一个新 Package 而不是覆盖旧版:
1 | plugin: |
几个关键约束,踩坑率最高:
- 至少提供
code.host或code.client之一; - 内容是返回 Cordis Plugin 的普通 JavaScript function body,不转换 TypeScript、JSX 或
import; - Package 不可变——更新是追加,不是覆盖;
define成功会返回稳定的pluginId和精确的packageId,下一步必须显式cordis_run。
跑起来用 cordis_run,mode 只有两种:
1 | pluginId: echo-1 |
run:首次启动、重启当前版本或回滚;update:从当前版本切换到另一个 Package。
五、为什么「沙箱」不是安全边界
这是整个机制里最反常识、也最重要的一节,务必看完再决定要不要开 Creator。
审批与否,看代码跑在哪,而不是看它「危不危险」:
- Host 半部:跑在 dsh 的 Node 进程里、
node:vm沙箱内,能碰文件、网络、命令、服务和模型工具——全是 server 端资源,但不需要审批(由沙箱 + 运行时守卫兜底)。 - Client 半部:跑在浏览器页面里,能碰主题、布局、页面状态,全局只剩 React、console、styles、host 这几个,
fetch、setTimeout被藏起来了——却需要人工审批,因为它钻进了用户自己的页面和会话。
看起来很别扭对吧?更危险的 Host 半部反而免审,看着无害的浏览器半部反而要签字。原因就一句话:Client 半部是「用户的个人扩展」,触及的是用户的人设和会话,必须本人点头。
审批的细节(来自对 cordis_run 源码的阅读):
- 审批在
cordis_run阶段触发,且只有当这个 Package 包含浏览器侧代码、且该版本还没被授权过时才弹。返回awaiting-approval表示「在等人」,不是报错。 - 两种授权粒度:单勾(
approvedClientPackages只覆盖当前packageId)和双勾(clientVersionUpdatesApproved覆盖该插件未来所有版本)。因为代码一改就是新 Package,单勾下次还会再问。 - 授权挂在
packageId上,技术故障重跑不会重新弹;cordis_stop只停运行但保留授权;只有cordis_undefine才会连授权一起清空。
再说「沙箱」。很多人一听沙箱就觉得「关起来了很安全」,错。它更像是在厨房角落隔了一个小房间——两边的全局变量互相看不见,但它不是一个安全边界。官方口径:授予这套工具集,信任级别等价于授予 bash。沙箱只防「误用」,不防「恶意」。
沙箱里被移走的三个东西,尤其能看出设计者的用心:require、setTimeout、fetch 这三个 Node 入口被直接拿掉,但报错信息不写「禁止」,而是给你路牌——「Node timers 不可用,请用 Cordis timer 服务」「要网络?去看 web 服务」「文件进程?走 fs 和 bash 服务」。文件、网络、进程、定时器四类能力,被统一导向可审查、可审计的官方通道。更狠的是 process 和 Buffer 被当成「根本不存在」——模型爱写的 typeof process 探测直接失效,想偷偷摸环境变量的路被堵死。还有一个 vmTimeoutMs(默认 5000ms)兜住同步求值的超时。
最后是开这个模式的三个安全红线:
- 只在可信本地环境用,禁止公网部署开 Creator;
- 授权粒度能窄就窄,API Key 走环境变量,工作区目录收窄;
- 沙箱 ≠ 安全边界,别把「开了沙箱」当成「可以随便跑任意代码」。
六、Creator 是试验场,规范才是「真写插件」
最后把关系理清,免得你被「Agent 自己写插件」唬住。分两层看:
表层:Creator 模式让你在会话里直接下指令,比如「在 scratch-plugin/src/ 下给我生成一个插件,注册一个 fetch_jira_ticket 工具,Token 从环境变量 JIRA_TOKEN 读」,Agent 会生成 .ts 源码和对应的 cordis.yml。插件开发被降级成了自然语言描述。
底层:真正「写插件」走的还是 Cordis 统一规范,跟你用哪种模式启动无关。最小形态就是一个导出 name 和 apply 的 TS 模块:
1 | import type { Context } from '@deepseek-ai/cordis' |
再用一个 cordis.yml 把它插进运行时,路径必须绝对:
1 | - insert: |
启动时用 --patch 覆盖层加载(本地试验最方便):
1 | pnpm dsh web --patch ./scratch-plugin/cordis.yml |
想直接体验 Cordis 那七个工具,官方仓库里带了现成的 patch 文件:
1 | pnpm dsh web --patch apps/cli/config/examples/cordis/cordis.yml |
小结一句:Creator 模式负责「让 Agent 帮你把插件造出来、试出来」,而插件最终落地,靠的是 apply + inject + cordis.yml 这套规范。前者是试验场,后者是生产规范,两条腿走路。
生命不息,折腾不止。下一篇我们把这套「自进化」的底裤彻底扒开——《DeepSeek Harness 权限模型:沙箱 × 审批,两个旋钮怎么管住 Agent》,讲 read-only / workspace-write / danger-full-access 三档沙箱、ask / never 两种审批策略怎么组合,以及为什么
danger-full-access会默认关掉审批、它在无人值守 CI 里到底该不该开。