Yoda
参考Agent 设计指南扩展

Skills

SKILL.md 已成跨厂商标准:CC 与 Codex 都读 ~/.agents/skills 或同构目录,分歧在触发方式(CC 编译成 /命令 + 模型自触发,Codex 用 $mention + 隐式调用探测)与 frontmatter 丰富度

Skills

结论

Skills 是继 hooks 之后第二个跨厂商收敛点,而且收敛到了文件格式层面:两家都用 skill-name/SKILL.md 目录格式,Codex 甚至直接扫描 ~/.agents/skills 和项目内 .agents/skills(agentskills.io 开放标准的共享目录)。分歧在运行模型:CC 把 skill 编译成 Command 对象(与 slash command 同一类型),用户可 /skill-name 调用、模型可自动触发,frontmatter 字段多达 17 个(model/effort/agent/context:fork/paths/hooks…);Codex 把 skill 当上下文注入,用 $skill-name mention 显式引用,注入为 <skill> 用户消息片段,并独有"隐式调用探测"——模型 bash 跑了某 skill 的 scripts/ 下脚本也算调用了该 skill。harness 校验器以 agentskills.io 的 name+description 必填为底线,再按 runtime 叠加各自字段规则。

研究问题

  • skill 文件格式与 frontmatter 各家差异(必填项、扩展字段)?
  • 扫描目录与 scope 优先级?
  • 触发机制:用户调用、模型自动触发、隐式调用各如何实现?
  • harness 内置校验器应覆盖哪些规则?

各 Agent 设计与实现

Claude Code

格式与标准。 [一手文档] claude-code-docs/docs/skills.md:19:CC skills 遵循 Agent Skills 开放标准(agentskills.io),CC 在标准之上扩展了 invocation control、subagent 执行、动态上下文注入。/skills/ 目录只接受 skill-name/SKILL.md 目录格式,单文件 .md 不支持([一手源码] src_2026-03-31/skills/loadSkillsDir.ts:426);legacy /commands/ 目录两种格式都收(loadSkillsDir.ts:632-634)。

扫描目录与 scope。 [一手源码] loadSkillsDir.ts:638-714:managed(<managed>/.claude/skills,可用 CLAUDE_CODE_DISABLE_POLICY_SKILLS 关)、user(~/.claude/skills)、project(.claude/skills,从 cwd 向上走到 home)、--add-dir 附加目录、legacy commands 目录,五路并行加载后按文件 identity(realpath)去重,先到先得loadSkillsDir.ts:728-763)。同名时 enterprise > personal > project,plugin skill 用 plugin-name:skill-name 命名空间永不冲突([一手文档] skills.md:110)。

Frontmatter:17 个字段。 [一手源码] loadSkillsDir.ts:185-264 parseSkillFrontmatterFieldsname(displayName) / description / allowed-tools / argument-hint / arguments / when_to_use / version / model / effort / disable-model-invocation / user-invocable(默认 true) / hooks(skill 可携带会话级 hooks!)/ context: fork / agent(指定在哪个 subagent 里跑)/ paths(glob 命中才激活的条件 skill)/ shelldescription 缺省时从正文抽取。

权限面。 [一手文档] docs/skills.md:531-534:skill 可被 permissions 规则逐个允许/拒绝:

{ "permissions": { "allow": ["Skill(commit)"], "deny": ["Skill(deploy-*)"] } }

这是 CC 侧"禁用单个 skill"的实际等价物——不是加载期开关(Codex 的 [skills.config] 才是),而是调用期权限门。两种范式对 harness 的含义不同:CC 的 skill 仍占 frontmatter 索引 token,Codex 被禁用的 skill 完全不进上下文。

编译为 Command。 [一手源码] loadSkillsDir.ts:316-343 createSkillCommand 返回 type:'prompt'Command——skill 和 slash command 在 CC 内部是同一个类型。运行时替换 ${CLAUDE_SKILL_DIR}${CLAUDE_SESSION_ID}$ARGUMENTS,并执行正文里的 !`cmd` bash 注入;MCP 来源的 skill 被禁止执行 bash 注入(远程不可信,loadSkillsDir.ts:371-374)。

