一、先算账:为什么 Prompt 工程走到尽头

大模型每轮对话都是"失忆"的,于是我们把技术选型、编码规范、业务流程全塞进 CLAUDE.md 之类的 System Prompt。项目一大,三笔账就还不上了:

症状

上下文账

Prompt 越写越胖,窗口被常驻规则占满,真正和当前任务相关的信息被稀释、被"淹没"

复用账

知识和单个项目深度耦合,换个项目整套重写,无法版本化、无法跨团队分发

维护账

所有规则平铺在一个文件里,改一条规范要在几千行里翻,没有人敢动

Agent Skill 的解法一句话:把领域知识封装成可移植、可版本控制的文件夹,Agent 按需加载。官方定义:

Agent Skills are a lightweight, open format for extending AI agent capabilities with specialized knowledge and workflows.

它已被 Claude Code、Cursor、GitHub Copilot、Gemini CLI 等 40+ 主流 Agent 产品采纳,是事实上的开放标准。接下来不讲理念,直接动手。

二、最小闭环:30 分钟搭出一个能用的 Skill

2.1 目录结构与硬性约束

trade-ab-skill/               # 必填:文件夹名即 Skill 名,小写字母+数字+连字符
├── SKILL.md                  # 必填:唯一入口,文件名必须全大写
├── modules/                  # 可选:业务模块(路由式组织,见第五节)
│   ├── creator/
│   │   ├── creator.md
│   │   ├── collect-phase.md
│   │   ├── validate-phase.md
│   │   ├── tools.md
│   │   └── safety.md
│   └── modifier/
│       └── modifier.md
├── scripts/                  # 可选:确定性逻辑脚本(见第七节)
│   └── mcp_precheck.py
├── references/               # 可选:按需查阅的参考文档
└── assets/                   # 可选:模板、静态资源

落地前先过一遍命名红线(不合规直接加载失败):

  • name≤ 64 字符,只允许小写字母、数字、连字符,不能以连字符开头/结尾;
  • SKILL.md 文件名全大写,拼成 skill.md、Skill.md 都不会被识别;
  • description≤ 1024 字符,非空。

2.2 一份完整的 SKILL.md(可直接改改用)

frontmatter 各字段的落地建议(以 Claude Code 为例,其他 Agent 产品字段集大同小异):

字段

必填

落地建议

name

省略时默认取目录名,建议显式写出,避免部署时目录被改名

description

触发命中的唯一依据,写法见第四节,写完必须过触发测试

argument-hint

有必填参数就写,如 [experimentId] [trafficPercent],会在 / 菜单里提示用户

allowed-tools

生产环境必填,支持前缀匹配如 Bash(python:*),见第六节

disable-model-invocation

危险操作类 Skill 设 true,只允许用户 /trade-ab-skill 手动触发

user-invocable

内部被其他 Skill 复用的"库型 Skill"设 false

model

简单任务(查状态、列表)指定轻量模型,省钱省时

context: fork

 + agent

执行过程会产生大量中间文本时,fork 到隔离子智能体,不污染主对话

hooks

需要强制拦截时配,见第六节

version

团队协作必填,semver,改动即递增,问题回溯靠它

2.3 最小模块文件

模块文件只做一件事:把该场景的执行步骤写清楚。以modules/creator/creator.md为例:

2.4 本地验证三招

写完先别提交,按顺序验三件事:

  • 手动触发:/trade-ab-skill 帮我建个实验-- 能进来,说明目录和 frontmatter 合规;
  • 自然语言触发:帮我建个AB(不打斜杠)-- 能自动激活,说明 description 生效;
  • 打包校验:用 skill-creator 的打包脚本跑一遍,它会校验 frontmatter 完整性、name/description是否存在、目录有无非法文件,有问题直接报位置。

三、渐进性披露:不是理念,是文件组织方式

Skill 体系最核心的设计是渐进性披露(Progressive Disclosure),三阶段对应三档上下文成本:

阶段

加载内容

成本量级

发生时机

Discovery 发现

全部 Skill 的 name + description

每个 Skill 几十 token,常驻

会话启动

Activation 激活

命中 Skill 的完整 SKILL.md

2000~3000 token(≈500 行)

