跳转到内容

技能系统设计:SKILL.md 结构、关键词检测与意图门控

技能系统设计:SKILL.md 结构、关键词检测与意图门控

学习目标

  • 理解 OMX 如何通过 SKILL.md 文件定义可复用工作流
  • 掌握关键词检测引擎的四层流水线
  • 了解意图门控防止危险技能误触发的实现
  • 理解任务规模过滤器和 Ralplan 门控的防御性设计

前置知识

本章涉及技能系统设计的通用原理,建议先阅读:

下文假设你已理解上述概念,直接聚焦 Oh-My-Codex 的具体实现。


项目实践

SKILL.md 结构

OMX 的每个技能都是一个目录,至少包含一个 SKILL.md 文件:

skills/
├── deep-interview/
│ └── SKILL.md
├── ralplan/
│ └── SKILL.md
├── ultragoal/
│ └── SKILL.md
├── ralph/
│ └── SKILL.md
├── team/
│ └── SKILL.md
├── autopilot/
│ └── SKILL.md
├── prometheus-strict/
│ ├── SKILL.md
│ └── README.md
└── ... (共 46 个技能)

SKILL.md 的前置元数据(YAML frontmatter):

---
name: deep-interview
description: 通过面试式提问澄清需求、边界和非目标
triggers: ["$deep-interview", "interview me", "don't assume"]
argument-hint: "describe the change or problem"
---

正文使用标准化的章节结构:Purpose、Use_When、Do_Not_Use_When、Steps、Tool_Usage、Examples。

技能分类

OMX 的 46 个技能分为以下类别:

类别数量典型技能
核心执行工作流9autopilot、ralph、ultragoal、team、pipeline
规划/面试4deep-interview、ralplan、prometheus-strict、best-practice-research
分析/审查5analyze、code-review、security-review、visual-verdict
设计/视觉3design、frontend-ui-ux、visual-ralph
实用工具10cancel、note、doctor、trace、hud、wiki
领域特定6git-master、build-fix、tdd、deepsearch
询问/沟通3ask、ask-claude、ask-gemini
协调2worker、ralph-init

关键词检测引擎的具体实现

OMX 的关键词检测引擎(src/hooks/keyword-detector.ts,~1800 行)运行在 Codex 的 UserPromptSubmit Hook 中。

四层检测流水线

关键词注册表src/hooks/keyword-registry.ts):

伪代码:
const KEYWORD_TRIGGER_DEFINITIONS = [
{ keywords: ["$autopilot", "autopilot", "build me"], skill: "autopilot", priority: 10 },
{ keywords: ["$ralph", "don't stop", "keep going"], skill: "ralph", priority: 9 },
{ keywords: ["$deep-interview", "interview me", "don't assume", "ouroboros"], skill: "deep-interview", priority: 8 },
{ keywords: ["$cancel", "stop", "abort"], skill: "cancel", priority: 5 },
// ... 更多定义
]

意图门控的危险关键词列表

伪代码:
KEYWORDS_REQUIRING_INTENT = [
"ralph", "team", "stop", "abort", "parallel",
"autoresearch", "ultragoal", "autopilot"
]

这些关键词即使用户在输入中提到,也需要显式的调用上下文(如 $ralphuse ralphralph mode)才能触发。

技能激活与状态持久化

关键词匹配后,recordSkillActivation() 执行:

伪代码:
function recordSkillActivation(skill, prompt, sessionId):
// 1. 持久化技能激活状态
state = read(".omx/state/skill-active-state.json")
state.activeSkill = skill
state.activatedAt = now()
write(state)
// 2. 初始化技能模式状态
if skill == "autopilot":
write(".omx/state/autopilot-state.json", { phase: "deep-interview", iteration: 0 })
if skill == "deep-interview":
write(".omx/state/deep-interview-state.json", { inputLocked: true })
// 3. 管理深度面试的输入锁(防止 "yes"/"ok" 等自动通过)
if skill == "deep-interview":
setInterviewInputLock(sessionId, true)

