1. 从一次 SQL 事故说起:Skill 到底解决什么问题
先说一个我亲身踩过的坑。团队里有个 Java 微服务,所有表都用deleted_at做软删除。某天让 AI Agent 帮忙写一个订单查询接口,它生成的 SQL 干净利落,跑起来也没报错,但上线后运营发现「已删除的订单又冒出来了」。排查半天才反应过来:Agent 根本不知道这个项目有软删除约定,它按通用 SQL 习惯写了SELECT * FROM orders WHERE user_id = ?,把标记删除的数据全带出来了。
这不是 Agent 笨,而是它缺少「项目上下文」。你可能会说,那我把它写进系统 prompt 不就行了?问题是,一个项目里这种约定可能有几十条:软删除规则、字段命名映射、响应格式、异常处理、日志规范……全塞进系统 prompt,上下文直接爆掉,而且换个项目就得重写一遍。
Skill 就是冲着这个痛点来的。一句话定义:Skill 是一套标准化的、可复用的、跨 Agent 平台共享的「知识包」,它不是一个 prompt 包装纸,而是一个自带元数据、指令正文、脚本和参考资料的完整文件夹。核心文件只有一个——SKILL.md。
它适合谁?三类人最该关注:一是天天和 AI 结对写代码、被「AI 不懂我项目」折磨的开发者;二是想把团队规范沉淀成可复用资产的技术负责人;三是已经在用 MCP、Plugin,但发现「工具有了、知识没有」的 Agent 玩家。这篇会从目录结构、触发机制讲到行为改变原理,再给一份可复制的SKILL.md模板,最后用 TaoToken 统一 Key 通道把 Agent 工具接起来,验证 Skill 是否真的生效。全程可跟做,最小 Skill 十分钟能跑通。
2. Skill、MCP、Plugin 的边界:别再问「是不是竞品」了
我在好几个技术群里看到同一个问题反复出现:「Skills 和 MCP Server 到底什么关系?是不是竞品?」答案很明确:它们是不同层面的东西,互补而非替代。理不清这个,后面写 Skill 会一直拧巴。
打个类比。Skill 是老师傅的操作手册,MCP Server 是工具箱里的新工具,Plugin 是给车装的新零件。三者回答的问题完全不同:
| 维度 | Skill | MCP Server | Plugin |
|---|---|---|---|
| 本质 | 做事的方法论 | 外部工具的接口 | 平台的扩展模块 |
| 给 Agent 什么 | 「怎么干」的 know-how | 「能调用什么」的能力 | 「多了什么功能」 |
| 格式标准 | SKILL.md(开放标准) | JSON-RPC over stdio/SSE | 各平台自定义 |
| 跨平台 | 任意兼容 Agent Skills 的平台 | 任意支持 MCP 的客户端 | 仅限特定平台 |
| 上下文开销 | 渐进式加载,极低 | 每次调用固定开销 | 取决于平台 |
具体点说。Skill 告诉你「怎么把一件事做对」,比如「写 SQL 记得加deleted_at IS NULL」「做 code review 重点看认证检查」。MCP Server 给你「能做一件新的事」,比如「去数据库查表」「往 Slack 发消息」「调 GitHub API 创建 Issue」——Agent 本来不会连外部系统,MCP 给了它那个连接。Plugin 给平台加「一个新功能模块」,比如编辑器的 GitLens、Claude Code 的 plugin marketplace。
三者可以协同:一个 Skill 里完全可以写「用 MCP Server X 去查数据库,然后按这个格式输出」。Skill 是大脑,MCP 是手,Plugin 是装备栏。所以「有了 MCP 就够了,要 Skill 干嘛」这个说法,就像「有了扳手就够了,要维修手册干嘛」——工具和知识从来不是二选一。
那 Skill 的适用边界在哪?我的经验是:凡是「跨会话、跨项目、需要反复提醒 AI 的约定」,都值得写成 Skill;凡是「一次性、强依赖具体运行时状态」的,写进对话里就行。MCP 适合封装「有状态的外部系统调用」,Plugin 适合「深度绑定某个编辑器/平台的能力」。三者别混用,混用就是给自己找麻烦。
3. 可复制配置:一个最小 Skill 的目录与 SKILL.md 模板
理论讲够了,直接上手。Skill 的目录结构长这样:
my-skill/ ├── SKILL.md # 必需:元数据 + 指令 ├── scripts/ # 可选:可执行代码 ├── references/ # 可选:参考文档 └── assets/ # 可选:模板、图片等资源核心只有SKILL.md。它用 YAML frontmatter 声明名字和触发条件,正文写清楚步骤和注意事项。一个最简单的 Skill 十行就能跑:
--- name: roll-dice description: Roll dice using a random number generator. Use when the user asks to roll a die or generate a random dice result. --- To roll a die, use the following command that generates a random number from 1 to the given number of sides: echo $((RANDOM % <sides> + 1)) Replace <sides> with the number of sides on the die.但真正有价值的是贴近生产的例子。回到开头那个软删除事故,把它写成 Skill:
--- name: java-db-query description: Write database queries for our Java project. Use when writing SQL, JPA, or MyBatis queries involving tables that use soft deletes. --- ## Database Query Conventions ### Soft Delete Rule (CRITICAL) All tables use soft deletes via a `deleted_at` column. Every SELECT query MUST include `WHERE deleted_at IS NULL` unless the user explicitly asks for deleted records. ### Gotchas - The `users` table uses `user_id` in the DB, but `uid` in the auth service. Both refer to the same value. Never confuse them. - The `/health` endpoint returns 200 even if the DB is down. Always use `/ready` for health checks. ### Example - Correct Query SELECT * FROM orders WHERE user_id = ? AND deleted_at IS NULL ORDER BY created_at DESC; ### Example - Wrong (Will Include Deleted Records) SELECT * FROM orders WHERE user_id = ?;放到项目的.claude/skills/目录下,每次 AI 写 SQL 时自动加载这些约束。有团队在 CI 里跑了 100 次 SQL 生成测试,有 Skill 的情况下正确率从 42% 提升到 91%。
这里有个大多数教程不会提的设计决策,但它是整个架构最聪明的一步:渐进式加载(Progressive Disclosure)。Skill 分三层加载:
第一层,元数据,约 100 tokens。Agent 启动时只读每个 Skill 的name和description,够它判断「这个 Skill 能不能用在这里」。第二层,指令正文,推荐小于 5000 tokens。当 Agent 判断匹配当前任务,才把完整SKILL.md加载进上下文。第三层,附属资源,按需加载。scripts/里的脚本、references/里的文档,只有实际用到才读。
这意味着什么?你可以在一个项目里放 50 个 Skill,Agent 启动时的上下文开销只比放 1 个多一点点——因为每次只加载元数据。相比之下,把 50 段说明书直接塞进系统 prompt,上下文早就爆了。这个设计让 Skill 的「可堆叠性」成为现实,也是 MCP Server 和 Plugin 做不到的。
4. 用 TaoToken 统一通道接入并验证 Skill 行为
Skill 写好了,怎么验证它真的改变了 Agent 行为?这里我用 TaoToken 做统一 Key/API 通道,把 Agent 工具接起来。TaoToken 的定位是给开发者提供统一的模型调用入口,一个 Key 走通多家模型,省去到处配环境变量的麻烦。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。
第一步,拿 Key。进控制台创建 API Key,路径在 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,Key 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。创建后复制那串sk-开头的字符串,别截图发群里。
第二步,配置 Agent 工具。以 Claude Code 这类支持自定义 Base URL 的工具为例,核心三件套是 Base URL、Key、Model ID,缺一不可:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的Key" export ANTHROPIC_MODEL="claude-sonnet-4-20250514"如果你用的是 Codex 系工具,配置写在~/.codex/auth.json里,结构大致如下:
{ "OPENAI_API_KEY": "sk-你的Key", "base_url": "https://taotoken.net/api", "model": "gpt-4o" }注意base_url不要带末尾斜杠,也不要带/v1之外的路径,具体以接入文档为准,文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。Cline 这类走 MCP 的工具,在 MCP 配置里填 Base URL 和 Key 即可,Model ID 按你实际要用的填。
第三步,验证请求通不通。先用最朴素的 curl 打一发,确认通道没问题:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "只回复两个字:通了"}] }'返回里能看到choices[0].message.content是「通了」,说明 Key 和通道都正常。这一步过了,再谈 Skill 验证。
第四步,验证 Skill 行为。把前面那个java-db-querySkill 放进项目的.claude/skills/目录,然后给 Agent 下指令:
帮我写一个查询订单列表的 SQL,按创建时间倒序。如果 Skill 生效,Agent 生成的 SQL 会自动带上WHERE deleted_at IS NULL。如果没带,说明 Skill 没被加载——先检查目录名是否全小写、SKILL.md的 frontmatter 是否合法、description是否写清楚了触发场景。我实测下来,description里明确写「Use when writing SQL」这类触发词,命中率会高很多。
想更直观地看模型对话效果,可以用模型对话页快速对比: https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。如果你打算长期跑编码 Agent、把 Skill 当团队资产沉淀,Coding Plan 会更划算,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
接入和验证过程中,报错基本集中在几个固定位置。我把踩过的坑按现象、原因、解法列出来,对照着查。
401 Unauthorized。最常见,九成是 Key 问题。先确认Authorization头是不是Bearer sk-xxx格式,别漏了Bearer和空格。再确认 Key 有没有复制全,前后有没有多余空格或换行。如果 Key 是从网页复制的,注意别把行尾的换行符带进去。还有一种情况是 Key 被禁用或额度耗尽,去控制台看一眼状态。
local proxy failed / connection refused。这个报错通常出现在你本地配了代理类工具,但代理没起来或者端口不对。先检查环境变量里有没有残留的HTTP_PROXY、HTTPS_PROXY,有的话临时清掉再试:
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY然后确认ANTHROPIC_BASE_URL或base_url填的是https://taotoken.net/api,不要多写路径、不要少写协议头。地址写错也会表现成连接失败。
reading choices 相关报错。典型的是Cannot read properties of undefined (reading 'choices'),意思是返回体里没有choices字段,代码却按有choices去解析。根因通常是请求根本没成功,返回的是错误 JSON,但客户端没检查状态码就直接取字段。排查方法:把原始返回打印出来看。如果是 curl,加-i看 HTTP 状态码;如果是代码,先判断response.ok再解析。常见触发原因是 Model ID 写错,服务端返回了错误结构。
OAuth 相关报错。如果你用的是 Claude Code 这类带 OAuth 登录流程的工具,报OAuth token expired或invalid_grant,说明它还在走官方 OAuth 通道,没切到你配的 Base URL。检查配置优先级:环境变量是否被工具自身的登录态覆盖。有些工具需要先登出官方账号,再配自定义 Base URL 才生效。这一步别偷懒,登出后重启工具。
Skill 不生效但请求正常。这种最隐蔽。请求通了、模型也回了,但 Agent 就是不带deleted_at IS NULL。按顺序查:目录名是否全小写连字符、SKILL.md是否在 Skill 根目录、frontmatter 的name和description是否都有、description是否包含触发场景关键词。我试过把description写成「数据库查询规范」,结果命中率很低;改成「Use when writing SQL, JPA, or MyBatis queries」之后立刻稳定。触发机制靠的就是这段描述,别省。
排查完这些,基本能覆盖 95% 的接入问题。剩下的边角情况,去接入文档翻一下对应章节,文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
6. 把 Skill 当资产养:从最小可用到团队规范
最后聊点实操心得。Skill 不是写一次就完事的,它的价值在于持续迭代。我的做法是:每次 Agent 犯了你想纠正的错误,就把纠正规则追加到对应 Skill 里。这是 Skill 积累价值最快的方式。
比如写完spring-api-response那个 Skill 后,Agent 还是偶尔忘记处理@Valid校验失败的情况,那就加一条 Gotcha:
### Gotchas (追加) - When using `@Valid @RequestBody`, ALWAYS add a global `@ExceptionHandler` for `MethodArgumentNotValidException` that returns `ApiResponse.error(400, fieldErrors)`. Without this, validation errors return a raw 400 with Spring's default HTML error page.这就是 Skill 开发的核心循环:发现问题 → 写成 Skill → Agent 不再犯 → 遇到新问题 → 追加规则 → 持续收敛。两周下来,你的 Agent 会比第一天聪明一大截。
几个我踩过的坑,直接给你省时间。第一,description是触发开关,不是简介,一定要写清楚「什么时候用」,包含具体技术栈和动作词。第二,一个 Skill 只干一件事,别把 SQL 规范和 API 格式塞进同一个文件,触发会互相干扰。第三,scripts/里的脚本要幂等,Agent 可能重复调用。第四,团队协作时把.claude/skills/提交进 Git,让规范跟着代码走,新人拉下来就自带上下文。
至于通道侧,统一用 TaoToken 的好处是换模型不用改代码,只改 Model ID。今天用 Claude 写 SQL,明天想换别的模型对比效果,Base URL 和 Key 都不动。长期跑编码 Agent 的话,Coding Plan 比按量更省心,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。先把最小 Skill 跑通,再慢慢往团队规范上堆,这条路我走过,稳。