项目:创建并验证 Agent Skill

项目目标

检查一个完整的 text-statistics Skill:合法 frontmatter、明确触发边界、无网络脚本、结构化输出和 eval cases。然后做一次小改动并用负向测试证明校验有效。

项目结构

examples/
├── validate_skill.py                 # 严格教学 profile 验证器
├── test_validate_skill.py            # 56 个离线回归测试
└── text-statistics/
    ├── SKILL.md
    ├── scripts/
    │   └── text_stats.py
    └── evals/
        └── evals.json

样例只读取显式命令行文本或不超过 1 MiB 的 UTF-8 文件;两条输入路径按 UTF-8 字节数应用同一个上限,把统计结果写到 stdout。它不访问网络、不写业务文件、不需要凭据,也不回显原文。

在 PowerShell 7 运行

以下命令从同时包含 docs/ 与 .website/ 的项目根目录运行:

Push-Location -LiteralPath 'docs\Agent Skills' # 进入课程目录,使下面的示例相对路径可正确解析
python -B .\examples\validate_skill.py .\examples\text-statistics # 验证示例 Skill 的 frontmatter、资源引用、评测语料和脚本语法
python -B .\examples\text-statistics\scripts\text_stats.py --text "Hello Agent 世界" # 用直接文本输入演示稳定 JSON 统计;-B 不生成缓存
python -B .\examples\text-statistics\scripts\text_stats.py --help # 查看 CLI 的互斥输入参数与安全提示,不产生文件副作用
python -B .\examples\test_validate_skill.py # 普通模式运行全部离线回归测试
python -B -O .\examples\test_validate_skill.py # 优化模式验证 validator 不依赖 bare assert
python -B -W error .\examples\test_validate_skill.py # 将警告升级为失败,及早发现不兼容行为
python -B -O -W error .\examples\test_validate_skill.py # 组合最严格模式再次验证全部测试
Pop-Location # 恢复进入该代码块前的 PowerShell 工作目录

预期:第一条输出 status: ok、正反各 10 条触发用例和已检查脚本的 JSON;第二条输出包含 words、characters、lines;第三条展示非交互参数说明;四次测试都应报告 56 项通过。-B 避免生成 __pycache__,-O 复跑可证明测试不依赖会被优化移除的裸 assert,-W error 则把 warning 升为错误。

阅读顺序

  1. 打开 SKILL.md,找出“做什么”和“何时用”。
  2. 检查 name 是否与父目录 text-statistics 完全一致。
  3. 检查 body 何时让 agent 运行 text_stats.py,并确认 --text 与文件输入都以 1 MiB UTF-8 字节为界。
  4. 阅读 evals.json,审查正例与近似负例是否真实;它是本课程触发语料格式,不是官方通用 schema。
  5. 运行验证器和测试,再在临时副本中故意把 name 改为 Text-Statistics,确认校验失败;不要破坏课程原件。

资源引用也属于可审计的文本契约:它必须是从 scripts/、references/ 或 assets/ 开始的规范 POSIX 相对路径。即使 scripts/../SKILL.md 解析后仍在 Skill 根内,本地验证器也会拒绝它,以免同一个资源出现多种可混淆写法;这不是对官方规范的额外认证结论。

扩展任务

新增 --top-words N 前先写 contract:输入范围、中文/英文 token 规则、大小写、标点和输出 schema。然后:

  • 更新脚本与 --help;
  • 只有范围确实改变时才更新 description;
  • 新增正常、空文本、非法 N 三个测试;
  • 检查默认输出没有泄露原始全文。

验收清单

  • 本地教学验证器退出码为 0。
  • 脚本无交互、无网络、stdout 为 JSON、缺参时错误可操作。
  • description 含能力与使用时机,且不过度覆盖改写/翻译任务。
  • evals 含正反各 10 条触发用例,负例覆盖相邻任务而非显然无关问题。
  • 56 个回归测试在正常、-O、-W error 与 -O -W error 四种模式通过。
  • 能说明本地验证器不是完整 YAML 解析器,也不是官方规范认证。
  • 若具备官方 skills-ref,另运行 skills-ref validate ./examples/text-statistics;未安装时如实记录未执行。

自测

  1. 为什么父目录名也是契约的一部分?它让发现和 Skill identity 保持稳定。
  2. 为什么 should-not-trigger case 不要求脚本输出?它检验的是 Skill 是否应被加载,而不是运行结果。
  3. 如果脚本需要真实文件写入,应新增哪些保护?至少包括目标范围、dry-run/确认、幂等或回滚、脱敏日志。

参考资料