任务规模过滤器

伪代码(src/hooks/task-size-detector.ts):
function classifyTaskSize(text):
wordCount = countWords(text)
hasSmallSignals = text.contains([
"typo", "spelling", "rename", "one-liner", "single file", "minor fix"
])
hasLargeSignals = text.contains([
"architecture", "refactor", "redesign", "cross-cutting", "migration", "full-stack"
])
if wordCount < 50 && hasSmallSignals:
return "small"
if wordCount > 200 || hasLargeSignals:
return "large"
return "medium"

小型任务会抑制重型模式(ralph、autopilot、team、ultrawork、ultragoal、swarm、ralplan)的触发。逃生舱前缀:quick:simple:tiny:minor:small:just:only:

Ralplan 门控

伪代码(keyword-detector.ts 中的 applyRalplanGate):
function applyRalplanGate(keyword, text):
if keyword not in ["ralph", "autopilot", "team", "ultrawork"]:
return keyword
effectiveWords = countEffectiveWords(text)
hasFileRefs = regexMatchFilePatterns(text)
hasCodeBlocks = text.contains("```")
hasStructured = regexMatchStructuredPatterns(text)
if effectiveWords < 15 && !hasFileRefs && !hasCodeBlocks && !hasStructured:
return "ralplan" // 输入太模糊,先规划
return keyword

Prompt 引导合约(不变量验证)

OMX 维护一套 Prompt 引导合约(src/hooks/prompt-guidance-contract.ts),验证模板文件中的关键模式是否存在:

伪代码:
const ROOT_TEMPLATE_CONTRACTS = [
{
file: "templates/AGENTS.md",
patterns: [
/outcome.first framing/i,
/auto-continue rule/i,
/permission handoff/i,
/role routing guidance/i
]
}
]
const SKILL_CONTRACTS = [
{ file: "skills/ultraqa/SKILL.md", patterns: [
/adversarial e2e/i,
/scenario matrix/i,
/hostile user modeling/i,
/prompt injection testing/i
]}
]

这确保重构提示词时不会遗漏关键指令。

问题与规避

问题后果OMX 的规避策略
危险技能误触发意外执行破坏性操作意图门控要求显式调用上下文
小任务触发重型编排资源浪费、延迟高任务规模过滤器 + 逃生舱前缀
模糊输入直接执行产出方向错误Ralplan 门控自动重定向到规划
提示词重构遗漏关键指令Agent 行为异常Prompt 引导合约验证
过期技能残留旧工作流被误触发omx setup 清理 deprecated 技能

设计取舍

为什么选择关键词检测而非纯 Agent 判断?

OMX 选择了基于关键词的显式路由,而非让 Agent 自主判断使用哪个技能。

优势

  • 确定性:匹配结果是确定的,不受模型输出波动影响
  • 低延迟:关键词匹配比额外一轮 Agent 推理快得多
  • 用户可控:用户通过 $skill 语法精确控制触发哪个技能

代价

  • 用户需要学习技能名称和触发短语
  • 关键词注册表需要维护,避免膨胀和冲突

替代方案

  • 纯 Agent 判断:让 Agent 根据输入自主选择技能(更灵活但不可控)
  • 混合模式:关键词优先,无匹配时 Agent 自主判断(OMX 的 triage heuristic 就是这种模式)

参考来源

  • Oh-My-Codex v0.18.9 源码 — src/hooks/keyword-detector.ts(检测引擎)
  • Oh-My-Codex v0.18.9 源码 — src/hooks/keyword-registry.ts(关键词注册表)
  • Oh-My-Codex v0.18.9 源码 — src/hooks/task-size-detector.ts(任务规模分类)
  • Oh-My-Codex v0.18.9 源码 — src/hooks/prompt-guidance-contract.ts(引导合约验证)
  • Oh-My-Codex v0.18.9 源码 — skills/ 目录(46 个 SKILL.md 文件)