触发:用户 /skill-name;模型经 SkillTool 自动触发(disable-model-invocation: true 可关);paths 命中文件时自动激活——带 paths 的"条件 skill"与无条件 skill 分池管理,激活后进入 activatedConditionalSkillNames 集合(loadSkillsDir.ts:771-779)。

渐进披露的成本模型。 [一手源码] loadSkillsDir.ts:97-104:skill 的常驻 token 成本只按 frontmatter(name+description+whenToUse)估算,注释原文 "full content is only loaded on invocation"。这是 skills 能大规模铺开而不爆上下文的关键设计,也是 harness 做"skill token 预算面板"时应采用的口径。

Codex CLI

格式。 [一手源码] codex-rs/core-skills/src/loader.rs:107SKILLS_FILENAME = "SKILL.md",同样目录格式。元数据模型(core-skills/src/model.rs:14):name / description / short_description / interface / dependencies / policy / scope / plugin_id。其中 CC 没有的:

  • interface:display_name、大小图标、brand_color、default_prompt——为 GUI 门面准备(model.rs:60-67);
  • dependencies.tools:声明 skill 依赖的工具(type/value/transport/command/url,可声明依赖某 MCP server,model.rs:69-82);
  • policyallow_implicit_invocationproducts 产品门控(model.rs:51-57)。

扫描目录与 scope。 [一手源码] loader.rs:290-360 + protocol.rs:3394 SkillScope { User, Repo, System, Admin }

  • Repo:各 .codex/ 配置层下的 skills/,以及 cwd 到项目根之间每一级的 .agents/skillsloader.rs:363-384);
  • User:$CODEX_HOME/skills(已标记 deprecated,向后兼容)+ ~/.agents/skills(注释原文 "user-installed skills");
  • System:$CODEX_HOME/skills/.system(内嵌系统 skill 缓存);
  • Admin:/etc/codex/skills。 排序 Repo(0) < User(1) < System(2) < Admin(3)(loader.rs:214-220)。

开关。 [一手源码] config/src/skills_config.rs[skills] 支持 include_instructions(是否注入自动 skills 说明块)、bundled.enabled,以及按 pathname 选择器的逐条 enabled 开关——Codex 可以禁用单个 skill,CC 侧未见等价配置

自动说明块与渲染。 [一手源码] core-skills/src/system.rs/render.rs 负责把可用 skill 清单渲染进自动 instructions 块([skills] include_instructions 可关),mention_counts.rs 统计 mention 频次喂遥测;远程 skill 有独立加载路径(remote.rs),skill 正文经 ExecutorFileSystem 抽象读取——支持从远端执行环境的文件系统读 skill(model.rs:150-157),与 MCP 章的 environment_id 远端能力同构。

触发:mention + 隐式探测。 [一手源码] mention 符号是 $utils/plugins/src/mention_syntax.rs:4 TOOL_MENTION_SIGIL = '$')。被提及的 skill 正文以 <skill><name>…</name><path>…</path>…</skill> 用户消息片段注入(core-skills/src/skill_instructions.rs:31-40)。独有机制:detect_implicit_skill_invocation_for_commandinvocation_utils.rs:29)——拦截 bash 命令,若模型在跑某 skill 的 scripts/ 目录下脚本或在读 SKILL.md 本体,就记账为该 skill 的隐式调用(识别 python/bash/node 等 10 种 runner + 7 种脚本后缀)。

差异矩阵

