Skills 生态深度拆解:当 AI Agent 决定「用 Markdown 替代 JSON-RPC」——从 Karpathy 的防坑指南到万星 Skills 仓库,一个被 10 万+ 开发者采用的新范式如何重新定义 Agent 工程化的终极形态
引言:2026 年 AI Agent 开发的范式迁移
2024 年 11 月,Anthropic 发布了 MCP(Model Context Protocol),用 JSON-RPC 定义了 AI 连接外部工具的标准协议。开发者们兴奋地搭建 MCP Server,让 AI 能读数据库、调 API、操作文件系统。
2025 年,关键词变成了 Skill。开发者发现 MCP 解决了「连接」问题,但没有解决「方法论」问题——AI 知道有哪些工具可用,却不知道拿到需求后该分几步走、每步做什么、异常怎么处理。
2026 年开年,Andrej Karpathy——OpenAI 联合创始人、Tesla 前 AI 总监——发布了 andrej-karpathy-skills 仓库,一周内突破 10 万星。这个仓库做的事情极其简单:四条行为约束,告诉 AI 编程时别「自作聪明」。
与此同时,Matt Pocock 的 mattpocock/skills 紧随其后达到 6 万+。GitHub Trending 上,Skills 相关项目连续霸榜。一个清晰的信号正在释放:AI 工作流的标准化正在从「协议层」向「知识层」迁移。
本文将深度拆解这场范式迁移的技术内核:Skills 到底是什么?它和 MCP、CLI 的本质区别在哪?Karpathy 的四条约束背后隐藏着怎样的 LLM 认知模型?一个完整的 Skills 生态应该如何构建?
第一章:理解三大范式——MCP、CLI、Skills 的本质差异
在深入 Skills 之前,我们需要先厘清 AI Agent 开发中的三大技术范式。它们不是竞争关系,而是三个不同层级的抽象。
1.1 MCP:AI 的 USB-C 接口
MCP(Model Context Protocol)是 Anthropic 在 2024 年 11 月发布的开放协议。它解决的核心问题是:AI 怎么知道有哪些工具可以用,以及怎么调用它们。
MCP 定义了三种原语:
{
"tools": [
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"inputSchema": {
"type": "object",
"properties": {
"sql": { "type": "string", "description": "SQL query to execute" }
},
"required": ["sql"]
}
}
]
}
优点:标准化、可发现、跨平台。任何 MCP Client 都能自动发现并调用任何 MCP Server 提供的工具。
致命缺陷:
- 上下文成本高:每个工具的 JSON Schema 定义会持续占用上下文窗口。一个有 50 个工具的 MCP Server,光工具定义就吃掉数千 Token
- 只管「连接」不管「方法」:AI 知道能调
query_database,但不知道拿到需求后应该先查用户表、再查订单表、最后 JOIN 关联 - 配置复杂:需要运行独立的 Server 进程,管理进程生命周期
1.2 CLI:LLM 的自然语言
CLI(Command Line Interface)是另一种被低估的范式。通过封装 API 为命令行工具,AI 可以像人类一样「执行命令」。
# AI 执行一条命令就能查数据库
gh issue list --repo owner/repo --state open --limit 10
# AI 执行一条命令就能部署
docker compose up -d
优点:
- 透明可调试:每条命令都是可审计的
- LLM 天然擅长:大模型在训练数据中见过海量 Shell 命令
- 零额外上下文:命令本身不需要 Schema 定义
局限:CLI 是原子操作,不包含业务逻辑的编排知识。
1.3 Skills:AI 的工作说明书
Skills 是 2026 年的范式突破。它不是协议,不是工具,而是结构化的 Markdown 文件,告诉 AI「遇到某类任务时,应该按什么流程执行」。
---
name: database-query
description: 当用户要求查询数据库时使用此技能
---
# 数据库查询技能
## 触发条件
用户提到「查询」「查一下」「找一下」+ 数据相关关键词
## 执行流程
1. 理解用户意图,确定查询目标
2. 检查是否有现成的查询模板可用
3. 构建 SQL 查询语句
4. 执行查询并格式化结果
5. 如果查询失败,分析错误并重试
## 异常处理
- 权限不足 → 提示用户联系管理员
- 查询超时 → 建议添加索引或优化查询
- 结果为空 → 检查拼写和条件
核心洞察:Skills 不是在「描述工具」,而是在「描述工作流程」。它是 AI 的 SOP(标准操作流程),是领域专家经验的结构化沉淀。
1.4 三者的关系
| 维度 | MCP | CLI | Skills |
|---|---|---|---|
| 核心定位 | 连接层(USB-C) | 执行层(命令行) | 知识层(工作说明书) |
| 解决的问题 | AI 能访问什么 | AI 能执行什么 | AI 应该怎么做 |
| Token 效率 | 低(Schema 常驻) | 高(按需执行) | 高(按需加载) |
| 适合场景 | 数据库、API、文件系统 | 原子操作、脚本执行 | 业务流程、领域知识 |
| 代表项目 | MCP Servers | gh, docker, kubectl | karpathy-skills |
第二章:Karpathy 的四条约束——为什么「不做什么」比「做什么」更重要
2.1 四条规则的原文
Karpathy 的 CLAUDE.md 文件包含四条核心约束:
1. 除非明确要求,否则不要创建新文件。优先编辑现有文件。
2. 除非明确要求,否则不要添加依赖。优先使用已有依赖。
3. 除非明确要求,否则不要做大规模重构。优先做最小改动。
4. 如果不确定,先问。
这四条规则看起来简单到可笑,但它们直击 LLM 编程的四大致命弱点。
2.2 规则 1:不要创建新文件——对抗「过度工程化」
LLM 有一个根深蒂固的倾向:面对任何问题,第一反应都是从头构建。
你让它修一个 bug,它会创建一个新的工具类;你让它加一个功能,它会新建三个文件、两个配置、一套全新的架构。这不是因为它「笨」,而是因为它的训练数据中,「构建新系统」的示例远多于「在现有代码中做最小改动」。
# ❌ LLM 的典型行为:创建新文件
# 用户:帮我添加一个缓存功能
# LLM 创建了:
# cache_manager.py
# cache_config.py
# cache_middleware.py
# cache_utils.py
# tests/test_cache.py
# ✅ Karpathy 约束下的行为:编辑现有文件
# 用户:帮我添加一个缓存功能
# LLM 在现有的 service.py 中添加:
import functools
def cached(ttl=300):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
cache_key = f"{func.__name__}:{hash(str(args) + str(kwargs))}"
if cache_key in _cache:
return _cache[cache_key]
result = func(*args, **kwargs)
_cache[cache_key] = result
return result
return wrapper
return decorator
本质洞察:LLM 的「创造力」在编程场景中是一把双刃剑。Karpathy 的第一条规则,本质上是在教 LLM 学会「克制」。
2.3 规则 2:不要添加依赖——对抗「依赖地狱」
每个有经验的程序员都知道:npm install 一时爽,依赖冲突火葬场。
LLM 尤其容易犯这个错误。你让它实现一个功能,它可能引入一个你从未听说过的 npm 包,这个包又依赖另外三个包,其中一个和你现有的依赖版本冲突。
// ❌ LLM 倾向于引入新依赖
{
"dependencies": {
"lodash": "^4.17.21", // 已有
"date-fns": "^3.0.0", // 新增:用来格式化日期
"dayjs": "^1.11.0", // 新增:也是日期处理
"moment": "^2.30.0" // 新增:还是日期处理
}
}
// ✅ Karpathy 约束下:用已有依赖或原生实现
// 项目已有 lodash,直接用 lodash/date-fns 其中之一
// 或者原生实现:
const formatDate = (date) => {
const d = new Date(date);
return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
};
2.4 规则 3:不要做大规模重构——对抗「架构幻觉」
LLM 有一个危险的幻觉:它认为自己比现有代码「更懂」架构。
你让它改一个函数的返回值,它可能会顺手「重构」整个模块的结构,把函数拆成三个类、引入设计模式、重写错误处理。结果就是:原来的 bug 修了,但引入了三个新 bug。
2.5 规则 4:不确定就问——对抗「过度自信」
LLM 不会说「我不知道」。它会自信地给你一个看似合理但可能完全错误的答案。第四条规则是唯一一条让 LLM 承认认知边界的约束。
第三章:SKILL.md 的架构设计——一个被忽视的工程范式
3.1 文件结构
一个标准的 Skill 目录结构如下:
.claude/skills/
database-query/
SKILL.md # 核心文件:技能定义
references/ # 可选:参考文档
schema.md # 数据库 Schema 说明
scripts/ # 可选:辅助脚本
validate_sql.py # SQL 校验脚本
templates/ # 可选:模板文件
common_queries.sql
code-review/
SKILL.md
references/
style-guide.md
3.2 SKILL.md 的格式规范
每个 SKILL.md 必须包含两个部分:
---
name: code-review
description: 当用户要求代码审查时使用此技能
---
# 代码审查技能
## 触发条件
- 用户提到「review」「审查」「看看代码」「检查一下」
- 用户提交了 PR 或 MR 的链接
- 用户粘贴了一段代码并要求评估
## 执行流程
### 第一步:理解上下文
1. 读取相关的源代码文件
2. 理解代码的业务逻辑和架构背景
3. 确定审查的侧重点(性能?安全?可读性?)
### 第二步:逐文件审查
对每个文件,按以下维度检查:
1. **正确性**:逻辑是否正确?边界条件是否处理?
2. **安全性**:是否有注入漏洞?敏感信息是否暴露?
3. **性能**:是否有 N+1 查询?是否有不必要的循环?
4. **可读性**:命名是否清晰?注释是否充分?
5. **可维护性**:是否遵循项目现有风格?
### 第三步:输出审查报告
格式:
- 🔴 严重问题(必须修复)
- 🟡 建议改进(推荐修复)
- 🟢 良好实践(值得肯定)
## 异常处理
- 代码量过大 → 分批审查,每批不超过 500 行
- 不熟悉的语言 → 声明限制,建议找对应语言专家
- 安全敏感代码 → 重点检查 OWASP Top 10
3.3 Frontmatter 的设计哲学
Frontmatter(--- 之间的 YAML 元数据)的设计是有深意的:
---
name: code-review # 唯一标识符
description: 当用户要求代码审查时使用此技能 # 触发条件描述
---
description 字段是 LLM 决定是否加载这个 Skill 的依据。它的设计原则是:
- 精确:明确说明「什么时候」该用
- 简洁:一句话说清楚,不超过 160 字符
- 排他:和其他 Skill 的描述不重叠
第四章:Skills 生态的三大流派
4.1 Karpathy 流派:行为约束型
Karpathy 的 Skills 核心是约束——告诉 AI 不做什么。这是最小化的方案,适合已经熟悉 AI 编程的高级开发者。
# Karpathy-style CLAUDE.md
1. 不要创建新文件,除非明确要求
2. 不要添加依赖,除非明确要求
3. 不要大规模重构,除非明确要求
4. 不确定就问
适用场景:个人项目、熟练团队、对 AI 行为有明确预期的场景。
4.2 Pocock 流派:工作流型
Matt Pocock 的 Skills 核心是流程——告诉 AI 遇到某类任务时按什么步骤执行。这是更完整的方案,适合需要标准化的团队。
---
name: nextjs-component
description: 创建 Next.js React 组件时使用
---
# Next.js 组件创建流程
## 前置检查
1. 确认项目使用 App Router 还是 Pages Router
2. 确认组件库(shadcn/ui、Radix、自定义)
3. 确认样式方案(Tailwind、CSS Modules、styled-components)
## 创建步骤
1. 在 components/ 目录下创建文件
2. 使用 TypeScript 定义 Props 接口
3. 导出为 default export
4. 如果是 Client Component,添加 'use client' 指令
5. 创建对应的测试文件
## 代码规范
- 使用 PascalCase 命名
- Props 接口以 Props 结尾
- 不使用 any 类型
- 组件文件不超过 200 行
4.3 社区流派:知识库型
社区中还出现了一种「知识库型」Skills——不是告诉 AI 怎么做,而是告诉 AI「我知道什么」。
---
name: project-knowledge
description: 项目的核心架构和设计决策
---
# 项目架构知识库
## 技术栈
- Runtime: Bun 1.3
- Framework: Hono
- Database: Turso (libSQL)
- ORM: Drizzle
- 部署: Cloudflare Workers
## 关键设计决策
1. 使用 Turso 而非 Neon,因为 SQLite 在边缘计算场景延迟更低
2. 使用 Hono 而非 Next.js,因为需要极致的冷启动性能
3. 所有 API 都是 RPC 风格,不使用 REST
## 代码约定
- 所有数据库操作封装在 lib/db.ts
- 错误处理统一用 AppError 类
- 日志使用 pino
第五章:实战——从零构建一个完整的 Skills 体系
5.1 项目初始化
# 创建 Skills 目录
mkdir -p .claude/skills
# 创建第一个 Skill
cat > .claude/skills/database-query/SKILL.md << 'EOF'
---
name: database-query
description: 当用户要求查询或操作数据库时使用
---
# 数据库操作技能
## 环境信息
- 数据库: Turso (libSQL)
- ORM: Drizzle ORM
- 连接配置: src/db/index.ts
## 查询流程
1. 分析用户意图,确定是查询还是写入
2. 检查 Drizzle schema 中是否有对应的表
3. 使用 Drizzle 的类型安全 API 构建查询
4. 执行查询并格式化结果
## 代码示例
\`\`\`typescript
import { db } from '@/db';
import { users, orders } from '@/db/schema';
import { eq, desc } from 'drizzle-orm';
// 查询用户
const user = await db.select().from(users).where(eq(users.id, userId));
// 查询用户的订单(带分页)
const userOrders = await db.select().from(orders)
.where(eq(orders.userId, userId))
.orderBy(desc(orders.createdAt))
.limit(10)
.offset(page * 10);
\`\`\`
## 注意事项
- 所有查询必须使用 Drizzle API,禁止拼接 SQL
- 写入操作必须在事务中执行
- 敏感字段(密码、Token)禁止出现在查询结果中
EOF
5.2 创建代码审查 Skill
cat > .claude/skills/code-review/SKILL.md << 'EOF'
---
name: code-review
description: 当用户要求代码审查或提交 PR 时使用
---
# 代码审查技能
## 审查清单
### 安全性(最高优先级)
- [ ] 无 SQL 注入风险
- [ ] 无 XSS 漏洞
- [ ] 敏感信息未硬编码
- [ ] API Key 未暴露在前端
### 正确性
- [ ] 边界条件已处理
- [ ] 错误处理完善
- [ ] 并发安全
### 性能
- [ ] 无 N+1 查询
- [ ] 无不必要的重渲染
- [ ] 大数据集使用分页
### 可维护性
- [ ] 命名清晰
- [ ] 函数职责单一
- [ ] 代码重复度低
## 输出格式
🔴 **必须修复** [文件:行号] 问题描述
🟡 **建议改进** [文件:行号] 问题描述
🟢 **良好实践** [文件:行号] 亮点描述
EOF
5.3 Skills 的加载机制
Skills 的加载是按需的、懒加载的。LLM 在处理用户请求时,会先扫描所有 Skill 的 description,判断哪个 Skill 与当前任务相关,然后只加载那个 Skill 的完整内容。
用户请求: "帮我查一下最近7天的订单"
LLM 内部流程:
1. 扫描所有 Skill 的 description
2. 匹配到 "database-query" (关键词: 查询, 数据库)
3. 加载 database-query/SKILL.md 的完整内容
4. 按照 Skill 中定义的流程执行
这种设计的优势在于 Token 效率:
- MCP:50 个工具的 Schema 常驻上下文,约 5000 Token
- Skills:100 个 Skill 的 description 索引,约 2000 Token;实际执行时只加载 1 个 Skill,约 500 Token
第六章:Skills 与 MCP 的协同——不是替代,而是互补
6.1 最佳实践架构
用户请求
↓
Agent(决策层)
├── Skills(知识层)→ 告诉 Agent 应该怎么做
├── MCP(连接层)→ 告诉 Agent 有哪些工具可用
└── CLI(执行层)→ Agent 执行具体命令
一个完整的 AI Agent 系统应该同时使用三者:
# .claude/settings.json
{
"mcpServers": {
"database": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sqlite", "./data.db"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]
}
}
}
# .claude/skills/database-query/SKILL.md
# → 当需要查数据库时,按此流程执行
# → 实际调用 MCP 的 database server 执行查询
6.2 Token 预算管理
在生产环境中,Token 预算是核心约束。推荐的分层策略:
┌─────────────────────────────────────────┐
│ System Prompt + CLAUDE.md │ ~2000 Token(常驻)
├─────────────────────────────────────────┤
│ Skill Descriptions Index │ ~1000 Token(常驻)
├─────────────────────────────────────────┤
│ MCP Tool Schemas(精简版) │ ~1500 Token(常驻)
├─────────────────────────────────────────┤
│ Active Skill Content │ ~500 Token(按需加载)
├─────────────────────────────────────────┤
│ Conversation History │ 动态
├─────────────────────────────────────────┤
│ Reserved for Response │ ~4000 Token
└─────────────────────────────────────────┘
第七章:生产级 Skills 的工程化实践
7.1 Skills 的版本管理
Skills 应该纳入 Git 版本控制,但需要区分「个人 Skills」和「团队 Skills」:
# 个人 Skills(不提交)
.claude/skills/local-debugging/
# 团队 Skills(提交到仓库)
.claude/skills/
code-review/ # 团队共用
api-design/ # 团队共用
deployment/ # 团队共用
7.2 Skills 的测试
Skills 也可以测试——通过模拟用户请求,验证 AI 是否按照 Skill 定义的流程执行:
// tests/skills.test.ts
import { testSkill } from '@anthropic/testing';
test('database-query skill handles basic query', async () => {
const result = await testSkill('database-query', {
request: '帮我查一下最近7天的订单',
mockTools: {
query_database: jest.fn().mockResolvedValue([])
}
});
// 验证 AI 按照 Skill 流程执行
expect(result.steps).toEqual([
'理解用户意图',
'检查 Drizzle schema',
'构建查询',
'执行查询'
]);
});
7.3 Skills 的分发
Skills 可以通过多种方式分发:
- Git 仓库:团队内部通过 Git 共享
- npm 包:发布为
@org/skills-xxx包 - Skill Hub:社区驱动的 Skills 市场
- 项目模板:作为项目脚手架的一部分
第八章:2026 年 Skills 生态全景
8.1 头部项目
| 项目 | Stars | 定位 | 语言 |
|---|---|---|---|
| karpathy-skills | 129K+ | 行为约束型 CLAUDE.md | Markdown |
| mattpocock/skills | 60K+ | 工作流型 Skills 集合 | Markdown |
| openclaw-skills | - | Agent Skills 平台 | TypeScript |
| codegen.com | - | Skills 目录和搜索引擎 | TypeScript |
8.2 Skills 的未来方向
- Skills 市场:类似于 npm 的 Skills 分发平台
- Skills 组合:像搭积木一样组合多个 Skills
- Skills 进化:AI 根据执行结果自动优化 Skill 定义
- 跨 Agent 互操作:不同 Agent 框架共享同一套 Skills
总结:从「连接一切」到「理解一切」
MCP 解决了 AI「能做什么」的问题,Skills 解决了 AI「该怎么做」的问题。
2026 年的 AI Agent 开发,正在经历从「协议驱动」到「知识驱动」的范式迁移。Karpathy 的四条约束看似简单,却道出了 LLM 编程的本质:AI 最需要的不是更多工具,而是更好的判断力。
Skills 就是这种判断力的结构化载体。它不是提示词的花哨包装,而是领域专家经验的可执行沉淀。当 Skills 生态成熟时,每个开发者都能站在前人的肩膀上,让 AI 不仅「能做事」,更能「做对事」。
这场迁移才刚刚开始。而你,已经站在了浪潮的起点。
参考资源
- Karpathy Skills 仓库:https://github.com/anthropics/andrej-karpathy-skills
- Matt Pocock Skills:https://github.com/mattpocock/skills
- MCP 官方文档:https://modelcontextprotocol.io
- Claude Code Skills 文档:https://docs.anthropic.com/en/docs/claude-code/skills
- Codegen.com Skills 目录:https://www.codegen.com