任务匹配 description

Execution 执行

路由命中的模块文件

按实际任务而定

进入对应模块

落地要点:绝大多数请求只走前两阶段,这就是"按需投放"的经济学来源,上下文窗口留给当前任务真正需要的知识。能不能拿到这个收益,完全取决于你的文件怎么拆。

拆分判断用这棵决策树(对每一段知识自问自答):

这段知识每次激活 Skill 都需要吗?
├── 是 → 放 SKILL.md(路由表 + 全局红线)
└── 否 → 每次进入该模块都需要吗?
         ├── 是 → 放模块主文件(如 creator.md)
         └── 否 → 仅某个 Step 才需要吗?
                  ├── 是 → 放 phase 文件(如 collect-phase.md)
                  └── 否 → 仅特定条件下查阅吗?
                           ├── 是 → 放参考文件(tools.md / safety.md)
                           └── 否 → 删掉,不要留

三条可量化的拆分阈值:

  • SKILL.md ≤ 500 行(约 2000~3000 token),超过就说明你把知识仓库塞进了路由器;
  • 任何单文件 > 300 行,拆;
  • 某个 Step 的规则 > 100 行,下沉为独立的 phase 文件。

在 SKILL.md 中引用子文件时,必须建立引用契约——只给路径是不够的,Agent 不知道何时读、读完要干什么。模板:

当 <触发条件> 时,读取 <相对路径>,用于 <用途>,读完后应产出 <可验证的结果>

反例:详见 modules/creator/collect-phase.md(没有时间、没有目的,经常被跳过)。 正例:当进入参数收集步骤时,读取 modules/creator/collect-phase.md,逐项执行其中的 11 项清单,全部完成后向用户复述已确认的参数表。

四、触发可靠性:description 是唯一入口,按写接口文档的标准写

触发机制比 Skill 内容本身更重要,内容写得再好,触发不了等于不存在。

4.1 两种触发方式

  • 自动触发:靠 description 做语义匹配,用户无感。新用户友好,但对写法要求高;
  • 手动触发:/trade-ab-skill显式调用。确定性 100%,适合危险操作和老用户。

两者互补,不是二选一。生产建议:常规能力双通道都开;高危能力disable-model-invocation: true,只留手动通道。

4.2 description 写作公式

功能定义(WHAT) + 触发场景(WHEN) + 触发词枚举 + 排除边界(可选)

四个落地原则:

WHAT 和 WHEN 必须同时出现。"处理文档"这种写法等于没写;

显式枚举触发词,包括口语说法。语义匹配靠关键词命中,"创建实验、新建实验、做个实验、建个AB"都要写进去。收集方法:把功能讲给 3 个同事听,录音他们会怎么开口提需求,原话就是触发词;

用第三人称客观描述。description 会被注入系统提示词,写 "Creates and modifies AB experiments",不要写 "我可以帮你建实验";

划定排除边界降误触发。如"不处理实验数据分析与报告解读"。

正反例对照:

❌ 帮助用户操作 AB 实验平台。
✅ 为用户提供 AB 实验的创建与修改能力,支持实验创建、调流量、加桶删桶、
   实验下线等操作。当用户提到创建实验、新建实验、做个实验、建个AB、
   修改实验、调流量、加桶、删桶、实验下线等场景时触发。
   不处理实验数据分析、报告解读场景。

4.3 触发测试:10 正例 + 5 反例

description 定稿前,必须跑触发测试集。模板:

类型

测试输入

预期

正例

"帮我创建一个AB实验"

触发

正例

"新建个实验试试"

触发

正例

"给实验 12345 流量调到 20%"

触发

正例

"这个实验加两个桶"

触发

正例

"把实验 XX 下线"

触发

……

(凑满 10 条自然语言变体,覆盖书面语+口语)

触发

反例

"帮我分析实验 12345 的数据"

不触发

反例

"这个指标的口径是什么"

不触发

反例

"写一篇实验复盘文档"

不触发

……

(凑满 5 条易混淆输入)

不触发

任何一条不达标,回去改 description,不要改测试集。

五、路由式正文:SKILL.md 只干两件事