维度Claude CodeCodex CLI
文件格式skill-name/SKILL.md(agentskills.io 标准)同(SKILLS_FILENAME = "SKILL.md"
共享目录 .agents/skills不读 [推断](源码扫描列表中无)读:~/.agents/skills + 项目内逐级 .agents/skills
Scopemanaged/user/project/--add-dir/plugin/bundled/mcpAdmin/System/User/Repo + plugin
Frontmatter 扩展17 字段:model/effort/agent/context:fork/paths/hooks…interface(图标/品牌色)/dependencies(工具依赖)/policy
用户调用/skill-name(skill 即 Command)$skill-name mention
模型自动触发SkillTool;disable-model-invocation 可关自动 instructions 块 + allow_implicit_invocation
隐式调用探测有:跑 scripts/ 脚本或读 SKILL.md 即记账
禁用单个 skill仅 permissions 规则(Skill(name))[一手文档][[skills.config]] name/path + enabled=false
正文 bash 注入!`cmd`(MCP skill 禁用)无(skill 是纯上下文注入)
携带 hooks可(frontmatter hooks不可(元数据无此字段)
常驻 token 成本仅 frontmatter 索引,正文按需载入自动 instructions 块(可整体关闭)
远端文件系统读取不支持 [推断]支持(ExecutorFileSystem 抽象)

最小复现

# 双 runtime 共享一个 skill(验证 .agents/skills 收敛)
mkdir -p ~/.agents/skills/demo && cat > ~/.agents/skills/demo/SKILL.md <<'EOF'
---
name: demo
description: say hello politely
---
Always greet in French.
EOF
codex    # 输入 "$demo bonjour?" → skill 正文应注入(loader.rs:323 证明该目录被扫)
claude   # /demo 不存在——CC 不扫 ~/.agents/skills,需复制到 ~/.claude/skills/(未实测,基于 loadSkillsDir.ts 目录清单)

Harness 接入建议(Yoda 实践)

Yoda 的 harness-spec.ts 已声明 claude: ['.claude/skills']codex: ['.agents/skills', '.codex/skills'],方向正确。建议:

  1. 检测补全:Codex 侧补 ~/.agents/skills(用户级)与 $CODEX_HOME/skills(deprecated 但仍生效);CC 侧补 managed 目录与 legacy .claude/commands(它们也是 skill)。注意 Codex 的 .agents/skills 是 cwd→项目根逐级扫描,单层检测会漏。
  2. 校验器分层:L1 通用(agentskills.io 底线):目录名/SKILL.md 存在、frontmatter 可解析、name+description 非空;L2 per-runtime:CC 校验 17 字段类型(重点 paths glob、agent 引用存在性、allowed-tools 工具名);Codex 校验 dependencies.tools 引用的 MCP server 是否在 config 中、interface 图标路径存在。
  3. 触发方式要在 UI 上区分:同一个 skill 在 CC 是 /demo、在 Codex 是 $demo,harness 的"运行 skill"按钮要按目标 runtime 生成正确的调用语法。
  4. 调试:CC 看 skill 是否被 dedup 掉(同 realpath 先到先得);Codex 看 [skills.config] 是否禁用、以及 SkillLoadOutcome.errors(loader 失败不是静默的,有结构化错误可展示)。

失效条件

  • CC 开始扫描 .agents/skills(与 Codex 完全收敛,"共享目录"差异行失效)
  • agentskills.io 规范字段变更(本章 L1 校验底线基于 name+description 必填)
  • Codex $ mention 语法或 <skill> 注入格式变更(mention_syntax.rs / skill_instructions.rs
  • CC skill frontmatter 字段增删(parseSkillFrontmatterFields 返回类型变化)

参考资料

  • CC 源码:src_2026-03-31/skills/loadSkillsDir.tsskills/bundledSkills.tstools/SkillTool/SkillTool.ts
  • Codex 源码:codex/codex-rs/core-skills/src/{loader.rs,model.rs,injection.rs,skill_instructions.rs,invocation_utils.rs}config/src/skills_config.rsutils/plugins/src/mention_syntax.rs
  • 文档:claude-code-docs/docs/skills.mdcodex/docs/skills.md(指向 https://developers.openai.com/codex/skills );https://agentskills.io
  • 未确认(UNCONFIRMED):agentskills.io 规范移交 Linux Foundation AAIF 一事在本地源码与文档中无佐证,引用前需另行核实
  • Yoda:yoda/src/renderer/features/projects/components/harness-view/harness-spec.ts

On this page