Codex Skill 执行机制:从加载、选择到按需读取

本文按场景解释 Codex 如何“执行” skill。这里先澄清一个容易误解的点:

Codex 并没有一个独立的 skill 虚拟机。
SKILL.md 本身不是被运行的程序,而是模型可读的任务说明、流程约束和资源索引。
真正会被执行的是模型随后调用的普通工具,例如 shell、exec、apply_patch、MCP 工具,或者 skill/scripts/ 下的脚本。

所以“执行 skill”的完整链路其实是:

发现 skill -> 抽取元数据 -> 把可用 skill 列表注入给模型
-> 用户显式选择或模型语义判断需要使用某个 skill
-> 加载 SKILL.md 或由模型按路径读取 SKILL.md
-> 模型按照 SKILL.md 里的流程读取 references、运行 scripts、使用 assets 或调用工具
-> 结果进入普通会话历史和工具调用历史

下面按真实使用场景展开。

场景一:新会话启动,为什么模型只看到 skill 清单

用户进入一个仓库后说:

帮我分析这个项目,看看有哪些内置能力可以用。

Codex 不会一上来把所有 SKILL.md 全部塞进上下文。它先扫描 skill 元数据,然后只把“可用 skill 列表”注入到 developer role 中。这个列表通常长这样:

## Skills
A skill is a set of local instructions to follow that is stored in a `SKILL.md` file.
Below is the list of skills that can be used...

### Available skills
- imagegen: Generate or edit raster images... (file: /home/.../imagegen/SKILL.md)
- openai-docs: Use when the user asks how to build with OpenAI products... (file: /home/.../openai-docs/SKILL.md)

这一步由 Session::build_initial_context 调用 build_available_skills 完成,主要实现位置:

  • codex-rs/core/src/session/mod.rs
  • codex-rs/core-skills/src/manager.rs
  • codex-rs/core-skills/src/loader.rs
  • codex-rs/core-skills/src/render.rs

模型看到的关键提示词

相关提示词 / Tool Description

英文原文:

A skill is a set of local instructions to follow that is stored in a SKILL.md file. Below is the list of skills that can be used. Each entry includes a name, description, and file path so you can open the source for full instructions when using a specific skill.

中文对照:

skill 是一组存放在 SKILL.md 文件里的本地指令。下面是当前会话可用的 skill 列表。每一项都包含名称、描述和文件路径,因此当你需要使用某个具体 skill 时,可以打开对应源码读取完整指令。

这段话的作用是:让模型先获得“可用能力目录”,但不立即消耗上下文加载所有 skill 正文。模型知道每个 skill 的名字、用途和 SKILL.md 路径。

紧接着 Codex 注入更重要的操作规则:

相关提示词 / Tool Description

英文原文:

  • Discovery: The list above is the skills available in this session (name + description + file path). Skill bodies live on disk at the listed paths.
  • Trigger rules: If the user names a skill (with $SkillName or plain text) OR the task clearly matches a skill’s description shown above, you must use that skill for that turn. Multiple mentions mean use them all. Do not carry skills across turns unless re-mentioned.
  • Missing/blocked: If a named skill isn’t in the list or the path can’t be read, say so briefly and continue with the best fallback.
  • How to use a skill (progressive disclosure):
    1. After deciding to use a skill, open its SKILL.md. Read only enough to follow the workflow.
    2. When SKILL.md references relative paths (e.g., scripts/foo.py), resolve them relative to the skill directory listed above first, and only consider other paths if needed.
    3. If SKILL.md points to extra folders such as references/, load only the specific files needed for the request; don’t bulk-load everything.
    4. If scripts/ exist, prefer running or patching them instead of retyping large code blocks.
    5. If assets/ or templates exist, reuse them instead of recreating from scratch.

