Init
This commit is contained in:
+380
@@ -0,0 +1,380 @@
|
||||
---
|
||||
tags: [mcp, ai-development, protocol, llm-tools]
|
||||
create time: 2026-04-30 14:30
|
||||
---
|
||||
|
||||
# MCP — 模型上下文协议
|
||||
|
||||
## 概述
|
||||
|
||||
**Model Context Protocol (MCP)** 是由 Anthropic 开源的开放协议,为 AI 模型与外部数据源、工具之间提供标准化的通信接口。它让大语言模型能够安全、可控地访问文件系统、API、数据库等外部资源,是构建 AI Agent 基础设施的关键组件。
|
||||
|
||||
> [!question] 为什么需要 MCP?
|
||||
> 在 MCP 出现之前,每个 AI 应用集成新数据源都需要写自定义代码——GitHub 一个接口、Slack 一个接口、公司内部 API 又一个接口。MCP 用一套统一协议解决了"重复造轮子"的问题:定义一次 Server,所有兼容 MCP 的 Client 都能使用。
|
||||
|
||||
---
|
||||
|
||||
## 核心架构
|
||||
|
||||
MCP 采用 **Client-Server** 架构,通过 JSON-RPC 2.0 进行通信:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph client["MCP Client(宿主应用)"]
|
||||
C1["Claude Desktop"]
|
||||
C2["Cursor / IDE"]
|
||||
C3["自建应用"]
|
||||
end
|
||||
|
||||
subgraph mcp_layer["MCP 协议层\n(JSON-RPC 2.0)"]
|
||||
P1["Tools\n工具调用"]
|
||||
P2["Resources\n数据读取"]
|
||||
P3["Prompts\n模板预设"]
|
||||
P4["Sampling\n子模型调用"]
|
||||
end
|
||||
|
||||
subgraph server["MCP Server(能力提供者)"]
|
||||
S1["文件系统 Server"]
|
||||
S2["GitHub Server"]
|
||||
S3["数据库 Server"]
|
||||
S4["自定义 Server"]
|
||||
end
|
||||
|
||||
C1 <-->|"stdio / SSE"| P1
|
||||
C1 <-->|"stdio / SSE"| P2
|
||||
C1 <-->|"stdio / SSE"| P3
|
||||
C2 <-->|"stdio / SSE"| P4
|
||||
C3 <-->|"HTTP SSE"| P1
|
||||
|
||||
P1 --> S1
|
||||
P1 --> S2
|
||||
P2 --> S3
|
||||
P2 --> S4
|
||||
P3 --> S1
|
||||
P4 --> S2
|
||||
|
||||
style client fill:#e8f5e9
|
||||
style mcp_layer fill:#fff3e0
|
||||
style server fill:#e3f2fd
|
||||
```
|
||||
|
||||
**三个核心角色:**
|
||||
|
||||
| 角色 | 职责 | 类比 |
|
||||
|------|------|------|
|
||||
| **Client** | 发起请求,连接 Server,将能力提供给 AI 模型 | "插件管理器" |
|
||||
| **Server** | 暴露 Tools、Resources、Prompts 等能力 | "插件实现" |
|
||||
| **Protocol** | 定义 JSON-RPC 通信格式和消息类型 | "USB 接口标准" |
|
||||
|
||||
> [!tip] 关键理解
|
||||
> MCP **不是**另一个 LLM 框架或 SDK,它是一个**通信协议**。类似 HTTP 之于 Web 开发——你不需要"学 HTTP 框架",只需要知道如何发起请求和响应。MCP 同理,Server 和 Client 各自用 JSON-RPC 说话。
|
||||
|
||||
---
|
||||
|
||||
## 三种核心能力
|
||||
|
||||
### 1. Tools — 让 AI 执行操作
|
||||
|
||||
Tools 允许 AI 模型调用函数并获取结果,是 MCP 最常用的能力类型。
|
||||
|
||||
```go
|
||||
// Go 实现:注册一个「查询天气」Tool
|
||||
server.AddTool(mcp.Tool{Name: "get_weather", Description: "查询指定地点的天气"},
|
||||
func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
city := req.Arguments["city"].(string)
|
||||
weather := queryWeather(city) // 调用实际业务逻辑
|
||||
return mcp.SuccessResult(mcp.TextContent(weather)), nil
|
||||
})
|
||||
```
|
||||
|
||||
客户端调用流程:
|
||||
|
||||
```go
|
||||
// Client 侧发起 Tool 调用
|
||||
result, err := client.CallTool(ctx, "get_weather", map[string]any{
|
||||
"city": "Beijing",
|
||||
})
|
||||
```
|
||||
|
||||
**典型场景:** 搜索代码仓库、创建 GitHub Issue、发送 Slack 消息、执行数据库查询。
|
||||
|
||||
### 2. Resources — 让 AI 读取数据
|
||||
|
||||
Resources 提供结构化的只读数据访问,AI 可以根据 URI 按需读取:
|
||||
|
||||
```go
|
||||
// 注册一个 Resource Template(支持参数化 URI)
|
||||
server.AddResourceTemplate(
|
||||
mcp.ResourceTemplate{URI: "repo://{owner}/{repo}/file/{path}", Name: "Repository File"},
|
||||
func(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
|
||||
// 根据 URI 参数读取文件内容
|
||||
content := readFile(req.Arguments["path"].(string))
|
||||
return mcp.SuccessResult(mcp.TextContent(content)), nil
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
AI 可以通过 `repo://anthropic/claude-docs/file/README.md` 这样的 URI 读取任意仓库文件。
|
||||
|
||||
### 3. Prompts — 可复用的对话模板
|
||||
|
||||
Prompts 允许 Server 预定义结构化提示词模板,Client 加载后自动注入上下文:
|
||||
|
||||
```go
|
||||
server.AddPrompt(mcp.Prompt{Name: "code_review", Description: "代码审查模板"},
|
||||
func(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
|
||||
diff := req.Arguments["diff"].(string)
|
||||
return &mcp.GetPromptResult{
|
||||
Messages: []mcp.PromptMessage{{
|
||||
Role: mcp.RoleUser,
|
||||
Content: mcp.TextContent(fmt.Sprintf(`请审查以下代码变更:
|
||||
|
||||
%s
|
||||
|
||||
重点关注:安全性、性能、可读性。`, diff)),
|
||||
}},
|
||||
}, nil
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 传输层:连接 Client 与 Server
|
||||
|
||||
MCP 支持两种传输方式,覆盖从本地到云端的完整场景:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph stdio_transport["本地进程通信"]
|
||||
A["Local MCP Server"] -->|stdin/stdout| B[Host Application]
|
||||
end
|
||||
|
||||
subgraph sse_transport["网络通信"]
|
||||
C["Remote MCP Server"] -->|HTTP POST| D[SSE Endpoint]
|
||||
D -->|Event Stream| E[Client App]
|
||||
end
|
||||
|
||||
style stdio_transport fill:#e8f5e9
|
||||
style sse_transport fill:#e3f2fd
|
||||
```
|
||||
|
||||
| 传输方式 | 适用场景 | 特点 |
|
||||
|----------|----------|------|
|
||||
| **stdio** | 本地运行的 Server | 零配置,通过标准输入输出通信,适合命令行工具和本地集成 |
|
||||
| **SSE (Server-Sent Events)** | 远程 Server | 通过 HTTP 端口暴露,适合云端服务和多客户端共享 |
|
||||
|
||||
> [!note] 底层原理
|
||||
> 无论哪种传输方式,上层使用的都是相同的 **JSON-RPC 2.0** 消息格式。传输层仅负责"把消息送到对方手里",不关心内容语义。
|
||||
|
||||
---
|
||||
|
||||
## JSON-RPC 消息格式
|
||||
|
||||
MCP 基于 JSON-RPC 2.0,消息结构简洁直观:
|
||||
|
||||
**初始化握手(Initialize):**
|
||||
|
||||
```json
|
||||
// Client → Server
|
||||
{"jsonrpc":"2.0","id":1,"method":"initialize",
|
||||
"params":{"protocolVersion":"2024-11-05","capabilities":{"tools":{},"resources":{}},"clientInfo":{"name":"my-client","version":"1.0.0"}}}
|
||||
|
||||
// Server → Client 响应
|
||||
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{},"resources":{}},"serverInfo":{"name":"weather-server","version":"1.0.0"}}}
|
||||
```
|
||||
|
||||
**列出可用 Tools:**
|
||||
|
||||
```json
|
||||
// Client → Server
|
||||
{"jsonrpc":"2.0","method":"tools/list","id":2}
|
||||
|
||||
// Server → Client
|
||||
{"jsonrpc":"2.0","result":{"tools":[{"name":"get_weather","description":"查询天气","inputSchema":{"type":"object","properties":{"city":{"type":"string"}}}}]}}
|
||||
```
|
||||
|
||||
**调用 Tool:**
|
||||
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"tools/call","id":3,"params":{"name":"get_weather","arguments":{"city":"Tokyo"}}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 实战:从零搭建 MCP Server
|
||||
|
||||
以下是一个完整的 Go 实现示例,演示创建一个简单 MCP Server 的最小路径:
|
||||
|
||||
### Step 1:初始化项目
|
||||
|
||||
```bash
|
||||
mkdir mcp-weather-server && cd mcp-weather-server
|
||||
go mod init mcp-weather-server
|
||||
go get github.com/modelcontextprotocol/go-sdk/mcp
|
||||
```
|
||||
|
||||
### Step 2:编写 Server 代码
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 创建 Stdio 传输(本地模式)
|
||||
transport := mcp.NewStdioTransport()
|
||||
|
||||
// 创建 Server 实例
|
||||
server := mcp.NewServer(&mcp.ServerInfo{Name: "weather-server", Version: "1.0.0"})
|
||||
|
||||
// 注册 Tool:查询天气
|
||||
server.AddTool(mcp.Tool{
|
||||
Name: "get_weather",
|
||||
Description: "Query weather for a given city",
|
||||
InputSchema: map[string]any{
|
||||
"type": "object",
|
||||
"properties": map[string]any{"city": map[string]string{"type": "string"}},
|
||||
"required": []string{"city"},
|
||||
},
|
||||
}, handleGetWeather)
|
||||
|
||||
// 启动服务
|
||||
if err := server.Run(context.Background(), transport); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理天气查询的核心逻辑
|
||||
func handleGetWeather(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
|
||||
city := req.Arguments["city"].(string)
|
||||
|
||||
// 此处接入真实天气 API
|
||||
response := fetchFromOpenWeather(city)
|
||||
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{mcp.TextContent(response)},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func fetchFromOpenWeather(city string) string {
|
||||
// TODO: 调用 OpenWeatherMap API
|
||||
return fmt.Sprintf("City %s: Sunny, 23°C", city)
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3:配置 Claude Desktop 使用
|
||||
|
||||
在 Claude Desktop 的配置文件中添加 Server:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"weather": {
|
||||
"command": "go",
|
||||
"args": ["run", "/path/to/mcp-weather-server"],
|
||||
"transport": "stdio"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4:验证效果
|
||||
|
||||
启动 Claude Desktop 后,在对话中直接告诉 AI "帮我查一下北京的天气",AI 会自动识别调用 `get_weather` Tool。
|
||||
|
||||
> [!abstract] 代码说明
|
||||
> 以上代码展示了 MCP Server 的三个核心步骤:**创建 Server → 注册 Tool → 启动传输**。实际项目中只需替换 `handleGetWeather` 中的业务逻辑即可。
|
||||
|
||||
---
|
||||
|
||||
## 常见开源 MCP Server 参考
|
||||
|
||||
| Server | 用途 | 技术栈 |
|
||||
|--------|------|--------|
|
||||
| **Filesystem** | 读写本地文件系统 | TypeScript |
|
||||
| **GitHub** | Issue/PR/Code Search | TypeScript |
|
||||
| **PostgreSQL** | 数据库查询 | Python |
|
||||
| **GitLab** | GitLab 项目管理 | TypeScript |
|
||||
| **Slack** | 消息收发 | Python |
|
||||
| **Memory** | 向量存储的知识库 | TypeScript |
|
||||
|
||||
这些参考实现在 MCP 官方仓库的 `servers` 目录下,可以直接编译运行或二次开发。
|
||||
|
||||
---
|
||||
|
||||
## 安全考虑
|
||||
|
||||
MCP 的设计将权限控制交给了 Host Application(宿主应用),这带来了灵活性的同时也需要注意安全风险:
|
||||
|
||||
> [!warning] 安全最佳实践
|
||||
> - **沙箱隔离**:对 Server 的文件/网络访问权限进行限制,避免恶意 Server 读写敏感数据
|
||||
> - **权限最小化**:只授予 Server 完成工作所需的最小权限集
|
||||
> - **审计日志**:记录所有 Tool 调用和 Resource 访问,便于追踪异常行为
|
||||
> - **用户确认**:对破坏性操作(删除、修改)应在 AI 执行前请求用户确认
|
||||
> - **依赖安全**:检查 Server 的代码依赖,防止供应链攻击
|
||||
|
||||
---
|
||||
|
||||
## MCP 与相关技术的关系
|
||||
|
||||
```mermaid
|
||||
quadrantChart
|
||||
title AI 集成生态中的位置
|
||||
x-axis "专用集成" --> "通用协议"
|
||||
y-axis "运行时绑定" --> "标准化抽象"
|
||||
"Custom Integrations": [0.15, 0.1]
|
||||
"OpenAI Function Calling": [0.3, 0.2]
|
||||
"LangChain Tools": [0.25, 0.15]
|
||||
"MCP": [0.7, 0.75]
|
||||
"REST APIs": [0.85, 0.85]
|
||||
"gRPC": [0.8, 0.9]
|
||||
```
|
||||
|
||||
**核心区别:**
|
||||
|
||||
| 对比维度 | Function Calling | MCP |
|
||||
|----------|------------------|-----|
|
||||
| **作用域** | LLM API 内部的能力调用机制 | 跨应用的独立通信协议 |
|
||||
| **可复用性** | 每次调用需重新定义 function deffinition | 一次部署,所有兼容 Client 共享 |
|
||||
| **生命周期** | 单次请求内有效 | 持久运行的独立进程 |
|
||||
| **生态位** | "LLM 怎么调用函数" | "应用之间怎么交换能力和数据" |
|
||||
|
||||
> [!note] 两者可以共存
|
||||
> MCP Server 内部仍然可以使用 Function Calling 调用的方式与 LLM 交互。MCP 解决的是"应用层面的互操作",Function Calling 解决的是"模型层面的函数感知"——二者在不同层级工作。
|
||||
|
||||
---
|
||||
|
||||
## 本章小结
|
||||
|
||||
| 概念 | 定位 | 一句话理解 |
|
||||
|------|------|-----------|
|
||||
| **Tools** | 操作型能力 | 让 AI "动手做事" |
|
||||
| **Resources** | 数据型能力 | 让 AI "读取数据" |
|
||||
| **Prompts** | 模板型能力 | 让 AI "复用话术" |
|
||||
| **stdio 传输** | 本地通信 | 进程间 stdin/stdout |
|
||||
| **SSE 传输** | 网络通信 | HTTP 流式推送 |
|
||||
| **JSON-RPC 2.0** | 消息协议 | 统一的请求-响应格式 |
|
||||
|
||||
> [!success] 学习成果
|
||||
> 完成本章后,你应该能够:
|
||||
> - 理解 MCP 的 Client-Server 架构和工作原理
|
||||
> - 区分 Tools、Resources、Prompts 三种核心能力的不同场景
|
||||
> - 具备从零搭建一个 MCP Server 的能力
|
||||
> - 了解 MCP 与传统 Function Calling 的关系与差异
|
||||
|
||||
---
|
||||
|
||||
## 扩展阅读
|
||||
|
||||
- MCP 官方规范:https://modelcontextprotocol.io/specification
|
||||
- Go SDK 文档:https://github.com/modelcontextprotocol/go-sdk
|
||||
- TypeScript SDK 文档:https://github.com/modelcontextprotocol/sdk
|
||||
- 官方参考 Server:https://github.com/modelcontextprotocol/servers
|
||||
|
||||
## 关联笔记
|
||||
@@ -0,0 +1,767 @@
|
||||
---
|
||||
tags:
|
||||
- Skill
|
||||
- Agent
|
||||
- 自动化
|
||||
create time: 2026-05-03 15:30
|
||||
---
|
||||
|
||||
# 怎么创建一个自己的 CLAUDE CODE SKILL
|
||||
|
||||
## 概述
|
||||
|
||||
本文系统梳理 Claude Code(原 Claude Desktop / Anthropic SDK)的 **Agent Skill** 概念、定义语法、开发工作流和最佳实践,并通过多个实战场景案例帮助读者从零创建属于自己的可复用 AI 助手技能。
|
||||
|
||||
> [!QUESTION] 💡 思考
|
||||
> 你是否有过这样的场景——反复向 AI 助手解释同样的上下文、规则或约束,才能让它按你的预期完成工作?Skill 机制正是为了解决这个问题而生的:将"重复教育"变成一键加载的「能力插件」。
|
||||
|
||||
## 什么是 Agent Skill
|
||||
|
||||
### 核心概念
|
||||
|
||||
Agent Skill 是 Anthropic 提供的一种 **结构化指令注入机制**。它允许开发者/用户通过 YAML 格式的 skill definition,在不修改模型权重的前提下,向 Claude 注入特定的行为规则、知识框架和工具调用策略。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
U["用户提示词\nFix the auth bug"] --> S{"Claude 模型"}
|
||||
|
||||
subgraph Context ["Skill Context 注入层"]
|
||||
direction TB
|
||||
T["Trigger: trigger(auth)"]
|
||||
R["Rules: System Prompt"]
|
||||
C["Constraints: Tool Limits"]
|
||||
end
|
||||
|
||||
S --> Context
|
||||
Context --> S
|
||||
|
||||
S --> O["专精行为输出\nSecurity Review / Config Update / etc."]
|
||||
|
||||
classDef normal fill:#e3f2fd,stroke:#1565c0
|
||||
classDef highlight fill:#fff3e0,stroke:#ef6c00
|
||||
class U,O normal
|
||||
class T,R,C highlight
|
||||
```
|
||||
|
||||
### Skill vs 普通 Prompt vs Project Instructions
|
||||
|
||||
| 维度 | 普通 Prompt | CLAUDE.md (Project Instructions) | Agent Skill |
|
||||
|------|------------|----------------------------------|-------------|
|
||||
| **粒度** | 单次对话级别 | 整个 workspace 级别 | 特定任务域级别 |
|
||||
| **触发方式** | 必须明确提及 | 始终生效 | 自动检测触发 / 手动 `@` 调用 |
|
||||
| **作用范围** | 不持久化 | 全局覆盖 | 按需挂载,不影响其他任务 |
|
||||
| **复杂度** | 简单 | 中等 | 高(含系统级指令注入) |
|
||||
| **典型用例** | 快速提问 | 编码规范、语言偏好 | 安全审计、配置管理、代码审查 |
|
||||
|
||||
> [!NOTE] 🔑 关键区别
|
||||
> - **CLAUDE.md** 是你的"项目宪法",适用于所有对话
|
||||
> - **Skill** 是你的"专业技能包",在特定场景下挂载到对话上,提供更深层的行为控制
|
||||
> - 两者可以共存 —— Skill 中的指令仅在 skill 激活时生效,优先级高于 CLAUDE.md
|
||||
|
||||
### 内置 Skill 一览
|
||||
|
||||
Claude Code SDK 自带一组开箱即用的 Skill,理解它们是学习自定义 Skill 的最佳起点:
|
||||
|
||||
| Skill | 功能 | 触发条件 |
|
||||
|-------|------|---------|
|
||||
| `update-config` | 修改 settings.json、管理权限和环境变量 | 涉及配置文件、hook、权限变更 |
|
||||
| `keybindings-help` | 定制键盘快捷键 | 用户询问快捷键相关 |
|
||||
| `simplify` | 审查并重用冗余代码 | 代码审查场景 |
|
||||
| `fewer-permission-prompts` | 扫描代码,生成 `.claude/settings.json` 的 allowlist | 请求减少权限提示时 |
|
||||
| `loop` | 运行定时/循环任务(如 `/loop 5m /foo`) | 用户要求周期性任务 |
|
||||
| `claude-api` | 构建和优化 Claude API 应用(含缓存策略) | 导入 anthropic SDK、问 API/模型相关问题 |
|
||||
| `init` | 初始化新的 CLAUDE.md | 新项目初始化 |
|
||||
| `review` | 审查 Pull Request | PR 审查请求 |
|
||||
| `security-review` | 安全审查当前分支变更 | 安全审查请求 |
|
||||
|
||||
## Skill 定义语法详解
|
||||
|
||||
### YAML Frontmatter 结构
|
||||
|
||||
每个 Skill 通过 YAML frontmatter 定义其元数据和触发逻辑:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: security-review
|
||||
description: Complete a security review of the pending changes on the current branch
|
||||
---
|
||||
```
|
||||
|
||||
一个完整的核心字段表:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `name` | ✅ | Skill 的唯一标识符(kebab-case) |
|
||||
| `description` | ✅ | 简短描述,用于匹配用户意图 |
|
||||
| `trigger` | ❌ | 何时自动激活(正则表达式) |
|
||||
| `skip` | ❌ | 什么情况下跳过该 Skill |
|
||||
| `tools` | ❌ | Skill 可用的工具白名单 |
|
||||
| `systemPrompt` | ❌ | 注入的系统级指令(核心内容区) |
|
||||
|
||||
### Trigger 模式匹配
|
||||
|
||||
Trigger 决定了 Skill 在什么情况下被自动激活。支持以下模式:
|
||||
|
||||
```yaml
|
||||
trigger: "code imports .anthropic. or @anthropic-ai/sdk."
|
||||
trigger: 'filename like \*-openai.py/.*-generic\.py'
|
||||
trigger: "/loop"
|
||||
```
|
||||
|
||||
常见的触发方式:
|
||||
|
||||
| 方式 | 示例 | 适用场景 |
|
||||
| ----------- | -------------------------------- | ---------------- |
|
||||
| **关键词匹配** | `trigger: "send email"` | 功能明确的任务 |
|
||||
| **文件路径匹配** | `trigger: "\.secrets\.""` | 特定文件或目录变更时 |
|
||||
| **命令前缀** | `trigger: "/deploy"` | Slash Command 触发 |
|
||||
| **正则表达式** | `trigger: "imports .anthropic."` | 复杂模式匹配 |
|
||||
| **手动 @ 引用** | `@my-skill` | 用户主动调用 |
|
||||
|
||||
> [!TIP] ⚡ 最佳实践
|
||||
> Trigger 要尽可能精确。过于宽泛会导致错误的 Skill 被激活,干扰正常对话。遵循 **"最小充分原则"**:用最少的匹配条件覆盖目标场景。
|
||||
|
||||
## Skill 开发工作流
|
||||
|
||||
### Step 1: 确定需求边界
|
||||
|
||||
> [!QUESTION] 🧭 先问自己
|
||||
>
|
||||
> 1. 这个 Skill 解决的是 **一次性问题** 还是 **反复出现的需求**?
|
||||
> - 一次性 → 直接写 prompt
|
||||
> - 反复出现 → 考虑做成 Skill
|
||||
>
|
||||
> 2. 这个 Skill 的规则能否用 **明确的 trigger + system prompt** 表达?
|
||||
> - 能 → 适合做成 Skill
|
||||
> - 不能 → 可能需要更复杂的 Agent 类型
|
||||
>
|
||||
> 3. 这个 Skill 会和其他 Skill **冲突**吗?
|
||||
> - 检查已有 Skill 的 trigger,避免重叠
|
||||
|
||||
### Step 2: 编写 Skill Definition
|
||||
|
||||
一个典型的 Skill 定义放在项目的 `.claude/skills/<skill-name>/SKILL.md` 文件中:
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-cool-skill
|
||||
description: Help with X when Y happens
|
||||
trigger: "X scenario appears"
|
||||
---
|
||||
|
||||
# My Cool Skill
|
||||
|
||||
When this skill is active, follow these rules:
|
||||
|
||||
## Rules
|
||||
1. Rule one...
|
||||
2. Rule two...
|
||||
|
||||
## Workflow
|
||||
Step-by-step instructions for Claude to follow.
|
||||
|
||||
## Examples
|
||||
Concrete examples showing expected behavior.
|
||||
```
|
||||
|
||||
### Step 3: 测试与迭代
|
||||
|
||||
| 阶段 | 操作 | 目的 |
|
||||
|------|------|-----|
|
||||
| **单元测试** | 针对单个触发场景验证 | 确认 trigger 正确匹配 |
|
||||
| **集成测试** | 模拟真实用户输入 | 观察 Skill 是否正确激活 |
|
||||
| **负样本测试** | 用不应触发的输入测试 | 防止误触发 |
|
||||
| **冲突检查** | 同时存在多 Skill 时测试 | 确保无歧义匹配 |
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### ✅ Do's
|
||||
|
||||
> [!SUCCESS] 推荐做法
|
||||
|
||||
**1. 职责单一原则(Single Responsibility)**
|
||||
|
||||
每个 Skill 只负责一个明确的领域。不要试图在一个 Skill 里塞入所有邮件发送逻辑。拆分为独立的 Skill:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Root["skills/"] --> A["send-email-report/\n发送邮件报告"]
|
||||
Root --> B["generate-changelog/\n生成 Changelog"]
|
||||
Root --> C["notify-team/\n团队通知"]
|
||||
|
||||
classDef folder fill:#e8f5e9,stroke:#2e7d32
|
||||
classDef item fill:#fff3e0,stroke:#ef6c00
|
||||
class Root folder
|
||||
class A,B,C item
|
||||
```
|
||||
|
||||
**2. System Prompt 要明确且封闭**
|
||||
|
||||
```yaml
|
||||
# good — 明确的正面指令 + 负面约束
|
||||
## Rules
|
||||
- ALWAYS use the smtp.send() helper from utils/email.py
|
||||
- NEVER hardcode credentials; always use os.getenv()
|
||||
- After sending, log the message ID to the database
|
||||
- If SMTP fails, queue the email and retry in 5 minutes
|
||||
|
||||
# bad — 模糊、开放式的描述
|
||||
## Notes
|
||||
You can send emails however you think is best, just make sure it works.
|
||||
```
|
||||
|
||||
**3. Trigger 要精确且有排他性**
|
||||
|
||||
```yaml
|
||||
# good — 具体的文件名 + 动作组合
|
||||
trigger: "user asks to review .migrations/ or changes to schema files"
|
||||
|
||||
# bad — 太宽泛
|
||||
trigger: "database"
|
||||
```
|
||||
|
||||
**4. 包含错误处理路径**
|
||||
|
||||
优秀的 Skill 不是只在理想情况下工作,还要定义失败时的行为:
|
||||
|
||||
```markdown
|
||||
## Error Handling
|
||||
- If the required config file is missing: create a template and ask the user to fill it in
|
||||
- If the API returns 429: implement exponential backoff (initial: 1s, max: 30s)
|
||||
- If the recipient list is empty: abort with an informative error message
|
||||
```
|
||||
|
||||
### ❌ Don'ts
|
||||
|
||||
> [!WARNING] ⚠️ 常见陷阱
|
||||
|
||||
**1. 过度依赖 Skill 解决简单问题**
|
||||
|
||||
如果只是一个简单的 `git commit` 封装,不需要写成 Skill。Skill 适合 **复杂、多步骤、有严格规则** 的场景。
|
||||
|
||||
**2. Trigger 相互冲突**
|
||||
|
||||
两个 Skill 的 trigger 匹配同一个输入时,行为不可预测:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Input["用户说: fix auth bug"] --> SkillA["Skill A\ntrigger: fix the bug in auth"]
|
||||
Input --> SkillB["Skill B\ntrigger: fix authentication bug"]
|
||||
|
||||
classDef input fill:#e3f2fd,stroke:#1565c0
|
||||
classDef conflict fill:#f9d0c4,stroke:#d84315
|
||||
class Input input
|
||||
class SkillA,SkillB conflict
|
||||
```
|
||||
|
||||
**3. 在 Skill 中硬编码敏感信息**
|
||||
|
||||
绝对不要在 system prompt 中写入密码、API Key、URL 等。使用环境变量或配置文件引用:
|
||||
|
||||
```markdown
|
||||
❌ BAD:
|
||||
Always use password = "mySuperSecret123!" at host smtp.example.com
|
||||
|
||||
✅ GOOD:
|
||||
Use credentials from ENV vars EMAIL_USER and EMAIL_PASS
|
||||
```
|
||||
|
||||
**4. 忽略性能影响**
|
||||
|
||||
过长的 system prompt 会增加 token 消耗和响应延迟。保持精简,只注入必要的上下文。
|
||||
|
||||
## 实战场景案例集
|
||||
|
||||
下面通过四个不同难度级别的实战场景,展示如何从需求到完整的 Skill 定义。
|
||||
|
||||
### 场景一:中间件集成的最佳编码实践(入门级)
|
||||
|
||||
**需求**: 当检测到项目中引入 Redis/MQ 等中间件时,自动注入最佳实践指导。
|
||||
|
||||
> [!QUESTION] 🤔 为什么需要这个 Skill?
|
||||
> 每次引入新中间件,你都需要告诉 AI:"记得连接池、超时设置、重试策略..." —— 这正是 Skill 的用武之地。
|
||||
|
||||
#### Skill 定义
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: redis-best-practices
|
||||
description: Guide proper Redis integration patterns when Redis-related code is detected
|
||||
trigger: "redis OR redigo OR go-redis OR ioredis OR Lettuce"
|
||||
---
|
||||
|
||||
# Redis Integration Best Practices
|
||||
|
||||
## Overview
|
||||
This skill activates when Redis-related imports or configuration appear in the codebase.
|
||||
It ensures the assistant guides the developer through production-ready patterns.
|
||||
|
||||
## Core Principles
|
||||
|
||||
> [!INFO] 三大基石
|
||||
> 1. **资源管理**: 连接必须复用,禁止每次请求新建连接
|
||||
> 2. **容错设计**: 网络异常必须有降级方案,Redis 不可用时服务不能完全崩溃
|
||||
> 3. **数据安全**: 敏感数据不能明文存储,大 value 要考虑内存水位
|
||||
|
||||
## Checklist
|
||||
|
||||
When reviewing or writing Redis code, verify:
|
||||
|
||||
- [ ] Connection pool configured with MinIdle/MaxActive ratios
|
||||
- [ ] Read/write timeouts explicitly set (> 0)
|
||||
- [ ] Retry logic implemented with bounded attempts (max 3)
|
||||
- [ ] Hot key detection strategy in place
|
||||
- [ ] Cache penetration/breakdown/avalanche handled
|
||||
- [ ] Distributed lock has auto-expiry + reentrant design
|
||||
- [ ] Pipeline used for batch operations (> 3 commands)
|
||||
- [ ] Keys have TTL set (except explicit no-expiry cases)
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern 1: Safe Cache-Aside
|
||||
|
||||
```go
|
||||
func GetProductCacheable(ctx context.Context, id string) (*Product, error) {
|
||||
// 1. Try cache first
|
||||
data, err := rdb.Get(ctx, productKey(id)).Result()
|
||||
if err == nil {
|
||||
// deserialized...
|
||||
return parse(data)
|
||||
}
|
||||
|
||||
// 2. Cache miss -> query DB with double-check pattern
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// Double-check after acquiring lock
|
||||
data, err = rdb.Get(ctx, productKey(id)).Result()
|
||||
if err == nil {
|
||||
return parse(data)
|
||||
}
|
||||
|
||||
result, err := db.QueryProduct(ctx, id)
|
||||
if err != nil {
|
||||
// Write cache with short TTL to prevent penetration
|
||||
rdb.Set(ctx, productKey(id), "", 30*time.Second)
|
||||
return nil, fmt.Errorf("product not found: %w", err)
|
||||
}
|
||||
|
||||
rdb.Set(ctx, productKey(id), marshal(result), 15*time.Minute)
|
||||
return result, nil
|
||||
}
|
||||
```
|
||||
|
||||
> [!SUMMARY] 这段代码的关键点
|
||||
> - 使用了 **Cache-Aside** 模式(缓存旁路),而非 Write-Through
|
||||
> - 实现了 **Double-Check** 加锁机制,防止缓存击穿下的并发穿透
|
||||
> - 穿透保护用了 30 秒短 TTL(空值缓存),常规数据用 15 分钟
|
||||
> - 注意这里用 `marshal/unmarshal` 抽象了序列化,实际应统一使用 msgpack 或 protobuf
|
||||
|
||||
### Pattern 2: Distributed Lock (Redisson-style)
|
||||
|
||||
```go
|
||||
func WithDistributedLock(ctx context.Context, key string, ttl time.Duration, fn func() error) error {
|
||||
lockKey := "lock:" + key
|
||||
locked, err := rdb.SetNX(ctx, lockKey, uuid.New().String(), ttl).Result()
|
||||
if err != nil {
|
||||
return fmt.Errorf("acquire lock failed: %w", err)
|
||||
}
|
||||
if !locked {
|
||||
return ErrLockAcquireFailed
|
||||
}
|
||||
|
||||
// Auto-release on exit
|
||||
defer rdb.Del(ctx, lockKey)
|
||||
|
||||
return fn()
|
||||
}
|
||||
```
|
||||
|
||||
## Anti-patterns to Avoid
|
||||
|
||||
> [!FAILURE] ❌ 反模式
|
||||
|
||||
- **全量导出**: `KEYS *` 在生产环境禁用,改用 `SCAN`
|
||||
- **阻塞操作**: `BLPOP` 无超时时间可能导致 goroutine 泄漏
|
||||
- **主从切换丢失**: 同步写后立即读可能命中 slave 导致不一致,需用 `READONLY` 或 `WAIT`
|
||||
- **Large Key**: Value > 10KB 的 hash/string 需特别注意内存和网络开销
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["客户端请求"] --> B{"缓存命中?"}
|
||||
B -- "Yes" --> C["返回缓存值"]
|
||||
B -- "No" --> D["获取分布式锁"]
|
||||
D --> E{"获取成功?"}
|
||||
E -- "No" --> F["等待后重试"]
|
||||
F --> D
|
||||
E -- "Yes" --> G["查询数据库"]
|
||||
G --> H["写入缓存 + 设置 TTL"]
|
||||
H --> C2["返回数据"]
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["客户端"] --> B["Sentinel / Cluster"]
|
||||
B --> C[Master Node]
|
||||
C -- "异步复制" --> D[Slave 1]
|
||||
C -- "异步复制" --> E[Slave N]
|
||||
|
||||
subgraph Problem ["主从切换期间的风险"]
|
||||
W1["写入 Master"] -.->|"可能未复制到 Slave"| W2["Master 故障"]
|
||||
W2 --> W3["Slave 晋升为新 Master"]
|
||||
W3 --> W4["新写入丢失"]
|
||||
end
|
||||
|
||||
classDef warn fill:#f9d0c4,stroke:#d84315
|
||||
class W1,W2,W3,W4 warn
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
- [[AI/Claude Code 生态/Agent 架构基础]]
|
||||
- [[后端/中间件集成/Redis 实战指南]]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 场景二:自动化邮件报告(进阶级)
|
||||
|
||||
**需求**: 创建 Skill 让 AI 能够自动生成周报、月报并通过邮件发送。
|
||||
|
||||
> [!SUCCESS] 这个 Skill 的优势在于 —— 它不仅是一个模板,还包含了完整的错误处理和幂等保证。
|
||||
|
||||
#### Skill 定义
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: email-report
|
||||
description: Generate and send automated reports (weekly/monthly) via email
|
||||
trigger: "generate report AND email OR send weekly OR monthly report OR 生成报告"
|
||||
---
|
||||
|
||||
# Automated Email Report Skill
|
||||
|
||||
## Overview
|
||||
Guides the creation of structured reports and their delivery via email,
|
||||
handling template rendering, attachment generation, and notification delivery.
|
||||
|
||||
## Pre-flight Checks
|
||||
|
||||
Before sending any report, verify these environment variables are set:
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `SMTP_HOST` | Yes | SMTP server address |
|
||||
| `SMTP_PORT` | Yes | SMTP port (587 for TLS) |
|
||||
| `EMAIL_USER` | Yes | Sender address |
|
||||
| `EMAIL_PASS` | Yes | App-specific password or API token |
|
||||
| `REPORT_RECIPIENTS` | No | Comma-separated recipient list |
|
||||
|
||||
> [!IMPORTANT] 安全提醒
|
||||
> All credentials must come from ENV or secrets manager. NEVER hardcode.
|
||||
|
||||
## Workflow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant S as Email Report Skill
|
||||
participant T as Template Engine
|
||||
participant A as Attachment Generator
|
||||
participant M as SMTP Client
|
||||
participant R as Recipients
|
||||
|
||||
U->>S: "Generate weekly report"
|
||||
S->>S: Parse scope & date range
|
||||
S->>T: Render HTML template
|
||||
T-->>S: Generated HTML
|
||||
S->>A: Generate PDF attachment
|
||||
A-->>S: PDF bytes
|
||||
S->>M: Send email with attachments
|
||||
M-->>R: Deliver to all recipients
|
||||
S->>S: Log delivery status
|
||||
S-->>U: Report sent successfully
|
||||
```
|
||||
|
||||
## Step 1: Report Template Structure
|
||||
|
||||
All reports follow this standard structure:
|
||||
|
||||
```html
|
||||
<h1>{{report_type}} Report — {{period}}</h1>
|
||||
|
||||
<section>
|
||||
<h2>Summary</h2>
|
||||
<p>{{summary}}</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Key Metrics</h2>
|
||||
<table>
|
||||
<!-- rendered metrics table -->
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Action Items</h2>
|
||||
<ul>
|
||||
<!-- rendered action items -->
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<footer>Sent by automated reporting system</footer>
|
||||
```
|
||||
|
||||
## Step 2: Sending Implementation
|
||||
|
||||
```python
|
||||
import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.base import MIMEBase
|
||||
from email import encoders
|
||||
import os
|
||||
|
||||
def send_report(subject: str, html_body: str,
|
||||
attachments: list[str] | None = None,
|
||||
recipients: list[str] | None = None):
|
||||
"""Send report email with optional attachments."""
|
||||
|
||||
msg = MIMEMultipart("mixed")
|
||||
msg["From"] = os.getenv("EMAIL_USER")
|
||||
msg["To"] = ", ".join(recipients or [])
|
||||
msg["Subject"] = subject
|
||||
|
||||
# HTML body
|
||||
msg.attach(MIMEText(html_body, "html"))
|
||||
|
||||
# Attachments (PDFs, charts, etc.)
|
||||
for filepath in attachments or []:
|
||||
with open(filepath, "rb") as f:
|
||||
part = MIMEBase("application", "octet-stream")
|
||||
part.set_payload(f.read())
|
||||
encoders.encode_base64(part)
|
||||
part.add_header("Content-Disposition", "attachment", filename=os.path.basename(filepath))
|
||||
msg.attach(part)
|
||||
|
||||
# Send with TLS and timeout protection
|
||||
with smtplib.SMTP(os.getenv("SMTP_HOST"), int(os.getenv("SMTP_PORT"))) as server:
|
||||
server.starttls()
|
||||
server.login(msg["From"], os.getenv("EMAIL_PASS"))
|
||||
server.send_message(msg, to_addrs=recipients)
|
||||
```
|
||||
|
||||
## Step 3: Retry Strategy
|
||||
|
||||
```python
|
||||
import tenacity
|
||||
|
||||
@tenacity.retry(
|
||||
stop=tenacity.stop_after_attempt(3),
|
||||
wait=tenacity.wait_exponential(multiplier=1, min=2, max=30),
|
||||
retry=tenacity.retry_if_exception_type(smtplib.SMTPException),
|
||||
before_sleep=lambda retry_state: print(f"Retrying email delivery... ({retry_state.attempt_number}/3)")
|
||||
)
|
||||
def send_with_retry(email_fn, *args, **kwargs):
|
||||
"""Email sending with exponential backoff retry."""
|
||||
return email_fn(*args, **kwargs)
|
||||
```
|
||||
|
||||
## Error Handling Matrix
|
||||
|
||||
| Scenario | Action | Logging Level |
|
||||
|----------|--------|---------------|
|
||||
| Missing env vars | Abort early, output help text | ERROR |
|
||||
| SMTP connection refused | Queue job for retry | WARN |
|
||||
| Authentication failed | Notify admin via web hook | CRITICAL |
|
||||
| Attachment too large (> 25MB) | Split into multiple emails | WARN |
|
||||
| Empty recipient list | Skip sending, log info | INFO |
|
||||
|
||||
## Cron Integration (Optional)
|
||||
|
||||
If scheduling is needed, recommend platform-native schedulers over custom cron scripts:
|
||||
|
||||
| Platform | Recommendation | Example |
|
||||
|----------|---------------|---------|
|
||||
| Linux | systemd timer or crontab | `0 9 * * 1 /usr/bin/python report.py` |
|
||||
| Docker | entrypoint wrapper script | Health-checked container |
|
||||
| Cloud | EventBridge / Cloud Scheduler | Configured via IaC |
|
||||
|
||||
## 关联笔记
|
||||
- [[AI/Automated Reporting/报告生成架构]]
|
||||
- [[后端/基础设施/SMTP 邮件服务]]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 场景三:PR Review Checklist(实用级)
|
||||
|
||||
**需求**: 每当用户请求审查某个 PR 或 diff 时,自动以预设的检查清单来审视代码变更。
|
||||
|
||||
#### 快速定义
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: pr-review-checklist
|
||||
description: Run a structured code review checklist on PR diffs
|
||||
trigger: "review PR OR review diff OR review pull request"
|
||||
---
|
||||
|
||||
# PR Review Checklist
|
||||
|
||||
## Quick Reference
|
||||
|
||||
Review each change against these categories:
|
||||
|
||||
### 1. Correctness
|
||||
- [ ] Logic matches requirements?
|
||||
- [ ] Edge cases handled (empty input, null, zero)?
|
||||
- [ ] Error propagation correct (not swallowed)?
|
||||
|
||||
### 2. Performance
|
||||
- [ ] No O(n²) loops where O(n) suffices?
|
||||
- [ ] Database queries not N+1?
|
||||
- [ ] Large data streaming instead of loading entirely into memory?
|
||||
|
||||
### 3. Security
|
||||
- [ ] Input sanitization present?
|
||||
- [ ] AuthN/AuthZ verified before sensitive operations?
|
||||
- [ ] Secrets never logged or committed?
|
||||
|
||||
### 4. Maintainability
|
||||
- [ ] Function size reasonable (< 50 lines)?
|
||||
- [ ] Meaningful variable/function names?
|
||||
- [ ] Comments explain WHY not WHAT?
|
||||
|
||||
### 5. Testing
|
||||
- [ ] Unit tests cover happy path + edge cases?
|
||||
- [ ] Test isolation maintained (no shared mutable state)?
|
||||
- [ ] Integration tests if external dependency involved?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 场景四:数据库迁移脚本生成器(高级)
|
||||
|
||||
**需求**: 基于当前的数据库 schema 和用户提出的变更需求,自动生成带版本控制和回滚能力的迁移脚本。
|
||||
|
||||
> [!FAILURE] ⚠️ 这个场景比较危险 —— 涉及数据库变更的操作,必须在 Skill 中加入强制确认步骤。
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: db-migration-generator
|
||||
description: Generate safe database migration scripts with rollback support
|
||||
trigger: "migration OR alter table OR add column AND database"
|
||||
---
|
||||
|
||||
# Database Migration Generator
|
||||
|
||||
> [!CRITICAL] 安全协议
|
||||
> This skill operates on real databases. Every generated migration MUST include:
|
||||
> 1. A rollback script
|
||||
> 2. Data safety analysis
|
||||
> 3. Explicit confirmation requirement before execution
|
||||
|
||||
## Safe Migration Rules
|
||||
|
||||
### Zero-Downtime Pattern for Schema Changes
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Step 1: Add nullable column"] --> B["Step 2: Backfill existing data"]
|
||||
B --> C["Step 3: Deploy app with dual-write"]
|
||||
C --> D["Step 4: Validate new data correctness"]
|
||||
D --> E["Step 5: Switch reads to new column"]
|
||||
E --> F["Step 6: Remove old column (next release)"]
|
||||
classDef step fill:#e8f5e9,stroke:#2e7d32
|
||||
class A,B,C,D,E,F step
|
||||
```
|
||||
|
||||
### Never Do This on Large Tables
|
||||
|
||||
> [!FAILURE] 高危操作 —— 以下操作在 > 100K 行的表上执行会导致锁表:
|
||||
|
||||
| 操作 | 风险等级 | 推荐替代方案 |
|
||||
|------|---------|------------|
|
||||
| `ALTER TABLE ADD NOT NULL` | 🔴 致命 | 分步添加 + backfill |
|
||||
| `ALTER TABLE DROP COLUMN` | 🔴 致命 | 标记废弃 + 下周期清理 |
|
||||
| `ALTER TABLE MODIFY TYPE` | 🟠 危险 | 新建列 + 数据迁移 + 切换 |
|
||||
| `ADD UNIQUE INDEX CONCURRENTLY` | 🟢 安全 | PostgreSQL 原生支持 |
|
||||
|
||||
### Generated Script Template
|
||||
|
||||
```sql
|
||||
-- Migration: 0042_add_user_email_verified
|
||||
-- Date: YYYY-MM-DD
|
||||
-- Risk: LOW (additive change only)
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- Step 1: Add new nullable column
|
||||
ALTER TABLE users
|
||||
ADD COLUMN email_verified_at TIMESTAMP WITH TIME ZONE DEFAULT NULL;
|
||||
|
||||
-- Step 2: Create index (non-blocking where possible)
|
||||
CREATE INDEX CONCURRENTLY idx_users_email_verified
|
||||
ON users(email_verified_at) WHERE email_verified_at IS NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================
|
||||
-- ROLLBACK SCRIPT
|
||||
-- ============================
|
||||
-- BEGIN;
|
||||
-- DROP INDEX CONCURRENTLY IF EXISTS idx_users_email_verified;
|
||||
-- ALTER TABLE users DROP COLUMN IF EXISTS email_verified_at;
|
||||
-- COMMIT;
|
||||
```
|
||||
|
||||
## Confirmation Steps
|
||||
|
||||
Before generating any migration, ask the user:
|
||||
|
||||
1. What is the target database and version? (PostgreSQL 15, MySQL 8.x, etc.)
|
||||
2. Is the table large (> 1M rows)? If yes, enforce zero-downtime pattern.
|
||||
3. Can rolling deploy be supported? If no, plan full downtime window.
|
||||
4. Has the migration been reviewed by a second person?
|
||||
|
||||
## 关联笔记
|
||||
- [[后端/数据库/迁移最佳实践]]
|
||||
- [[DevOps/零停机部署策略]]
|
||||
```
|
||||
|
||||
## 总结与进阶方向
|
||||
|
||||
### Skill 成熟度模型
|
||||
|
||||
```mermaid
|
||||
graph BT
|
||||
P1["Level 1: Prompt 库"]
|
||||
P2["Level 2: CLAUDE.md snippets"]
|
||||
P3["Level 3: Custom Skill"]
|
||||
P4["Level 4: Custom Agent Type"]
|
||||
P5["Level 5: MCP Server Integration"]
|
||||
|
||||
P1 --> P2 --> P3 --> P4 --> P5
|
||||
|
||||
classDef low fill:#fff3e0,stroke:#ef6c00
|
||||
classDef mid fill:#e3f2fd,stroke:#1565c0
|
||||
classDef high fill:#e8f5e9,stroke:#2e7d32
|
||||
|
||||
class P1,P2 low
|
||||
class P3,P4 mid
|
||||
class P5 high
|
||||
```
|
||||
|
||||
### 下一步学习路线
|
||||
|
||||
| 阶段 | 重点 | 推荐资源 |
|
||||
|------|------|---------|
|
||||
| **Phase 1** | 理解现有内置 Skill 的触发逻辑 | 阅读本 Skill 的定义源码 |
|
||||
| **Phase 2** | 创建第一个极简 Skill(3 条 rule) | 参考 PR Review Checklist 案例 |
|
||||
| **Phase 3** | 加入 workflow 图表 + 错误处理 | 参考 Email Report 案例 |
|
||||
| **Phase 4** | 探索自定义 Agent Type(超越 Skill 的能力边界) | Study Explore / Plan agent 的实现 |
|
||||
| **Phase 5** | 构建 MCP Server 实现跨工具链联动 | Anthropic MCP Protocol 文档 |
|
||||
|
||||
### 一句话总结
|
||||
|
||||
> **好的 Skill 不是"教 AI 怎么做",而是"给 AI 一套它做这件事时一定会遵守的思维框架"。** 就像给高级工程师一份技术规范——细节他可以自己决定,但红线和标准你必须写好。
|
||||
Reference in New Issue
Block a user