openinterpreter ZCode Harness:skill-creator 技能规范与"创建-测试-迭代"工作流深度解析
skill-creator 是 openinterpreter 仓库 ZCode harness 内置的一个"造技能的技能"(skill for authoring skills)。本篇基于仓库中的技能定义文件 zcode_skill_creator.md 展开,完整继承其中的技能创建循环、SKILL.md 结构规范、渐进式披露(progressive disclosure)机制与迭代改进方法论,并结合 handle_zcode_skill 处理器、ZCode 请求构建器 等源码,说明该技能如何被编译进二进制、如何被 Skill 工具按需加载,读者可据此掌握在本地编码 Agent 中编写、触发与持续优化可复用技能的完整方法。
一、技能定位:一个编译进二进制的内置技能
从源码结构看,skill-creator 不是放在磁盘上等待发现的普通技能,而是以 Rust include_str! 宏直接嵌入 codex-core 编译产物的内置资源:
- 技能正文即 zcode_skill_creator.md,文件头带有 YAML frontmatter(
name: skill-creator与一段用于触发的description); - harness_aliases.rs 中将其声明为常量
ZCODE_SKILL_CREATOR_MD,并配套版本常量ZCODE_SKILL_CREATOR_VERSION: &str = "0.1.0"; - zcode.rs 的 builtin_zcode_skills_message 会在会话的内置技能清单中向模型宣告
skill-creator:skill-creator的存在及其用途摘要,并给出"可加载路径"(官方插件缓存目录下的SKILL.md路径)。
这条链路解释了文档开头那句 "A skill for authoring and iteratively improving local ZCode skills" 的工程含义:模型先通过元数据感知到技能存在,随后调用 Skill 工具触发加载,处理器再把正文注入上下文。
Skill 工具如何交付正文
handle_zcode_skill 的处理逻辑与文档中"三层加载"的说法直接对应:
- 解析
Skill工具调用参数,取skill字段; - 当值为
skill-creator时,剥离 frontmatter(strip_prefix("---\n")后再按\n---\n切分),只保留 markdown 正文; - 组装返回文本:以
<skill_content name="skill-creator">包裹正文,并附加 "Base directory for this skill: ...",该 base directory 由OPEN_INTERPRETER_HOME/INTERPRETER_HOME/CODEX_HOME环境变量(缺省~)拼接到.zcode/cli/plugins/cache/zcode-plugins-official/skill-creator/0.1.0/skills/skill-creator; - 若请求的是其他技能名,则返回 "Skill
{skill}is not available through the native ZCode harness yet" 的失败提示。
也就是说,文档承诺的"元数据常駐上下文、正文按需加载"这一渐进式披露第一层到第二层的跨越,正是由这段处理器代码实现的。
二、核心循环:定位用户处于哪一环
文档开宗明义给出了工作流总纲,这也是使用该技能时最应先内化的部分。技能加载后,Agent 的职责是判断用户处于循环的哪个阶段并帮助其推进——用户说 "I want a skill for X" 就从最顶端开始;用户已持有草稿则直接跳到评估/迭代环节。文档特别强调灵活性:如果用户说 "just vibe with me, no formal evaluation",就按用户节奏来,不强行执行完整评估。
循环本体(文档 "At a high level, the loop is" 一节):
- 弄清技能要做什么、大致怎么做(Capture intent);
- 写出技能草稿(Write a draft);
- 用 2–3 个贴近真实的测试 prompt 试跑(Try the skill on 2–3 realistic test prompts);
- 与用户一起阅读输出并修改(Read the outputs with the user and revise);
- 重复直至技能足够好(Repeat until the skill is good enough)。
文档 "The core loop, one more time" 一节再次收束为六步:搞清楚技能主题 → 起草 → 跑 2–3 个真实测试 prompt → 与用户共读结果 → 改进 → 重复直到用户满意或改进不再奏效。两端呼应是为了防止迭代过程中偏离主线。
关于与用户的沟通方式,文档还有一条常被忽视的操作准则:使用者从资深技能作者到新手都有,出现术语不确定时应简短解释而非假设对方熟悉——例如 "an eval prompt is just a test message you'd send the model to see how the skill behaves"。这条准则本质上是把"技能文档的读者"与"技能使用者的水平差异"做了显式处理。
三、创建技能:从意图捕获到 SKILL.md 结构
3.1 Capture intent(意图捕获)
文档建议:如果当前会话本身已经展示了一个值得固化的工作流(比如用户同一件事手动做了多次后说 "turn this into a skill"),应优先从会话历史中抽取答案——用过哪些工具、步骤顺序、用户做过哪些纠正、输入/输出格式——然后再就缺口向用户确认。
文档给出的四个标准问题应作为访谈清单完整保留:
- What should this skill enable the model to do?(这个技能要让模型能做什么?)
- When should it trigger? What user phrasings or contexts?(何时触发?哪些用户措辞或上下文?)
- What's the expected output format?(期望的输出格式是什么?)
- Are there example inputs/outputs to lock the behavior down?(有无可锁定行为的示例输入/输出?)
3.2 技能目录与优先级(Where skills live)
ZCode 按以下优先级(从高到低)发现技能:
<project>/.zcode/skills/<name>/SKILL.md
<project>/.agents/skills/<name>/SKILL.md
~/.zcode/skills/<name>/SKILL.md
~/.agents/skills/<name>/SKILL.md
文档给出的选型规则是:
- 新技能默认放在
.agents/skills/—— 这是跨工具(cross-tool)标准位置; .zcode/skills在发现阶段仍然优先:同名技能两处都存在时,.zcode/skills副本胜出,因此.zcode/skills是**覆盖(override)**已存在技能的地方;- 只对当前仓库有意义的技能选
<project>路径;希望处处可用的个人技能选~/(用户级)路径。
这一优先级模型与仓库中 session_skills.rs 解析 <skills_instructions> 块的方式相互印证:模型侧看到的可用技能清单是 - name: description (file: path) 形式,path 可为绝对路径,也可能在预算压力下呈现为 rN/... 别名路径(见该文件 L16-L26 注释与测试用例),说明发现阶段的路径解析确实发生在 harness 之下的统一 skills 层。
3.3 SKILL.md 的必备结构
每个技能是一个目录,核心是带 YAML frontmatter 的 SKILL.md:
my-skill/
├── SKILL.md (required)
└── (optional)
├── references/ (extra docs the model reads on demand)
├── scripts/ (helper scripts the model can invoke)
└── assets/ (templates, fixtures, etc.)
frontmatter 必填字段及其约束:
name—— 技能标识符。小写 kebab-case,1–64 个字符,必须与目录名一致;description—— 技能何时触发、做什么。文档明确指出这是首要触发信号:技能"做什么"和"在什么上下文下"都应写进 description 而不是正文。还给出了一条关键反直觉经验:模型倾向于触发不足(under-trigger),所以 description 应该写得"稍微强势一点"(a little bit pushy)。文档给出的对照改写示例值得保留:- 弱:"How to build a dashboard for internal data"
- 强:"How to build a fast dashboard for internal data. Use whenever the user mentions dashboards, data visualization, internal metrics, or wants to display any company data — even if they don't explicitly say 'dashboard'."
可选(预留)字段以 ZCode 技能规范为准;对多数技能,name + description 两项即够。
3.4 渐进式披露(Progressive disclosure)
ZCode 分三层加载技能,token 预算控制思路清晰:
| 层级 | 内容 | 加载时机 | 预算约束 |
|---|---|---|---|
| 1. 元数据 | name + description | 常驻上下文 | 必须短小 |
| 2. SKILL.md 正文 | 完整指令 | 技能被触发时 | 目标 500 行以内 |
| 3. 打包文件 | references/、scripts/、assets/ |
按需读取 | 原则上无大小限制 |
当正文变长时,文档给出的拆分模式是把领域细节移入 reference 文件,并让 SKILL.md 明确指示"何时去读它们":
cloud-deploy/
├── SKILL.md (workflow + selection)
└── references/
├── aws.md
├── gcp.md
└── azure.md
SKILL.md 中相应地写一句 "if the target is AWS, read references/aws.md before proceeding"。这套"目录即路由表"的设计正是三层加载在实操中的落法:正文充当调度器,细节延迟到确定需要时才进入上下文。
3.5 写作风格(Writing style)
文档给出四条可执行准则:
- 用祈使句("Read the file before editing");
- 解释 why:当规则不显然时说明原因——现代模型在理解理由后对指引的遵循度更高;
- 警惕全大写 MUST/NEVER:如果你发现自己在写一堆全大写的 MUST 和 NEVER,通常说明规则需要更好的解释,而不是更响亮的强制语气;
- 示例胜过规则:若技能产生结构化输出,直接给一个字面格式示例;若应使用特定工具,直接展示调用。
四、测试:2–3 个真实 prompt 的评估循环
文档对测试阶段的要求非常具体:
- 写完草稿后,自己先想好 2–3 个真实感测试 prompt——像用户会真的输入的那样:带具体文件路径、列名、随意的措辞,甚至可以有错别字;
- 先与用户分享:"Here are a few cases I want to try. Anything to add or change?";
- 然后逐条执行:加载草稿技能,把测试 prompt 交给模型,检查实际发生什么。文档特别注明当前 ZCode 不会派生并行评估子代理(does not currently spawn parallel evaluation subagents),因此一次跑一个 prompt,并与用户共同查看每个结果。
"Reviewing the draft" 一节给出每条 prompt 的标准操作:
- 确保草稿技能已落在上文四个可发现目录之一;
- 在一个全新的 ZCode 会话轮次中给出测试 prompt——要么让 description 自然触发技能,要么用
/skill <name> <prompt>强制加载; - 与用户一起看结果:技能触发了吗?输出符合预期吗?哪里跑偏了?
这里还有一个关键的分析视角——同时观察结果与轨迹(trace):如果技能导致模型做了大量"忙活"(busywork),比如反复重读同一批文件、写一次性脚本、原地打转,那通常意味着技能过度规定(over-prescribing)或表述不清。文档的结论是:这是"该删"的信号,而不是"该加更多规则"的信号。这一条与后文 "Keep the prompt lean" 首尾呼应,构成该技能方法论中最重要的反直觉点之一。
五、改进:循环的心脏
"Improving the skill" 是文档自认的"heart of the loop",四条改进思路应完整保留:
- 从反馈中泛化(Generalize from feedback):你和用户是在用少量例子快速迭代,但技能必须对双方都没见过的输入有效。如果某个顽固问题抗拒针对性修改,尝试换一种框架(framing)或隐喻,而不是层层叠加约束。零碎的过拟合规则与压迫性的 MUST 会随时间让技能变差;
- 保持 prompt 精简(Keep the prompt lean):删掉没有贡献的东西。如果模型在忙活上浪费 token,而忙活正是技能鼓励的,直接删掉那条指引再观察;
- 解释 why:现在的模型在有上下文时推理得很好。即便用户反馈简短甚至带着情绪,也要先弄清其真实诉求,再把这种理解转写进指令。重构(reframing)通常优于加码强制;
- 寻找重复劳动(Look for repeated work):如果每次测试都独立写出了同一个辅助脚本、或走了同样的多步流程,就把脚本打包进
scripts/让技能直接指向它——"写一次,而不是让模型每次重新发明"。
随后进入再循环:应用改进 → 重跑测试 prompt → 向用户展示新输出 → 持续到用户满意或进一步修改不再带来收益。
六、更新已安装技能
当目标是更新一个已安装技能而非新建时,文档规定三条规则:
- 保留原
name与目录名:已安装技能叫research-helper,更新版仍然叫research-helper,而不是research-helper-v2; - 只读路径的覆盖策略:如果已安装技能路径只读(例如随官方插件缓存分发),把技能复制到可写的用户位置(如
~/.agents/skills/<name>/),在那里编辑,并让用户级优先级发现覆盖原版; - 同名不同路径是不同安装身份:不同路径下的同名技能作为各自独立的已安装技能存在,路径(path)才是安装身份。
这与 builtin_zcode_skills_message 中内置技能声明"官方插件缓存"路径(~/.zcode/cli/plugins/cache/zcode-plugins-official/...)的做法一致——内置与插件缓存分发物落在该目录,用户侧覆盖则走上文的用户级目录,两条路径各司其职。
七、与 harness 集成的实现视角
把文档声明与源码对齐,可以得到完整的运行时图景:
- 发现层:skills 加载逻辑位于 codex-rs/core-skills,统一以
SKILL.md为文件名常量(SKILLS_FILENAME),解析 frontmatter 元数据并做 fail-open 处理(元数据解析失败不阻断SKILL.md加载,见 loader.rs L467 附近); - 宣告层:session_skills.rs 将运行时组装好的
<skills_instructions>developer 块解析为SessionSkill { name, description, path }列表,各 harness 按自己最接近的形态重新渲染——这正是"元数据常驻上下文"的实现基础; - 触发层:
Skill工具由 HarnessAliasHandler 统一承接,ZCode 分支的handle_zcode_skill负责把 frontmatter 剥离后的正文以<skill_content>标签交付给模型,并附 base directory,使技能内相对路径(如references/aws.md、scripts/)有据可依。
对技能作者的实操含义是:/skill <name> <prompt> 强制加载路径与 description 自然触发路径最终都汇入同一份正文,因此 description 的质量同时决定"自然触发率"与"被宣告时的可读性"——这与文档"write descriptions a little bit pushy"的建议在实现上完全自洽。
八、可复制的最小实践清单
综合文档与源码,落地一个新技能可遵循以下检查清单:
- 用四个标准问题固化意图,优先从会话历史抽取已验证的步骤与纠正;
- 在
.agents/skills/<name>/(个人跨项目)或项目级对应目录创建SKILL.md,name与目录名一致(kebab-case,1–64 字符); - description 写足"做什么 + 何时触发",措辞适度主动以对抗 under-trigger;
- 正文控制在 500 行以内,祈使句 + 解释 why + 字面示例;超过预算的领域细节移入
references/并在正文写明读取时机; - 设计 2–3 个含具体路径、列名、口语化措辞的测试 prompt,新会话中逐条执行;
- 共读结果与 trace,识别 busywork 信号,以删除和重构替代加规则;
- 重复直到收敛;更新旧技能时不改名,只读路径走用户级目录覆盖。
以上流程全部以 zcode_skill_creator.md 为唯一规范来源,并可与 Skill 处理器、内置技能宣告 与 skills 加载器 对照阅读验证。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00