Skill 不是 Prompt,Skill 是文件夹:Anthropic 内部 Agent 工程的六个核心 Insight
March 25, 2026 · Tech Blog
基于 Thariq 的推文整理,原文:https://x.com/trq212/article/2033949937936085378
一、重新理解 Skill:从 Prompt 到微型 SDK
很多人对 Claude Code Skills 的第一反应是"写一段好的 prompt 让模型更聪明"。这是一个根本性的误解。
SKILL.md 只是索引层——一个路由表加分场景指令。真正的能力在整个文件夹里的脚本和资源。Claude 在触发 Skill 时,不是在"读一段写得好的 prompt 然后靠自己的知识去干活",而是在发现和调用一整套工具链。
以 Claude 内置的 docx Skill 为例,它的目录结构是这样的:
docx/
├── SKILL.md # 入口:路由表 + 分场景指令
├── scripts/
│ ├── accept_changes.py # 接受 tracked changes
│ ├── comment.py # 处理批注
│ ├── templates/ # Word 批注的 XML 模板
│ │ ├── comments.xml
│ │ ├── commentsExtended.xml
│ │ └── ...
│ └── office/
│ ├── pack.py # 散装 XML → .docx
│ ├── unpack.py # .docx → XML
│ ├── validate.py # 文档合规校验
│ ├── soffice.py # LibreOffice 转换桥接
│ ├── schemas/ # ~977KB 的 OOXML schema
│ └── validators/
这不是一段 prompt。这是一个给 agent 用的微型 SDK:有入口文件、有脚本、有模板、有 schema、有验证器。Skill 的价值不在于"告诉 Claude 怎么想",而在于"给 Claude 一整套可执行的基础设施"。
二、Skill 的八个品类:好的 Skill 只属于一类
Anthropic 内部把 Skills 归成了几个清晰的品类。跨类的 Skill 往往让 agent 困惑——一个 Skill 试图同时做 Data Fetching 和 Workflow Automation,模型反而不确定什么时候该触发它。
1. Library & API Reference
解决的问题: 模型训练数据中某个库/框架的覆盖率不够,导致频繁"猜" API。
babylonjs-reference/
├── SKILL.md # "当用户要写 Babylon.js 代码时触发"
├── gotchas.md # ❌ 不要用 scene.pick(),用 scene.pickWithRay()
│ # ❌ PBRMaterial 的 metallic 默认值是 0 不是 1
└── snippets/
├── physics_v2.ts # Havok 物理引擎的正确初始化方式
├── mesh_instancing.ts
└── webgpu_setup.ts
Claude 训练数据里 Babylon.js 的比例远低于 Three.js,它会频繁猜 API。这个 Skill 让它不用猜——直接查 snippets 文件夹。对于任何团队内部 SDK 也同理:把正确的调用方式和常见坑点写成 Skill,比在 prompt 里反复强调高效得多。
2. Verification
解决的问题: Agent 说"好了",但你不知道它的输出到底对不对。
visual-verification/
├── SKILL.md # "每次生成前端组件后必须执行验证"
├── scripts/
│ ├── screenshot.py # Playwright 无头浏览器渲染截图
│ ├── assert_layout.py # 元素是否在视口内、是否重叠
│ └── record_video.sh # 录制交互过程
└── config.json # dev server 地址、viewport 尺寸
Thariq 特别强调的 insight:让 Claude 录屏自己的输出。 你作为 reviewer 不需要自己跑一遍——直接看 Claude 自己生成的截图/视频就知道它到底测了什么。文章说值得一个工程师花一整周专门打磨 Verification Skill,因为它的质量直接决定了你能不能信任 agent 的输出。
3. Data Fetching & Analysis
解决的问题: 每次查数据都要手动写 SQL、告诉模型表名和字段名。
retention-analysis/
├── SKILL.md
├── config.json # ClickHouse 连接串、Grafana dashboard ID
├── queries/
│ ├── funnel.sql # signup → activation → paid 标准漏斗
│ ├── cohort.sql # 按周 cohort 的留存矩阵
│ └── segment_defs.json # "高价值用户"、"流失风险"的标准定义
└── lib/
└── fetch_data.py # 封装认证逻辑的查询脚本
说一句"帮我看下上周的 D7 留存",Claude 就知道用哪个 SQL 模板、连哪个数据库、怎么认证。
4. Workflow Automation
解决的问题: 重复性流程需要人盯着。
babysit-pr 是原文给的真实例子:
babysit-pr/
├── SKILL.md # "当用户说 babysit 这个 PR 时触发"
├── scripts/
│ ├── check_ci.sh # 轮询 CI 状态
│ ├── retry_flaky.sh # 识别 flaky test 并重跑
│ ├── resolve_conflicts.py
│ └── enable_automerge.sh
└── logs/
└── runs.jsonl # 每次执行的日志(Skill 自带记忆)
发了个 PR,说一句"babysit it",然后去吃饭。回来它已经帮你重跑了两次 flaky test、rebase 了一次 main、合进去了。logs/ 让 Claude 能回顾执行历史,下次做类似的事会更聪明。
5. Scaffolding
解决的问题: 项目脚手架里有些决策需要自然语言判断,纯模板覆盖不了。
create-service/
├── SKILL.md
├── templates/
│ ├── main.go.tmpl
│ ├── Dockerfile.tmpl
│ ├── deploy.yaml.tmpl
│ └── auth_middleware.go.tmpl
└── decisions.md # 自然语言决策树:
# - 面向外部?→ 加 rate limiter + WAF
# - 处理 PII?→ 加加密层 + audit log
# - 延迟敏感?→ 用 gRPC 不用 REST
纯 cookiecutter 模板只能做条件渲染,不能做"根据业务语境判断要不要加某个模块"。Skill 把这层自然语言推理交给 Claude。
6. Code Quality & Review
解决的问题: 写代码的 Claude 和审代码的 Claude 是同一个上下文,有"作者偏见"。
adversarial-review 是原文最有意思的例子:
adversarial-review/
├── SKILL.md
├── review_prompt.md # 给 subagent 的指令:假装你是一个
│ # 对这个 PR 完全不了解的 senior engineer
└── scripts/
├── spawn_reviewer.sh # 启动独立 subagent(全新上下文)
├── apply_fixes.sh # 自动应用修复
└── iterate.sh # review → fix → re-review 循环
# 直到 findings 降级到 nitpick 级别
关键设计:用独立 subagent做 review,写代码和审代码的 Claude 完全隔离。和人类 code review 的逻辑一样——写的人看不到自己的盲点。
7. CI/CD & Deploy
解决的问题: 部署流程中的灰度、监控、回滚需要人工判断。
deploy-payment-service/
├── SKILL.md
├── scripts/
│ ├── build.sh
│ ├── smoke_test.py # 打核心 API endpoint
│ ├── canary_rollout.py # 1% → 10% → 50% → 100%
│ ├── monitor_errors.py # 灰度期间 error rate vs baseline
│ └── rollback.sh # 超阈值自动回滚
└── config.json # 各环境的 cluster name、阈值参数
8. Investigation & Debugging
解决的问题: On-call 调查依赖工程师脑子里的 playbook。
payment-debugging/
├── SKILL.md
├── symptom_map.md # 症状 → 工具 → 查询模式:
│ # "用户说扣款了但没到账" → 查 Stripe webhook
│ # "超时" → 查 Grafana p99 延迟
│ # "重复扣款" → 查幂等性 key 碰撞
├── scripts/
│ ├── fetch_stripe_events.py
│ ├── query_grafana.py
│ └── check_idempotency.py
└── report_template.md # 结构化输出:症状 / 根因 / 影响范围 / 修复建议
本质上是把调查 playbook 外化成 agent 可执行的流程。
三、Description 不是摘要,是触发条件
Claude 在 session 开始时扫描所有 Skill 的 description 来决定"这个请求有没有对应的 Skill"。所以 description 是触发器,不是总结。
写得模糊,Claude 就永远不会加载它——不管 SKILL.md 本身写得多好。
写 description 的正确顺序:
- 先写清楚这个 Skill 做什么
- 再写什么时候应该触发(具体的用户意图、关键词、场景)
- 需要有点 pushy——宁可过度触发再剪枝,也不要 undertrigger
四、Skill 可以自带记忆
你可以在 Skill 里存数据:简单的用 append-only 文本日志或 JSON,复杂的用 SQLite。
比如一个 standup-post Skill 维护一个 standups.log,下次执行时 Claude 会读自己的历史,知道上次写了什么、这次应该从哪里接续。
这是一个巧妙的状态持久化方案——不依赖外部基础设施,Skill 文件夹本身就是状态容器。
五、用 Hook 做量化度量
Anthropic 内部用 Hook 记录 Skill 使用情况,发现哪些 Skill 高频使用、哪些在 undertriggering。
Hook 是 Claude Code 生命周期里的拦截器,核心三个时机:
PreToolUse — 动作执行前
Claude 准备跑 git push origin main,hook 先拿到命令,可以放行、拒绝、或改掉输入再放行。也可以在这里做 Skill 使用统计。
PostToolUse — 动作执行后
Claude 刚编辑完文件,hook 自动跑 prettier + eslint + typecheck。lint 挂了就把错误信息返回给 Claude 自己修。
{
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": ".claude/hooks/post-edit-quality.sh"
}]
}]
}
Stop — Claude 觉得自己干完了
这个最狠。Claude 说"我做完了",Stop hook 检查:测试跑了没?build 通过了没?如果没有,hook 返回 exit code 2,Claude 被打回去继续干。
{
"Stop": [{
"hooks": [{
"type": "command",
"command": ".claude/hooks/verify-completion.sh"
}]
}]
}
六、Skill 之间可以有依赖关系
目前没有原生的依赖管理机制,但你可以在 Skill 里按名字引用其他 Skill,模型会自动调用已安装的那些。
这意味着你可以构建 Skill 的组合链路:比如 deploy Skill 内部引用 verification Skill 做 smoke test,investigation Skill 引用 data-fetching Skill 拉监控数据。虽然是隐式依赖,但在实践中模型处理得不错。
小结
Skills 体系的设计哲学其实很清晰:不要试图让模型变聪明,而是给模型正确的工具。 SKILL.md 是路由器,文件夹是工具箱,description 是触发器,hook 是质量门禁,日志是记忆。
这套体系的核心约束也很明确:一个 Skill 只做一类事,description 要写成触发条件而非摘要,verification 值得重投入。跨类 Skill、模糊 description、缺失 verification——这三个是最常见的失败模式。