SKILL.md 的正文是路由器,不是知识仓库。它只保留两样东西:

  • 意图路由表:场景示例 → 路由模块 → 加载文件 → 预期产出(见 2.2 的完整示例);
  • 全局规则:对所有模块生效的安全红线、状态约定。

业务细节全部下沉到模块文件。判断标准很简单:如果你删掉某段内容后 Agent 无法正确分发任务,它才配留在 SKILL.md;否则一律下沉。

多模块同存时,路由表的"场景示例"列就是模块级的二次触发词,写法参照第四节的枚举原则,这是防止"进对了 Skill、走错了模块"的唯一手段。

六、安全落地:三层防线,一层都不能少

工程级 Skill 涉及多模块、多 MCP 接口,必须做模块级工具隔离,权限最小化。单层防护都有绕过路径,三层叠加才可靠:

L1:frontmatter 白名单(声明层)

allowed-tools: Read, Grep, Glob, Bash(python:*)

    Bash(python:*)这种前缀匹配的意思是:只允许通过 python 解释器执行脚本,禁掉任意 shell 命令。Skill 激活期间,白名单外的工具调用直接被拒。

    L2:模块级 tools.md(约定层)

    每个模块自带一份接口白名单,模块之间互不可见对方的接口:

    # creator 模块可用接口(白名单外一律禁止)
    | 接口 | 用途 | 类型 |
    |---|---|---|
    | create_experiment | 创建实验 | 写 |
    | query_business_info | 按工号查业务信息 | 读 |
    
    
    # 易混淆接口警示
    - submit_approval(审批接口):本 Skill 全局禁用,需要时提示用户转人工;
    - publish_experiment(发布接口):同上。

    modifier 模块的 tools.md 里只放 modify_traffic、add_bucket、remove_bucket、offline_experiment,create_experiment 不出现在它的白名单中,即使 Agent"想"调用也没有依据。

    L3:hooks 强制拦截(执行层)

    前两层靠模型自觉,L3 靠运行时强制。以 Claude Code 的 settings.json 为例,对发布类接口做硬阻断:

    {
      "hooks": {
        "PreToolUse": [
          {
            "matcher": "mcp__experiment__publish_experiment",
            "hooks": [
              {
                "type": "command",
                "command": "echo '发布接口已被安全策略禁用,请转人工审批' >&2; exit 2"
              }
            ]
          }
        ]
      }
    }

    PreToolUse 钩子在该工具调用前执行,退出码 2 直接阻断调用并把信息反馈给 Agent。这一层与模型无关,提示词注入也绕不过去。

    落地清单:危险操作(写、删、发布、审批)必须 L3 兜底;万能 HTTP 工具三层同时禁;每个模块的 tools.md 里把"长得像但禁用"的接口点名标注。

    七、把确定性还给脚本

    判断标准一句话:这件事让 LLM 做有概率出错、让脚本做 100% 确定,就封装成脚本。如果你发现自己在 SKILL.md 里写公式让 Agent 做算术,这段逻辑就该挪进 scripts/。

    场景

    纯指令的坑

    脚本的收益

    配置文件读写

    可能产出格式错误的 JSON

    格式保证 + 原子写入

    环境检测

    无法可靠探测系统状态

    直接查询,返回结构化结果

    日志/网络请求

    不应让 LLM 直接处理

    异常自处理,输出干净

    复杂计算

    算术不可靠

    精确

    脚本设计四原则

    • 自愈性:内部消化所有异常,永远正常退出(退出码 0),错误信息放进 JSON 字段,绝不阻断 Skill 主流程;
    • 结构化输出:stdout 只输出 JSON,Agent 解析零成本;
    • 幂等性:多次执行结果一致,预检类脚本只追加缺失项,不覆盖已有配置;
    • 安全边界:只碰指定文件,不碰其他系统资源。

    一份可直接复用的预检脚本

    #!/usr/bin/env python3
    """MCP 依赖预检脚本:Skill 启动前检测运行环境。
    契约:stdout 仅输出一行 JSON;任何情况下退出码为 0。
    """
    import json
    import shutil
    import sys
    
    
    REQUIRED_CLI = ["git", "node"]          # 依赖的命令行工具
    REQUIRED_ENV = ["MCP_ENDPOINT"]         # 依赖的环境变量
    
    
    def main() -> None:
        result = {"ok": True, "checks": [], "missing": []}
        try:
            for cli in REQUIRED_CLI:
                found = shutil.which(cli) is not None
                result["checks"].append({"item": f"cli:{cli}", "ok": found})
                if not found:
                    result["missing"].append(cli)
    
    
            import os
            for env in REQUIRED_ENV:
                found = bool(os.environ.get(env))
                result["checks"].append({"item": f"env:{env}", "ok": found})
                if not found:
                    result["missing"].append(env)
    
    
            result["ok"] = not result["missing"]
        except Exception as exc:  # 自愈:异常也走 JSON 输出
            result = {"ok": False, "checks": [], "missing": [],
                      "error": f"{type(exc).__name__}: {exc}"}
        print(json.dumps(result, ensure_ascii=False))
    
    
    if __name__ == "__main__":
        main()
        sys.exit(0)  # 永不阻断主流程

    Agent 侧的使用方式写进 SKILL.md:执行任何模块前,运行 Bash(python:scripts/mcp_precheck.py),解析返回 JSON;若 ok=false,向用户报告 missing 列表并终止本次操作。Agent 只读 JSON,不"猜"环境状态。

    八、跨阶段的参数与状态工程

    多阶段流程(收集 → 校验 → 提交)最大的翻车点是参数在阶段间丢失或被篡改。三个机制解决:

    8.1 快照(Snapshot):阶段间传参的唯一载体

    约定:每个阶段结束把产出写进snapshot.md,下一阶段开始前先读它。模板:

    8.2 阶段门卡:每个阶段开头的参数完整性检查

    写进各 phase 文件的开头,例如 validate-phase.md:

    ## 门卡(进入本阶段前逐项确认,缺一即终止并回报用户)
    - [ ] snapshot.md 存在且可解析
    - [ ] scenarioId 非空且在对照表范围内
    - [ ] 流量比例为 1~100 的整数
    - [ ] 用户已对参数表回复"确认"

    满足三个要求:显式(来源去向可追溯)、可校验(门卡挡缺项)、防丢失(关键参数落盘)。

    8.3 参数来源分级:用户给的、动态查的、模板定的

    参数

    来源策略

    businessName

    调业务信息查询接口,按当前用户工号动态获取,不问用户

    scenarioId

    拿用户输入的业务关键词,查 creator.md 里的对照表匹配

    metricBindingBases

    固定模板展开的指标数组,不从对话推导

    8.4 用户偏好持久化:第二次用少问一半问题

    操作成功后写入user-prefs.json,下次激活时自动注入:

    {
      "defaultScenarioId": "1001",
      "defaultMetricTemplateId": "tpl-200",
      "recentExperimentIds": ["12345", "12330"],
      "lastUsed": "2026-08-17",
      "usageCount": 2
    }

    落地细节:写文件用先写临时文件再 rename 的原子写入方式,防止中断写出半个 JSON;读取失败时静默降级为"无偏好",不报错、不阻断。

    九、测试与迭代:把 Skill 当软件测

    9.1 三类测试,一类都不能省

    ① 触发测试:见 4.3 的 10 正例 + 5 反例表。每次改 description 后重跑。

    ② 功能走查:用自然语言驱动完整流程,逐项核对:

    • 路由是否分发到正确模块;
    • 渐进加载是否按时序发生(不命中模块的文件没有被读);
    • 红线规则是否被遵守;
    • 异常场景:故意输边界值(流量填 0、填 999)、模拟工具不可用、诱导 Agent 调用禁用接口,happy path 测不出问题,这些才暴露问题。

    ③ 性能对比:同一任务,"无 Skill"和"有 Skill"各跑 5 次,记录两组数字:

    指标

    无 Skill

    有 Skill

    平均 token 用量

    一次成功率

    需要人工纠正次数

    9.2 观测驱动迭代

    迭代闭环与传统软件一致:发现问题 → 定位原因 → 修复文档 → 验证效果。高效做法是给 Skill 加日志埋点,用数据定位薄弱环节。埋点字段建议:

    字段

    说明

    traceId

    一次操作的唯一标识

    skillVersion

    用于回溯"哪个版本引入的问题"

    phase

    当前阶段(collect/validate/submit)

    status

    success / failed / cancelled

    durationMs

    各阶段耗时

    toolsCalled

    实际调用的工具列表(对照白名单审计)

    跨阶段操作用两阶段 traceId 配对:发起阶段埋一条、完成阶段埋一条,同一 traceId 配对成功才算闭环,能精确算出每阶段的失败率和耗时分布。

    十、团队协作:作用域、优先级与版本化

    10.1 作用域放哪里

    位置

    生效范围

    放什么

    企业配置中心

    全员

    强制开发规范、安全策略

    用户主目录全局配置

    个人所有项目

    通用工具、个人偏好

    项目根目录 / .skills/

    仅当前项目

    项目特定工作流、团队约定

    Plugin 内置

    随 Plugin 分发

    社区能力包、框架专用指令集

    两个 Skill 同时命中时的优先级惯例:企业策略 > 个人配置 > 项目配置 > Plugin 内置(不同产品实现略有差异,上线前用双 Skill 冲突用例实测一次)。

    10.2 Git 工作流

    • Skill 就是代码:一个仓库(或 monorepo 一个目录),走 MR 评审;
    • version 字段走 semver:改 description/路由表等影响触发的内容 → minor 起步;修文案 → patch;
    • commit message 里写清"改了哪个文件、影响了哪个模块",埋点数据回溯时靠它定位。

    10.3 用 skill-creator 从零起步的标准话术

    skill-creator 本身也是一个 Skill,负责初始化与打包。全流程只需对 AI 说六句话:

    • 帮我用 skill-creator 生成一个名为 order-query 的 Skill(生成标准目录)
    • 帮我编写 order-query 的详细内容,功能是 xxx,用于 xxx 场景,触发词包括 xxx、xxx
    • 把 xxx 的详细流程整理成 references/workflow.md,并在 SKILL.md 中加上引用
    • 用 skill-creator 打包验证 order-query,检查格式是否合规(自动校验 frontmatter、必填字段、非法文件)
    • 帮我把 order-query 初始化为 git 仓库,关联远端地址,提交并推送到 main
    • 后续迭代:帮我提交 order-query 的最新改动,commit 信息是 xxx,然后推送

    编写时的四个要点:description 枚举全部触发词;正文只写领域专有知识、不写常识;复杂内容拆到 references/ 用相对路径引用;SKILL.md 控制在 500 行以内。

    十一、上线前 Checklist(全部打勾再发布)

    结构合规

    • [ ] 目录名 = name,小写连字符,≤ 64 字符
    • [ ] SKILL.md 全大写,frontmatter 的 name/description 非空且 description ≤ 1024 字符
    • [ ] SKILL.md ≤ 500 行,无超过 300 行的单文件
    • [ ] 每个子文件引用都写了"何时读 + 为何读 + 读完产出什么"

    触发可靠

    • [ ] description 含 WHAT + WHEN + 触发词枚举(含口语说法)
    • [ ] 排除边界已声明
    • [ ] 10 正例全部触发,5 反例全部不触发

    安全

    • [ ] allowed-tools 已配置且最小化
    • [ ] 每个模块有 tools.md 白名单,易混淆禁用接口已点名
    • [ ] 危险接口有 hooks 硬阻断(不止靠提示词约束)

    健壮性

    • [ ] 确定性逻辑全部脚本化,脚本输出 JSON、退出码恒 0
    • [ ] 跨阶段参数走 snapshot,每阶段有门卡
    • [ ] user-prefs.json 原子写入、读取失败静默降级

    可运营

    • [ ] 功能走查覆盖异常场景(边界值、工具不可用、诱导越权)
    • [ ] 有/无 Skill 的 token 与成功率对比数据已留档
    • [ ] 埋点字段含 traceId、skillVersion、phase、status
    • [ ] version 已按 semver 打号,仓库可回溯

     学习资源推荐

    如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

    一、全套AGI大模型学习路线

    AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!​

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

    二、640套AI大模型报告合集

    这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示

    ​因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

    三、AI大模型经典PDF籍

    随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

    因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

    四、AI大模型商业化落地方案

    作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

    Logo

    小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

    更多推荐