主题
Codex CLI Skills 深度解析:加载规则与执行原理
适用版本:Codex CLI (Rust 版本, 2025.05+) 开放标准:Agent Skills Standard官方文档:developers.openai.com/codex/skills
一、Skills 概述
Skills 是 Codex CLI 的模块化能力扩展系统,允许用户通过自包含的文件夹为 Codex 注入专业知识、工作流程和工具集成。可以将 Skills 理解为 Agent 的"领域入职手册"——它将 Codex 从通用助手转化为特定领域的专业智能体。
1.1 Skills 能提供什么
| 能力类型 | 说明 | 示例 |
|---|---|---|
| 专业工作流 | 特定领域的多步骤操作流程 | CI/CD 部署流程、代码审查清单 |
| 工具集成 | 特定文件格式或 API 的操作指令 | PDF 编辑、BigQuery 查询 |
| 领域知识 | 公司特定的知识、Schema、业务逻辑 | 内部 API 文档、数据库 Schema |
| 捆绑资源 | 脚本、参考文档和模板资产 | 验证脚本、配置模板 |
1.2 Skills vs AGENTS.md vs MCP
| 维度 | Skills | AGENTS.md | MCP |
|---|---|---|---|
| 定位 | 可复用的专业工作流 | 持久性项目指令 | 外部工具连接 |
| 加载方式 | 按需渐进式加载 | 会话启动时全量加载 | 工具注册到可用列表 |
| 作用域 | 跨项目/项目级/目录级 | 项目级/目录级 | 会话级 |
| 格式 | SKILL.md + 脚本/资源 | 纯 Markdown | JSON-RPC 协议 |
| 复用性 | 高(可打包为 Plugin 分发) | 中(随仓库版本控制) | 高(标准协议) |
二、Skill 目录结构
my-skill/
├── SKILL.md # [必需] 核心指令 + 元数据
│ ├── YAML frontmatter # ├── name: (必需)
│ │ # └── description: (必需)
│ └── Markdown body # └── 操作指令和工作流
│
├── agents/ # [推荐] 可选元数据
│ └── openai.yaml # UI 元数据、调用策略、依赖声明
│
└── Bundled Resources/ # [可选] 捆绑资源
├── scripts/ # 可执行脚本 (Python/Bash)
├── references/ # 按需加载的参考文档
└── assets/ # 输出用文件 (模板、图标)2.1 SKILL.md 文件(必需)
SKILL.md 是 Skill 的核心文件,由两部分组成:
markdown
---
name: pdf-editor
description: Edit and manipulate PDF files. Use when the user needs to rotate,
merge, extract text, or perform other PDF operations.
---
# PDF Editor
## Workflow
1. 检查用户的 PDF 操作需求
2. 使用 scripts/rotate_pdf.py 进行旋转操作
3. 使用 scripts/merge_pdfs.py 进行合并操作
## Constraints
- 单次最多处理 50 页
- 不支持加密的 PDF关键要点:
- frontmatter (YAML):
name和description是必需字段,Codex 通过它们判断何时使用该 Skill - body (Markdown):只有 Skill 被触发后才加载到上下文中
description是主要触发机制——需要清晰描述该 Skill 做什么以及何时应该触发
2.2 agents/openai.yaml(可选)
yaml
interface:
display_name: "PDF Editor"
short_description: "PDF 文件编辑和处理"
icon_small: "./assets/small-logo.svg"
icon_large: "./assets/large-logo.png"
brand_color: "#3B82F6"
default_prompt: "帮我处理这个 PDF 文件"
policy:
allow_implicit_invocation: false # 关闭隐式触发,只能显式 $pdf-editor 调用
dependencies:
tools:
- type: "mcp"
value: "openaiDeveloperDocs"
description: "OpenAI Docs MCP server"
transport: "streamable_http"
url: "https://developers.openai.com/mcp"2.3 捆绑资源
| 资源类型 | 目录 | 加载时机 | 特点 |
|---|---|---|---|
| scripts/ | 可执行代码 | 按需执行 | Token 高效,可不读入上下文直接执行 |
| references/ | 参考文档 | 按需读取 | 保持 SKILL.md 精简 |
| assets/ | 模板/图片 | 使用时加载 | 不加载到上下文中 |
三、渐进式加载系统(Progressive Disclosure)—— 核心机制
这是 Codex Skills 最核心的设计,也是它能够大规模扩展的关键。渐进式加载使用三级信息披露,确保上下文窗口不被过度占用。
3.1 三级加载模型
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Level 1: 元数据(Metadata) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 加载时机: 会话启动时 —— 始终在上下文中 │ │
│ │ 内容: name + description (~100 tokens/skill) │ │
│ │ 作用: 让 Codex 判断何时应该使用该 Skill │ │
│ │ 预算: 模型上下文窗口的 ~2% 或 8,000 字符上限 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ▼ Skill 被触发时 │
│ │
│ Level 2: 完整指令(Full Instructions) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 加载时机: Skill 触发后 │ │
│ │ 内容: SKILL.md body(<5,000 words / <6,500 tokens) │ │
│ │ 作用: 提供完整的工作流程和操作指令 │ │
│ │ 限制: 建议保持在 500 行以内 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ▼ 任务需要时 │
│ │
│ Level 3: 深层资源(Deep Resources) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 加载时机: 按需加载 │ │
│ │ 内容: scripts/ + references/ + assets/ │ │
│ │ 作用: 提供详细文档、可执行脚本、模板资产 │ │
│ │ 限制: 无大小限制,可捆绑的知识量实际上不受限 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘3.2 为什么渐进式加载至关重要
问题:如果安装了 100 个 Skill,每个 Skill 的完整指令有 3,000 tokens,那么总共需要 300,000 tokens —— 直接超出大多数模型的上下文窗口。
解决方案:Level 1 只加载元数据,每个 Skill 约 100 tokens。100 个 Skill 仅占用 ~10,000 tokens,远低于上下文窗口限制。
传统方案(全量加载):
100 skills × 3,000 tokens = 300,000 tokens ← 溢出!
渐进式加载:
Level 1: 100 skills × 100 tokens = 10,000 tokens ← 始终加载
Level 2: 1-2 skills × 3,000 tokens = 6,000 tokens ← 按需加载
Level 3: 按需读取具体文件 ← 极度节省
─────────────────────────────────────────────
总计: ~16,000 tokens ← 仅占上下文的 8%3.3 Level 1 的预算管理
Codex 对 Level 1 的元数据列表有严格的预算控制:
元数据列表预算 = min(模型上下文窗口 × 2%, 8,000 字符)
当 Skills 数量过多时的退化策略:
① 首先:截短 description(保留关键词和触发词)
② 然后:如果仍超出预算,从列表中省略部分 Skills
③ 最后:显示警告告知用户部分 Skills 被省略
重要:预算限制仅适用于初始元数据列表。
当 Codex 选择了一个 Skill 后,它仍会读取该 Skill 的完整 SKILL.md。这就是为什么 description 的写法如此重要:当空间紧张时,Codex 会截短 description。应该将关键用例和触发词放在描述的开头,确保即使被截短也能正确匹配。
四、Skill 发现与扫描规则
4.1 六级作用域
Codex 在启动时从以下位置扫描 Skills,按作用域从窄到宽排列:
扫描顺序(由近及远):
┌────────────────────────────────────────────────────────────────────┐
│ 作用域 路径 用途 │
├────────────────────────────────────────────────────────────────────┤
│ REPO (CWD) $CWD/.agents/skills 当前目录特有的 Skills │
│ (如微服务/模块级) │
│ │
│ REPO (父级) $CWD/../.agents/skills 父目录共享的 Skills │
│ ...一直扫描到 Git 仓库根目录 (跨子目录共享) │
│ │
│ REPO (根) $REPO_ROOT/.agents/skills 仓库根目录的 Skills │
│ (全仓库通用) │
│ │
│ USER $HOME/.agents/skills 用户个人的全局 Skills │
│ (跨所有项目) │
│ │
│ ADMIN /etc/codex/skills 机器/容器级 Skills │
│ (管理员预设) │
│ │
│ SYSTEM Codex 内建 OpenAI 随 Codex 分发 │
│ (skill-creator 等) │
└────────────────────────────────────────────────────────────────────┘4.2 扫描算法
scan_skills():
skills = []
# ① 仓库级:从 CWD 向上扫描到 Git Root
current = $CWD
while current != $REPO_ROOT.parent:
if exists(current/.agents/skills/):
for each folder in current/.agents/skills/:
if exists(folder/SKILL.md):
skill = parse_frontmatter(folder/SKILL.md)
skill.scope = "REPO"
skills.append(skill)
current = current.parent
# ② 用户级
if exists($HOME/.agents/skills/):
for each folder in $HOME/.agents/skills/:
skills.append(...) # scope = "USER"
# ③ 管理员级
if exists(/etc/codex/skills/):
for each folder in /etc/codex/skills/:
skills.append(...) # scope = "ADMIN"
# ④ 系统内建
skills.append(system_skills) # scope = "SYSTEM"
# ⑤ 应用 skills.config 过滤(enabled/disabled)
skills = apply_config_overrides(skills)
# ⑥ 构建元数据列表(受 2% 预算限制)
metadata_list = build_metadata_list(skills, budget=context_window * 0.02)
return skills, metadata_list关键规则:
- 同名不合并:如果两个不同位置的 Skill 有相同的
name,Codex 不会合并它们,两者都会出现在选择器中 - 支持符号链接:Codex 会跟随 symlink 目标扫描
- 自动检测变化:修改 Skill 文件后 Codex 自动检测更新(如未生效则需重启)
4.3 通过配置启用/禁用 Skills
在 ~/.codex/config.toml 中控制:
toml
# 禁用特定 Skill(不删除文件)
[[skills.config]]
path = "/path/to/skill/SKILL.md"
enabled = false
# 可以有多个条目
[[skills.config]]
path = "/path/to/another-skill/SKILL.md"
enabled = false修改后需重启 Codex 生效。
五、触发与执行原理
5.1 两种触发方式
┌─────────────────────────────────────────────────────────────────┐
│ Skill 触发机制 │
│ │
│ ┌───────────────────────────────┐ │
│ │ 方式一:显式调用 │ │
│ │ │ │
│ │ • /skills 命令打开选择器 │ │
│ │ • $ 前缀直接引用 │ │
│ │ 例: $pdf-editor │ │
│ │ • /use skill-name 手动加载 │ │
│ │ │ │
│ │ → 一定会加载该 Skill │ │
│ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────┐ │
│ │ 方式二:隐式调用 │ │
│ │ │ │
│ │ Codex 自主判断当前任务是否 │ │
│ │ 匹配某个 Skill 的 description │ │
│ │ │ │
│ │ → 可通过 allow_implicit_ │ │
│ │ invocation: false 关闭 │ │
│ └───────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘5.2 路由决策机制(核心)
Codex 不使用任何算法路由,没有嵌入向量、分类器、正则匹配或 ML 意图检测。路由完全由 LLM 的前向传播决定。
路由实现原理:
① 启动时:扫描所有 Skills,提取 name + description
② 构建提示:将所有 Skill 元数据聚合为一个工具描述
注入到 Agent 的系统提示中
③ 用户请求到达 → LLM 评估请求 vs 所有 Skill 描述
④ LLM 决策:
├── 匹配到 Skill → 加载该 Skill 的完整 SKILL.md
└── 无匹配 → 使用通用能力处理具体流程图:
用户输入: "帮我把这个 quarterly-report.docx 的格式修复一下"
│
▼
┌─────────────────────────────────────────────┐
│ LLM 评估(在 Transformer 前向传播中完成) │
│ │
│ 系统提示中的 Skill 列表: │
│ │
│ $pdf-editor: "Edit PDF files..." │ ← 不匹配 (.docx)
│ $docx-editor: "Manipulate Word docs, │ ← 强匹配!
│ formatting, templates..." │
│ $xlsx-editor: "Work with Excel..." │ ← 不匹配
│ $bigquery: "Query company database..." │ ← 不匹配
│ │
│ 决策: 使用 $docx-editor │
└──────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 加载 Level 2: 读取 docx-editor/SKILL.md │
│ 完整指令进入上下文窗口 │
└──────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ 执行: 按 SKILL.md 中的工作流操作 │
│ 可能调用 Level 3 的脚本或参考文档 │
└─────────────────────────────────────────────┘5.3 LLM 路由的特性与注意事项
由于路由完全由 LLM 完成,存在以下特性:
| 特性 | 说明 | 应对策略 |
|---|---|---|
| 容易欠触发 | 简单任务(如"读取 PDF")可能不触发 Skill,因为 LLM 认为自己能直接处理 | 在 description 中明确写出触发场景 |
| 复杂任务更可靠 | 多步骤、专业领域任务更容易匹配 | Skill 更适合复杂工作流 |
| description 是唯一线索 | LLM 仅通过 description 判断 | 前置关键词,清晰定义边界 |
| 截短后可能失效 | 当 Skill 数量多时 description 被截短 | 将关键触发词放在开头 |
5.4 完整执行流程
┌─────────────────────────────────────────────────────────────────────┐
│ Skill 完整生命周期 │
│ │
│ Phase 1: 发现 (Discovery) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. Codex 启动 │ │
│ │ 2. 扫描六级作用域中的所有 .agents/skills/ 目录 │ │
│ │ 3. 读取每个 SKILL.md 的 YAML frontmatter │ │
│ │ (只读 name + description,不读 body) │ │
│ │ 4. 应用 skills.config 过滤 (enabled/disabled) │ │
│ │ 5. 构建元数据列表(受 2% 预算限制) │ │
│ │ 6. 注入到系统提示中 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Phase 2: 匹配 (Matching) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 7. 用户发送请求 │ │
│ │ 8. LLM 评估请求 vs 所有 Skill 的 description │ │
│ │ 9. 决策: │ │
│ │ ├── 显式调用 ($skill-name) → 直接触发 │ │
│ │ ├── 隐式匹配 → LLM 选择最佳 Skill │ │
│ │ └── 无匹配 → 使用通用能力 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Phase 3: 加载 (Loading) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 10. 读取选中 Skill 的完整 SKILL.md body (Level 2) │ │
│ │ 11. 将完整指令注入当前上下文 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Phase 4: 执行 (Execution) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 12. 按 SKILL.md 中的工作流步骤执行 │ │
│ │ 13. 如需要,调用 scripts/ 中的脚本 (Level 3) │ │
│ │ 14. 如需要,读取 references/ 中的文档 (Level 3) │ │
│ │ 15. 如需要,使用 assets/ 中的资源 (Level 3) │ │
│ │ 16. 产出结果 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘六、内建系统 Skills
Codex 自带两个系统级 Skill,启动时自动安装到 $CODEX_HOME/skills/.system/:
| 系统 Skill | 功能 | 触发方式 |
|---|---|---|
| skill-creator | 引导创建新 Skill | $skill-creator |
| skill-installer | 从 GitHub 安装 Skills | $skill-installer |
系统 Skills 随 Codex 更新自动升级。
6.1 使用 skill-creator 创建 Skill
bash
# 在 Codex 中输入
$skill-creator
# skill-creator 的工作流:
# 1. 了解 Skill 需求 — 收集具体的使用示例
# 2. 规划可复用内容 — 识别需要的脚本、参考文档和资产
# 3. 初始化 Skill — 运行 init_skill.py 创建目录结构
# 4. 实现 Skill — 编写资源和 SKILL.md
# 5. 验证 Skill — 运行 quick_validate.py 检查问题
# 6. 迭代改进 — 在实际任务上测试并根据反馈优化6.2 使用 skill-installer 安装 Skill
bash
# 安装预设 Skill
$skill-installer linear
# 从 GitHub 仓库安装
$skill-installer github.com/owner/repo/path/to/skill七、Skills 与子智能体(Subagents)的配合
7.1 子智能体可配置 Skill 范围
自定义子智能体可以通过 [[skills.config]] 控制其可用的 Skill 集合:
toml
# .codex/agents/ui-fixer.toml
name = "ui_fixer"
description = "Implementation-focused agent for small, targeted fixes."
model = "gpt-5.3-codex-spark"
sandbox_mode = "workspace-write"
developer_instructions = """
Own the fix once the issue is reproduced.
Make the smallest defensible change.
"""
# 为该子智能体禁用特定 Skill
[[skills.config]]
path = "/Users/me/.agents/skills/docs-editor/SKILL.md"
enabled = false7.2 分工示例
主智能体
├── Worker(带 pdf-editor Skill) → 处理 PDF 文件
├── Explorer(带 bigquery Skill) → 查询分析数据库
└── Reviewer(禁用 写入类 Skills) → 只读代码审查注意:截至当前版本,子智能体级别的
[[skills.config]]存在已知 Bug(#14161),per-agent 的 Skill 启用/禁用可能未被正确执行。
八、Skills 与 Plugins 的关系
┌────────────────────────────────────────────────────────────┐
│ │
│ Skills = 创作格式(Authoring Format) │
│ "设计工作流本身" │
│ │
│ Plugins = 分发单元(Distribution Unit) │
│ "将 Skill 打包供他人安装" │
│ │
│ 关系: │
│ ┌─────────┐ 打包 ┌──────────┐ 安装 ┌─────┐ │
│ │ Skill │ ──────────► │ Plugin │ ────────► │ 用户 │ │
│ │ Skill │ │ │ │ │ │
│ │ MCP │ │ │ │ │ │
│ │ Assets │ │ │ │ │ │
│ └─────────┘ └──────────┘ └─────┘ │
│ │
│ Plugin 可以捆绑: │
│ • 一个或多个 Skills │
│ • App 映射 │
│ • MCP 服务器配置 │
│ • 展示资产 │
│ │
└────────────────────────────────────────────────────────────┘使用建议:
- 本地开发和仓库内工作流 → 直接使用 Skill 目录
- 跨团队分发、捆绑多个 Skill → 打包为 Plugin
九、编写高质量 Skill 的最佳实践
9.1 description 编写原则
markdown
# ✅ 好的 description
description: >
Deploy containerized applications to Kubernetes clusters. Use when the user
asks to deploy, scale, or manage services in k8s, Docker, or container
orchestration environments.
# ❌ 差的 description
description: >
This skill helps with various deployment tasks and infrastructure management
operations that may involve containers and orchestration tools.原则:
- 前置关键词:将最重要的触发词放在开头(截短时仍保留)
- 明确边界:说明何时应该和不应该触发
- 具体场景:列出用户可能的措辞
- 控制长度:~200 字符最优(约 30 tokens)
9.2 自由度分级
| 自由度 | 实现方式 | 适用场景 |
|---|---|---|
| 高 | 纯文本指令 | 多种方案均可,决策依赖上下文 |
| 中 | 伪代码/参数化脚本 | 存在首选模式,允许一定变化 |
| 低 | 具体脚本 | 操作脆弱,一致性至关重要 |
9.3 核心原则
- 一个 Skill 只做一件事:保持专注,不要创建大而全的 Skill
- 优先使用指令:除非需要确定性行为或外部工具,否则偏好文本指令而非脚本
- 祈使句式:使用明确的输入和输出编写步骤
- 保持精简:SKILL.md body 控制在 500 行以内
- 拆分大文件:接近限制时,将详细内容拆到 references/ 中
- 测试触发:用不同的提示词测试 Skill 是否正确触发
十、与 Cursor Skills 的对比
Codex Skills 的设计理念已被多个 AI 编程工具采纳。与本项目使用的 Cursor Skills 对比:
| 维度 | Codex Skills | Cursor Skills |
|---|---|---|
| 文件名 | SKILL.md | SKILL.md |
| 元数据 | YAML frontmatter (name + description) | fullPath + 描述文本 |
| 加载模型 | 三级渐进式加载 | 元数据始终在上下文 + 按需读取 |
| 触发方式 | 显式 $skill + 隐式 LLM 匹配 | Agent 根据描述自动判断 |
| 路由机制 | 纯 LLM 路由(无算法) | 基于 available_skills 列表 |
| 作用域 | 6 级(REPO/USER/ADMIN/SYSTEM) | 2 级(全局 .claude/skills + 项目) |
| 资源支持 | scripts/ + references/ + assets/ | 纯指令文件 |
| 分发机制 | Plugin 打包 | 手动复制 |
| 开放标准 | agentskills.io | 无 |
十一、总结
Codex Skills 的核心设计哲学是**"上下文窗口是公共资源"**。通过三级渐进式加载,它实现了:
- 可扩展性:可安装数十甚至数百个 Skills,启动开销仅为元数据级别
- 精确触发:完全依赖 LLM 语义理解,无需硬编码规则
- 知识无限:通过 Level 3 的捆绑资源,单个 Skill 可携带任意量的专业知识
- 标准化:基于开放的 Agent Skills Standard,跨工具可移植
- 分级控制:六级作用域 + 配置级启用/禁用 + 子智能体级别的精细控制
这套系统将 Codex 从一个通用 AI 编码助手,转变为一个可组合、可扩展的专业智能体平台。