Meta-Skill 编写指南
本指南面向编写、校验和审阅 OpenSquilla MetaSkills 的作者与维护者。面向用户的指南请阅读 ../features/meta-skill-user-guide.md。
MetaSkill 是什么
MetaSkill 是一个 SKILL.md 文件,包含:
kind: meta;- 一个或多个自然语言的
triggers; - 一个
composition:块,定义步骤的有向无环图。
在运行时,模型可以调用:
meta_invoke(name="<meta-skill-name>")
随后 OpenSquilla 会按声明的 composition 逐步执行,并将最终结果返回给用户。模型选择 workflow,但运行时强制执行依赖顺序、模板渲染、风险元数据、递归防护、工具门禁、暂停以及最终文本选择。
运维人员可以在全局禁用模型可见的 MetaSkill 行为:
[meta_skill]
enabled = false
禁用后,MetaSkills 仍会被安装以便清点和历史运行查看,但不会被注入到 prompts,meta_invoke 也不会对模型可见,显式的 meta_invoke 调用会被拒绝。
何时使用 MetaSkill
当一项任务可重复并自然分解为一个小型 workflow 时,使用 MetaSkill,例如:
- 对用户请求进行分类,然后路由到合适的专家 skill;
- 运行两个独立的分析 skill,然后合并它们的输出;
- 搜索或检查上下文,然后将其总结为面向用户的回答;
- 执行一个确定性的、由 CLI 支撑的 skill,然后审阅或持久化结果;
- 在继续之前暂停以收集结构化的用户输入。
不要将 MetaSkill 用于一次性指令、应当保持对话式的开放式规划,或需要任意递归的流程。MetaSkill 不能组合另一个 MetaSkill。
MetaSkill 的放置位置
对于本地管理的 skills,创建:
~/.opensquilla/skills/<skill-name>/SKILL.md
对于仓库内置的 skills,将该 skill 放在内置 skills 目录树下:
src/opensquilla/skills/bundled/<skill-name>/SKILL.md
生成的提案在安装前会被审阅。接受提案后,OpenSquilla 会将其提升到受管 skills 目录,并刷新在线 skill 加载器。
基本编写流程
- 定义任务契约:输入、输出、边界、误触发情形以及用户确认点。
- 编写保守的
name、description和triggers。 - 将 workflow 拆分为如 intake、collect、analyze、draft、audit、deliver 等步骤。
- 当某步骤需要前序步骤的输出时,加入
depends_on。 - 在模板中过滤所有用户输入与前序步骤输出。
- 声明风险元数据与 capabilities。
- 运行确定性检查和软激活检查。
- 在接受或启用前,检查提案以及自动启用的审计输出。
用户可以通过两种方式激活 MetaSkill:
- 软激活:自然提问,让模型选择正确的
meta_invoke调用。 - 显式激活:在调试或测试时按名称请求该 MetaSkill。
必需的 Frontmatter
每个 MetaSkill 都应声明:
---
name: short-stable-name
kind: meta
description: One sentence that tells the model when this workflow applies.
triggers:
- short phrase users naturally type
meta_priority: 50
always: false
final_text_mode: auto
metadata:
opensquilla:
risk: low
capabilities: []
composition:
steps: []
---
各字段含义:
name:meta_invoke使用的稳定标识符。kind:必须是meta。description:面向模型的描述,说明何时使用该 workflow。triggers:用于确定性和模型辅助激活的短语。meta_priority:当多个 MetaSkills 可能匹配时的排序键。always:通常为false;MetaSkills 不应被无条件注入。final_text_mode:最终回答的派生方式。metadata.opensquilla.risk:无人值守自动启用时所需的最高风险等级。metadata.opensquilla.capabilities:显式声明的副作用 capabilities。composition.steps:有序的 DAG 定义。
风险元数据
使用 metadata.opensquilla.risk 声明 workflow 所需的最高风险等级:
low:只读推理、分类、摘要或安全的本地检查。medium:本地文件或 artifact 写入、确定性的文档生成或网络读取。high:shell/进程控制、凭据使用、网络写入、外部副作用或可改变状态的直接工具调用。
使用 metadata.opensquilla.capabilities 显式标明副作用。常见的 capabilities 包括:
filesystem-write;artifact-write;document-export;network;network-read;network-write;external-side-effect;credential-use;process-control;shell。
如果被引用的子 skill 缺少风险元数据,无人值守自动启用会对依赖做保守处理。新 skill 应声明 risk 和 capabilities,而不是依赖遗留兼容回退。
步骤类型
MetaSkill 步骤支持以下执行类型。
agent
将 agent 用于普通的、由 skill 支撑的 sub-agent turn。这是用户面向的推理和综合的最佳默认值。
- id: summarize
kind: agent
skill: summarize
with:
text: "{{ outputs.search | truncate(2000) }}"
llm_chat
将 llm_chat 用于一次有界、无工具循环的 LLM 生成步骤。适用于 intake 归一化、紧凑起草、最终 audit 和轻量综合。
- id: normalize
kind: llm_chat
with:
system: "Extract the request fields. Do not ask a question."
task: "{{ inputs.user_message | xml_escape | truncate(1000) }}"
llm_classify
当步骤应当从一个封闭集合中返回恰好一个值时使用 llm_classify。适用于路由、分诊和紧凑决策。
- id: classify
kind: llm_classify
output_choices: [BUG, FEATURE, QUESTION]
with:
text: "{{ inputs.user_message | xml_escape | truncate(512) }}"
user_input
当 workflow 应当暂停并从用户处收集结构化数据时使用 user_input。该步骤需要一个 clarify: schema。
- id: collect_project
kind: user_input
when: "'NEEDS_CLARIFICATION: yes' in outputs.intake"
clarify:
mode: form
intro: "A few fields are needed before this workflow can continue."
nl_extract: true
fields:
- name: topic
type: string
required: true
prompt: "Topic"
max_chars: 200
支持的字段类型为 string、enum、int 和 bool。当 intake 已有足够信息时,使用 skip_if 或 when 避免暂停。
tool_call
仅在确定性的直接工具执行时使用 tool_call。声明一个 tool_allowlist,保持参数收窄,并在工具可改变状态时将该 MetaSkill 标记为高风险。
- id: persist
kind: tool_call
tool: memory_save
tool_allowlist: [memory_save]
tool_args:
text: "{{ outputs.summary | truncate(2000) }}"
skill_exec
对带有 entrypoint: manifest、应当作为子进程运行的 skill 使用 skill_exec。这适用于确定性的、由 CLI 支撑的 skill,例如文档转换或报告生成。
- id: render
kind: skill_exec
skill: html-to-pdf
with:
html: "{{ outputs.report | truncate(12000) }}"
步骤标签与进度
两个可选的步骤级字段驱动 WebUI 的运行进度条带
(参见 ../features/meta-skill-user-guide.md
中的”运行进度条带”):
label:步骤的简短、人类可读名称。条带会将其渲染为 chip 文本。 如果省略,WebUI 会将步骤id人性化处理(例如intake→Intake)。progress_emits:步骤的执行器是否可以向条带发布实时status_text更新。按类型的默认值:agent/skill_exec:truetool_call:falsellm_chat/llm_classify/user_input:忽略
示例:
composition:
steps:
- id: intake
kind: llm_chat
label: 意图提取
with: { ... }
- id: search
kind: agent
skill: web-research
label: 检索证据
progress_emits: true
with: { ... }
保持标签简短(中文 2-6 字,英文 1-2 个词)。过长的标签会在条带头部被截断。
依赖与并行
无依赖的步骤可以并行运行。带 depends_on 的步骤会等待所有命名步骤完成。
composition:
steps:
- id: inspect_code
kind: agent
skill: code-reviewer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: inspect_tests
kind: agent
skill: test-engineer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: merge
kind: agent
skill: summarize
depends_on: [inspect_code, inspect_tests]
with:
text: |
Code review:
{{ outputs.inspect_code | truncate(2000) }}
Test review:
{{ outputs.inspect_tests | truncate(2000) }}
图必须是无环的。一个步骤只能依赖于同一 composition 中声明的步骤 id。
路由与失败处理
当一个 agent 或 skill_exec 步骤应根据先前输出选择 skill 时,使用 route:
- id: classify
kind: llm_classify
output_choices: [DOCS, BUG, SECURITY]
with:
text: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: handle
kind: agent
skill: summarize
depends_on: [classify]
route:
- when: "outputs.classify == 'DOCS'"
to: writer
- when: "outputs.classify == 'BUG'"
to: debugger
- when: "outputs.classify == 'SECURITY'"
to: security-reviewer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
使用 on_failure 指定单个替代步骤。该替代步骤必须存在于同一计划中,不得有自己的依赖项,也不得有自己的 on_failure。
Final Text 模式
使用 final_text_mode 控制面向用户的最终结果:
auto:默认。编排器将各步骤输出总结为一个简洁的最终回答。raw:原样返回最后一个非替代步骤的输出。step:<step_id>:原样返回某一指定步骤的输出。
示例:
final_text_mode: auto
final_text_mode: raw
final_text_mode: "step:summarize"
当某一个步骤就是预期交付物时,使用 step:<step_id>。当最终步骤已经格式化为完整报告时,使用 raw。当 workflow 产生若干中间输出,需要一个紧凑的面向用户的总结时,使用 auto。
模板安全
模板使用 Jinja 表达式。将用户输入和先前步骤的输出视为不可信:
- 对于用户文本,先用
xml_escape或slugify,然后用truncate限定边界。 - 对于
outputs.<step_id>,始终使用truncate、xml_escape、slugify或tojson进行边界限定或编码。 - 不要将原始
{{ inputs.user_message }}传入下游步骤。 - 不要将原始
{{ outputs.some_step }}传入另一个步骤。 - 保持 prompt 形状的字符串显式、简短且任务专属。
安全示例:
query: "{{ inputs.user_message | xml_escape | truncate(512) }}"
text: "{{ outputs.search | truncate(2000) }}"
slug: "{{ inputs.user_message | slugify | truncate(80) }}"
payload: "{{ outputs.plan | tojson }}"
不安全示例:
query: "{{ inputs.user_message }}"
text: "{{ outputs.search }}"
激活指南
在正常的产品使用中,MetaSkills 默认仅支持手动运行。用户通过 /meta <name> 启动它们,因此只有在你有意支持 meta_skill.auto_trigger = true 时,才需要 trigger 和软激活检查。
在维护自动触发兼容性时,将 triggers 写成用户会自然输入的短语:
- 推荐:
summarize recent history - 推荐:
review current diff - 避免:
run the internal OpenSquilla DAG composition meta skill
除非生产 workflow 有经过测试的理由,否则使用 2 到 5 个 triggers。避免与解释性问题冲突的 triggers,例如”how does this meta-skill work?”。当启用自动触发兼容性时,询问 MetaSkill 的用户不应意外地运行它。
将 description 设置为说明模型在自动触发模式下何时应选择该 workflow。不要只把关键约束藏在正文中;当启用自动触发时,模型主要看到的是 frontmatter 和注入的 skill 摘要。
校验清单
在分享或启用 MetaSkill 之前:
- 确认 frontmatter 可作为 YAML 解析。
- 确认存在
kind: meta和composition.steps。 - 确认所有
depends_on、route.to以及on_failure引用都指向有效的步骤或 skills。 - 确认图中无环。
- 确认所有用户输入和步骤输出都已过滤。
- 确认
metadata.opensquilla.risk和metadata.opensquilla.capabilities真实反映 workflow 的副作用。 - 如果支持
meta_skill.auto_trigger = true,使用scripts/meta_trigger_accuracy.py运行确定性 trigger 检查。 - 如果支持
meta_skill.auto_trigger = true,使用scripts/live_meta_soft_activation_e2e.py --env-file /path/to/.env运行模型决策的软激活检查。 - 对于生成的 skills,在接受或启用前检查 Web UI 中的提案详情及其自动启用 audit。
排障
如果 MetaSkill 似乎未运行:
- 检查
SKILL.md是否位于已加载的 skill 目录下。 - 如果 skill 是在提案接受流程之外添加的,刷新或重启 gateway。
- 确认你在支持 MetaSkill 运行的形态上用
/meta <name>运行了它。 - 确认你希望模型调用的 MetaSkill 未设置
disable-model-invocation。 - 如果你期望自然语言自动触发,确认
meta_skill.auto_trigger = true。 - 确认该 skill 具有
kind: meta且composition.steps列表非空。 - 确认用户措辞与 triggers 或 description 相匹配。
如果解析失败:
- 检查重复的步骤 id。
- 检查未知的
kind值。 - 检查
agent或skill_exec步骤缺失skill。 - 检查
llm_classify缺失output_choices。 - 检查
user_input缺失clarify.fields。 - 检查
tool_call缺失tool、tool_args非法或tool_allowlist不匹配。 - 检查环以及未定义的
depends_on引用。
如果自动启用被跳过:
- 在 Web UI 中检查提案的自动启用 audit。
- 为被引用的子 skills 补充缺失的风险元数据。
- 降低 workflow 的副作用,或要求 medium/high 风险 workflow 通过人工审阅。
测试 Prompts
至少包含:
- 英文正向 trigger;
- 显式调用;
- 粘贴历史的反例;
- 邻近领域的反例;
- 输出质量评判的 rubric。
使用真实的用户措辞,主体和目标清晰。避免使用用户不会自然输入的运维风格短语。