中文对照:

  • 发现:上面的列表是当前会话可用的 skill,包括名称、描述和文件路径。skill 正文在这些路径上的磁盘文件里。
  • 触发规则:如果用户点名某个 skill,比如 $SkillName 或自然语言点名,或者当前任务明显匹配上面某个 skill 的描述,本轮必须使用该 skill。多个 skill 被提到时都要使用。除非再次提到,否则不要跨 turn 延续 skill。
  • 缺失或受阻:如果被点名的 skill 不在列表里,或者路径无法读取,简短说明后使用最佳降级方案继续。
  • 如何使用 skill,采用渐进式披露:
    1. 决定使用某个 skill 后,打开它的 SKILL.md。只读取足够执行流程的内容。
    2. 如果 SKILL.md 引用了相对路径,例如 scripts/foo.py,优先按 skill 目录解析这些路径。
    3. 如果 SKILL.md 指向 references/ 等额外目录,只加载当前任务需要的具体文件,不要整目录批量加载。
    4. 如果存在 scripts/,优先运行或修改脚本,而不是重新手写大段代码。
    5. 如果存在 assets/ 或模板,复用它们,不要从零重建。

这段话的作用是:把 skill 系统设计成“先目录,后正文,再按需资源”的三层加载机制。模型不是凭空知道某个 skill 的完整流程,而是先看到元数据,再在需要时打开 SKILL.md

Codex 如何找到这些 skill

SkillsManager 会从多个 root 收集 skill:

项目配置目录下的 skills/              常见为 <repo>/.codex/skills/
仓库路径上的 .agents/skills/           从 project root 到 cwd 逐级扫描
用户目录下的 $CODEX_HOME/skills/       兼容旧位置
用户目录下的 $HOME/.agents/skills/     用户安装 skill 的位置
系统缓存 $CODEX_HOME/skills/.system    内置 system skills
管理员配置 /etc/codex/skills           admin-scoped skills
插件声明的 skill roots                 来自 plugin capability

源码里的入口是 skill_rootsskill_roots_with_home_dir。它们按配置层、仓库路径和插件声明汇总 root,然后去重。

Codex 如何扫描 SKILL.md

扫描规则比较保守:

从 skill root 开始递归扫描
跳过以 "." 开头的目录
最大扫描深度 MAX_SCAN_DEPTH = 6
每个 root 最多扫描 MAX_SKILLS_DIRS_PER_ROOT = 2000 个目录
遇到名为 SKILL.md 的文件就尝试解析

parse_skill_file 会读取 SKILL.md 的 YAML frontmatter。最关键字段是:

---
name: scenario-tech-article-writer
description: Write Chinese technical implementation-analysis articles...
metadata:
  short-description: Write scenario-first technical docs
---

namedescription 是模型选择 skill 时最重要的可见信息。description 不能写成普通介绍,它必须说明什么时候应该使用这个 skill,因为它会出现在“Available skills”列表中,成为模型语义判断的依据。

场景二:用户显式选中 $skill,为什么完整 SKILL.md 会自动进入本轮

用户说:

使用 $scenario-tech-article-writer 写一篇文档。

或者 UI / App 把用户点击的 skill chip 作为结构化输入提交:

UserInput::Skill {
  name: "scenario-tech-article-writer",
  path: "/home/.../scenario-tech-article-writer/SKILL.md"
}

这是代码层面的显式注入路径。Codex 会在 run_turn 里调用 collect_explicit_skill_mentions。它能识别:

结构化 UserInput::Skill
$skill-name
[$skill-name](skill://absolute/path/to/SKILL.md)
[$skill-name](/absolute/path/to/SKILL.md)

对于 $skill-name 这种 plain mention,只有当 skill 名称唯一、没有被禁用、也不和 connector slug 冲突时,Codex 才会选中它。路径链接更可靠,因为它可以精确匹配 SKILL.md 路径。

如果用户只是自然语言说“使用 scenario-tech-article-writer 这个 skill”,但没有 $、skill 链接,也没有被 UI 转成 UserInput::Skill,那就不是这条 host 显式注入链路,而是下一节的模型语义选择链路。

显式注入时模型看到什么

collect_explicit_skill_mentions 成功选中 skill 后,build_skill_injections 会读取完整 SKILL.md,并把它包装成一个 user-role contextual fragment:

相关提示词 / Tool Description

英文原文:

<skill>
<name>{skill name}</name>
<path>{path to SKILL.md}</path>
{contents of SKILL.md}
</skill>

中文对照:

<skill>
<name>{skill 名称}</name>
<path>{SKILL.md 路径}</path>
{SKILL.md 的完整内容}
</skill>

这段包装的作用是:把“用户这轮明确选择的 skill 正文”放进模型上下文,让模型不需要再自己读文件。实现位置是 codex-rs/core/src/context/skill_instructions.rs

注意这里的 role 是 user,而“Available skills”列表的 role 是 developer。也就是说:

developer role: 告诉模型有哪些 skill、如何使用 skill。
user role <skill>: 给模型本轮已经选中的 skill 正文。

显式注入发生在用户消息入库之前

run_turn 里的顺序大致是:

读取 turn_skills.outcome
解析用户 input 里的 skill mentions
处理 env_var / MCP skill 依赖
build_skill_injections 读取 SKILL.md
把 <skill> fragment 记录进 conversation items
再进入正常模型采样循环

所以当模型真正开始回答时,它已经能看到被显式选中的 skill 正文。

场景三:用户没写 $skill,模型怎么“自己选择”

用户说:

帮我写一篇场景化技术分析文档,解释 Codex 的 skill 执行机制。

用户没有写 $scenario-tech-article-writer,也没有通过 UI 结构化选中 skill。这时有一个容易混淆的问题:

如果模型发现应该用某个 skill,是不是一定会发起 toolcall 去加载 skill?

答案要分两条链路:

显式选择链路:host 在模型采样前读取 SKILL.md,并把 <skill> 注入上下文。
语义选择链路:模型根据 available skills 判断要用哪个 skill,然后自己用普通工具读取 SKILL.md。

用户没写 $skill 时,通常走第二条。Codex 不会在 Rust 代码里先跑一个语义分类器判断“这句话属于哪个 skill”,也不会在模型采样前自动把某个 SKILL.md 注入进去。真正驱动选择的是 developer prompt 中的 trigger rule:

相关提示词 / Tool Description

英文原文:

If the user names a skill (with $SkillName or plain text) OR the task clearly matches a skill’s description shown above, you must use that skill for that turn.

中文对照:

如果用户点名某个 skill,比如 $SkillName 或自然语言点名,或者当前任务明显匹配上面某个 skill 的描述,本轮必须使用该 skill。

这段话的作用是:把“是否使用 skill”的语义判断交给模型。代码没有写死“技术文档请求 -> scenario-tech-article-writer”。代码只负责把 skill 的 namedescriptionpath 给模型看;模型读到用户任务后,判断任务是否匹配某个描述。

模型一旦判断要用某个 skill,就继续遵守同一段 prompt 的渐进式披露规则:

相关提示词 / Tool Description

英文原文:

After deciding to use a skill, open its SKILL.md. Read only enough to follow the workflow.

中文对照:

决定使用某个 skill 后,打开它的 SKILL.md。只读取足够执行流程的内容。

这段话的作用是:要求模型在语义选择 skill 后,不要只凭列表里的 description 工作,而要读取 skill 正文。也就是说,如果没有 pre-turn <skill> 注入,模型按规则应该发起一次普通 toolcall 来读取 SKILL.md

也就是说,语义匹配路径通常长这样:

host 在 developer role 里注入 Available skills
模型看到 scenario-tech-article-writer 的 name、description、path
模型判断当前任务明显匹配这个 description
模型发送普通工具调用,例如 exec/shell 读取 /home/.../scenario-tech-article-writer/SKILL.md
工具返回 SKILL.md 内容
模型按 SKILL.md 的写作流程继续

这里没有一个特殊的 load_skill 工具。读取文件通常就是普通的文件读取或 shell 命令,例如:

sed -n '1,220p' /home/tlinux/.codex/skills/scenario-tech-article-writer/SKILL.md

所以你在 transcript 里看到的会是一次普通 toolcall,而不是“加载 skill”的专用事件。

那 MCP 依赖安装会不会自动发生

不会因为模型语义判断“我要用某个 skill”就一定自动发生。MCP 依赖安装挂在 pre-turn 的 mentioned_skills 上,而 mentioned_skills 来自 collect_explicit_skill_mentions 对用户输入的解析:

UserInput::Skill / $skill / skill 链接
-> mentioned_skills
-> resolve env_var dependencies
-> maybe_prompt_and_install_mcp_dependencies
-> build_skill_injections
-> 模型开始采样

语义选择路径发生在“模型开始采样之后”:

模型看到 Available skills
模型决定使用某个 skill
模型 toolcall 读取 SKILL.md

这时 pre-turn 依赖安装阶段已经过去了。即使该 skill 的 agents/openai.yaml 声明了 MCP server,语义选择本身也不会回头触发 maybe_prompt_and_install_mcp_dependencies

因此要把三种提示分开看:

<skill> 注入:host 读 SKILL.md 后放进模型上下文,只发生在显式 mentioned skill 上。
普通 toolcall 读取 SKILL.md:模型语义选择 skill 后自己做,使用 shell/exec/文件读取工具。
MCP 依赖安装提示:host 对显式 selected skills 做 pre-turn 检查后弹出,不是模型随口生成的文本。

如果语义选择的 skill 后续需要某个 MCP 工具,模型只能按当前可见工具继续:已经安装并暴露就直接用;工具被延迟加载就按 tool description 使用 tool_search;如果是明确请求安装的 plugin/connector 且 request_plugin_install 可用,再按它的规则请求安装。普通 agents/openai.yaml 里声明的 MCP dependency,不会因为模型读了 SKILL.md 就自动写入配置。

场景四:SKILL.md 被打开后,references、scripts、assets 怎么用

假设 SKILL.md 里写:

For complex examples, read references/examples.md.
If generating the report repeatedly, run scripts/build_report.py.
Use assets/template.md as the output template.

模型不会自动把这些目录都加载进上下文。它会按 prompt 的渐进式披露规则处理。

相关提示词 / Tool Description

英文原文:

If SKILL.md points to extra folders such as references/, load only the specific files needed for the request; don’t bulk-load everything.
If scripts/ exist, prefer running or patching them instead of retyping large code blocks.
If assets/ or templates exist, reuse them instead of recreating from scratch.

中文对照:

如果 SKILL.md 指向 references/ 等额外目录,只加载当前请求需要的具体文件,不要整目录批量加载。
如果存在 scripts/,优先运行或修改脚本,而不是重新手写大段代码。
如果存在 assets/ 或模板,复用它们,不要从零重建。

这段话的作用是:控制 token 成本和执行可靠性。SKILL.md 是入口和导航;references/ 是按需知识;scripts/ 是可执行或可修改的确定性流程;assets/ 是输出资源,通常不需要读入模型上下文。

references 是按需读取,不是自动记忆

references/ 里的内容不会自动进入上下文。模型必须根据 SKILL.md 的导航和当前任务决定读取哪一个文件。

例如:

用户:请按我们公司的 SQL 指标口径写报表。
模型:打开 skill 的 SKILL.md。
SKILL.md:指标定义在 references/metrics.md。
模型:只读取 references/metrics.md,而不是读取整个 references/ 目录。

这就是 skill 的“二级上下文”。它既能让 skill 很强,又避免每次都把大量文档注入。

scripts 是普通工具执行,不是特权执行

如果 skill 里有:

scripts/rotate_pdf.py
scripts/generate_openai_yaml.py

模型运行它们时,本质上是普通 shell/exec 调用:

python3 /path/to/skill/scripts/generate_openai_yaml.py <args>

这条命令仍然受当前 turn 的 sandbox、approval policy、权限配置、网络配置约束。agents/openai.yaml 里的元数据不会给脚本额外提权。测试里也有专门覆盖:skill script execution is governed by the turn sandbox, not a removed skill approval gate。

assets 是输出材料,不是提示词主体

assets/ 常见用途:

图标
模板
字体
前端 boilerplate
示例文件

模型只有在需要复制、修改或引用这些文件时才会使用它们。它们通常不是为了“读进上下文”,而是为了参与最终产物。

场景五:agents/openai.yaml 到底参与了什么

一个 skill 目录可能是:

skill-name/
├── SKILL.md
├── agents/
│   └── openai.yaml
├── references/
├── scripts/
└── assets/

SKILL.md 是模型读的行为说明。agents/openai.yaml 是宿主产品、UI 和 harness 读取的元数据。它不会替代 SKILL.md,也不是 AGENTS.md

相关提示词 / Tool Description

英文原文:

agents/openai.yaml is an extended, product-specific config intended for the machine/harness to read, not the agent. Other product-specific config can also live in the agents/ folder.

中文对照:

agents/openai.yaml 是扩展的、产品特定的配置,设计给机器或 harness 读取,而不是给 agent 直接读取。其他产品特定配置也可以放在 agents/ 文件夹里。

这段话的作用是:明确 agents/ 不是 multi-agent 运行目录,也不是 AGENTS.md 项目规则目录。它是 skill 的产品元数据目录。

一个完整示例:

相关提示词 / Tool Description

英文原文:

interface:
  display_name: "Optional user-facing name"
  short_description: "Optional user-facing description"
  icon_small: "./assets/small-400px.png"
  icon_large: "./assets/large-logo.svg"
  brand_color: "#3B82F6"
  default_prompt: "Optional surrounding prompt to use the skill with"

dependencies:
  tools:
    - type: "mcp"
      value: "github"
      description: "GitHub MCP server"
      transport: "streamable_http"
      url: "https://api.githubcopilot.com/mcp/"

policy:
  allow_implicit_invocation: true

中文对照:

interface:
  display_name: "可选的用户可见名称"
  short_description: "可选的用户可见简短描述"
  icon_small: "./assets/small-400px.png"
  icon_large: "./assets/large-logo.svg"
  brand_color: "#3B82F6"
  default_prompt: "调用该 skill 时可用的默认提示片段"

dependencies:
  tools:
    - type: "mcp"
      value: "github"
      description: "GitHub MCP server"
      transport: "streamable_http"
      url: "https://api.githubcopilot.com/mcp/"

policy:
  allow_implicit_invocation: true

这段 YAML 的作用分三类:

interface: 给 UI、插件列表、skill chip、默认 prompt 使用。
dependencies: 声明 skill 依赖的工具,例如 MCP server 或 env var。
policy: 控制是否允许隐式出现在模型可见的 available skills 列表中。

openai.yaml 解析失败不会阻塞 SKILL.md

load_skill_metadata 会尝试读取 skill_dir/agents/openai.yaml。如果不存在、读失败或 YAML 无效,Codex 会 fail open:忽略这份可选元数据,但不阻止 SKILL.md 被加载。

这和 SKILL.md frontmatter 不同。SKILL.md 缺少 frontmatter、YAML 无效、缺少 namedescription,会导致这个 skill 解析失败。

policy.allow_implicit_invocation 控制“默认出现在列表中”

policy.allow_implicit_invocation: false 的含义是:

这个 skill 默认不进入模型可见的 available skills 列表。
但用户显式通过 $skill 或结构化选择仍然可以使用它。

它适合不希望模型根据描述主动触发的 skill,例如危险、昂贵、内部测试或需要明确用户意图的 workflow。

场景六:skill 依赖 MCP 或环境变量时发生什么

用户说:

用 $openai-docs 帮我查最新 OpenAI API 文档。

openai-docsagents/openai.yaml 可能声明:

dependencies:
  tools:
    - type: "mcp"
      value: "openaiDeveloperDocs"
      description: "OpenAI Developer Docs MCP server"
      transport: "streamable_http"
      url: "https://developers.openai.com/mcp"

当这个 skill 是本轮显式提到的 mentioned_skills 时,run_turn 会先处理依赖,再让模型采样。

MCP 依赖安装

MCP 依赖处理入口是 maybe_prompt_and_install_mcp_dependencies。它会检查:

当前客户端是否 first-party
Feature::SkillMcpDependencyInstall 是否开启
本轮是否有 mentioned_skills
这些 skill 是否声明了 type = "mcp" 的 dependencies.tools
对应 MCP server 是否已经安装

如果缺失,Codex 会发起用户确认:

相关提示词 / Tool Description

英文原文:

The following MCP servers are required by the selected skills but are not installed yet: {server_list}. Install them now?

中文对照:

选中的 skill 需要以下 MCP server,但它们尚未安装:{server_list}。现在安装吗?

这段话的作用是:把 skill 的外部工具依赖变成显式授权步骤。用户选择安装后,Codex 会把缺失 MCP server 写入全局配置,必要时执行 OAuth login,然后刷新 MCP server 列表。

注意,这个提示不是模型在回答里“写出来”的自然语言,也不是模型看到 SKILL.md 后发起的普通 toolcall。它是 host 在模型采样前检查显式 mentioned_skills 后,通过 request_user_input 这类用户确认机制发出的安装询问。

如果用户没有通过 $skill、skill 链接或结构化方式显式选择,而只是模型语义判断要用某个 skill,这条 pre-turn 依赖安装链路不会自动补触发。因为代码里的依赖安装输入是 mentioned_skills,它来自用户输入解析,而不是模型后续的语义判断。

env_var 依赖只保存在当前 session

skill 也可以声明:

dependencies:
  tools:
    - type: "env_var"
      value: "GITHUB_TOKEN"
      description: "GitHub API token with repo scopes"

Feature::SkillEnvVarDependencyPrompt 开启时,Codex 会检查本机环境变量。如果缺失,会通过 request_user_input 向用户请求 secret。代码里的提示说明这类值:

stored in memory for this session only

也就是只存当前 session 的 dependency env,不写入长期配置。

场景七:为什么读 SKILL.md 或运行 scripts 也会被记录为 skill 使用

用户没有写 $skill,但模型根据 available skills 列表自己执行:

sed -n '1,220p' /home/tlinux/.codex/skills/scenario-tech-article-writer/SKILL.md

或者运行:

python3 /home/tlinux/.codex/skills/skill-creator/scripts/generate_openai_yaml.py ...

这时并没有 pre-turn 的 <skill> 注入,但 Codex 仍然可以记录“这个 skill 被隐式使用过”。shell 和 unified exec handler 会调用 maybe_emit_implicit_skill_invocation,它再调用 detect_implicit_skill_invocation_for_command

检测规则很具体:

如果命令是 cat/sed/head/tail/less/more/bat/awk 等读取器,
并且读取的是某个 SKILL.md,就认为该 skill 被隐式调用。

如果命令是 python/python3/bash/zsh/sh/node/deno/ruby/perl/pwsh 等 runner,
并且执行的是某个 skill/scripts/ 下的 .py/.sh/.js/.ts/.rb/.pl/.ps1,
也认为该 skill 被隐式调用。

这条链路主要用于 telemetry 和 analytics:

记录 skill name
记录 scope: repo/user/system/admin
记录 path
记录 invocation_type = Implicit
避免同一 turn 重复记录

它不会把 SKILL.md 自动注入给模型,也不会改变权限。它只是识别“模型已经通过文件读取或脚本执行实际使用了这个 skill”。

场景八:skill 如何被禁用、裁剪和治理

当 skill 很多时,Codex 需要避免 available skills 列表撑爆上下文。

元数据预算

build_available_skills 使用一个 skill metadata budget:

如果模型有 context_window,默认用 2% 作为 skill metadata budget。
否则使用 8000 characters 作为 fallback。

如果所有 skill 的完整描述放不下,Codex 会先保留每个 skill 的最小行:

- skill-name: (file: /path/to/SKILL.md)

然后在剩余预算中按字符分配 description。如果连最小行都放不下,就只能省略部分 skill,并向用户发 warning。

相关提示词 / Tool Description

英文原文:

Skill descriptions were shortened to fit the 2% skills context budget. Codex can still see every skill, but some descriptions are shorter. Disable unused skills or plugins to leave more room for the rest.

中文对照:

为了适配 2% 的 skill 上下文预算,skill 描述被缩短了。Codex 仍能看到每个 skill,但部分描述更短。可以禁用不用的 skill 或 plugin,为其他内容留下更多空间。

这段话的作用是:当描述被裁剪时提醒用户。裁剪不会改变磁盘上的 SKILL.md,只影响本轮模型看到的 available skills 列表。

如果最小信息也放不下,另一条 warning 是:

相关提示词 / Tool Description

英文原文:

Exceeded skills context budget. All skill descriptions were removed and {n} additional skills were not included in the model-visible skills list.

中文对照:

超出了 skill 上下文预算。所有 skill 描述都被移除,并且还有 {n} 个额外 skill 没有进入模型可见列表。

这段话的作用是:明确告诉用户有些 skill 对模型不可见,因此模型无法主动选择它们。用户仍可以通过显式路径或 $skill 使用没有被配置禁用的 skill。

路径别名

如果 skill 路径很长,Codex 会尝试构造 skill root alias:

### Skill roots
- `r0` = `/very/long/path/to/skills/root`

### Available skills
- demo-skill: ... (file: r0/demo/SKILL.md)

这不是另一个存储系统,只是为了节省 prompt token。

禁用规则

用户或 session config 可以通过 skills.config 按 name 或 path 禁用 skill。resolve_disabled_skill_paths 会把这些规则解析成 disabled_paths

被禁用的 skill:

不会进入 available skills 列表
不会被 `$skill-name` plain mention 选中
不会进入隐式调用索引

如果只是 policy.allow_implicit_invocation: false,它不会出现在 available skills 列表,但仍可以被显式选择。

cache 只减少扫描成本,不减少 prompt 成本

SkillsManager 有两个 cache:

cache_by_config: 按 skill roots + config rules 缓存结果
cache_by_cwd: 按 cwd 缓存结果

这些 cache 避免每个 turn 都重复扫描磁盘。它们不等于“把 skill 压缩进长期记忆”,也不减少模型上下文 token。真正控制 token 的是 available skills 的 metadata budget,以及 SKILL.md 的按需加载策略。

一条完整链路:从用户请求到 skill 生效

以当前请求为例:

用户:使用 scenario-tech-article-writer skill 写一篇文档,详细介绍 Codex 如何执行 skill。

完整链路是:

1. 会话构造初始上下文
   Codex 扫描各个 skills root,解析 SKILL.md frontmatter 和 agents/openai.yaml。

2. developer prompt 注入 available skills
   模型看到 scenario-tech-article-writer 的 name、description、file path。

3. 用户点名 skill
   如果输入被识别为结构化 skill 或 $scenario-tech-article-writer,host 会预先读取完整 SKILL.md 并注入 <skill> fragment。
   如果只是自然语言点名,模型根据 trigger rule 自己打开 SKILL.md。

4. 模型读取 SKILL.md
   它只读取足够执行工作流的内容;如果 SKILL.md 指向 references/,再读取具体需要的文件。

5. 模型执行普通工具
   写文档时可能用 shell 查看源码,用 apply_patch 创建文件,用 rg 搜索引用。
   如果 skill 要求运行脚本,脚本通过普通 shell/exec 执行。

6. 结果进入会话历史
   工具调用、文件修改、模型回答都按普通 turn 流程记录。

7. 如果上下文过长
   这不是 skill 系统单独处理,而是交给 Codex 的会话压缩、上下文管理和 rollout 持久化机制处理。

管理视角:设计优点和边界

Codex 的 skill 机制有几个明显取舍。

第一,它把“选择”交给模型,把“发现和注入”交给 host。host 只负责给出列表、解析显式 mentions、读取被显式选择的 SKILL.md;语义匹配主要靠模型读 description 判断。这让 skill 扩展很灵活,但也要求 description 写得非常准确。

第二,它用渐进式披露控制上下文。常驻 prompt 只放元数据,正文按需读取,references 更按需读取。这个设计能让 skill 数量增长,但不意味着可以无限增长。skill 太多时,available list 会裁剪;SKILL.md 太长时,读入正文仍会占用上下文。

第三,它没有给 skill 脚本特殊权限。脚本只是普通工具调用,仍受 turn sandbox 和 approval 控制。这避免了“安装一个 skill 就扩大权限”的风险。

第四,agents/openai.yaml 是 host 元数据,不是模型主提示词。它适合放 UI、默认 prompt、依赖、策略;真正改变模型行为的仍然是 SKILL.md body 和 available skills developer prompt。

第五,隐式调用统计不是自动加载。模型读取 SKILL.md 或运行 scripts/ 时,Codex 可以记录一次 implicit invocation;但这个记录不会反向把 skill 正文塞进上下文。

如果要进一步增强这个系统,常见方向是:

对 skill description 做检索排序,而不是只靠全量列表预算。
对大型 references 做 top-k retrieval,而不是让模型手动 rg。
对 skill 使用效果做质量评估,自动发现 stale skill。
对 dependencies 做更统一的生命周期管理。
对自然语言点名 skill 的 host-side 解析更强,减少模型手动打开文件的步骤。

但当前实现的核心思想已经很清楚:Codex skill 不是一个插件运行时,而是一个受 prompt 驱动、host 辅助加载、工具实际执行的分层上下文系统。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