AI 编码 Agent 技能指南:Addy Osmani 的实战模板

今天 GitHub 上有个项目炸了——Addy Osmani 的 agent-skills,上架一天狂揽 58k+ stars。这位 Google Chrome 团队的老兄写过《高性能 JavaScript》,现在他把注意力转到 AI 编码 Agent 上,想解决一个核心痛点:Agent 写的代码太“学生气”了,缺乏工程素养

这个项目解决什么问题?

你用 Cursor 或 Claude 写代码时,是不是经常遇到这种情况:

  • Agent 不遵守项目已有的代码风格(比如用单引号还是双引号)
  • 不写类型注解、不处理异常、不写文档
  • 生成的路由或 API 和现有架构格格不入
  • 每次对话都要重新强调规则,Agent 记不住

Addy 的做法很直接:把工程最佳实践写成一个个独立的 Skill 文件(Shell 脚本),让 Agent 在开始工作前先把这些规则“吸入”到上下文里。每个 Skill 就是一个可复用的专家知识包,比如“如何写提交信息”、“如何进行单元测试”、“如何编写安全的 Python 代码”。

你可以把 Skill 理解成 Agent 的“入职培训手册”——第一次用就把规矩定好,后面每次生成都自动遵循。

核心思路:用 Shell 脚本注入生产级约束

agent-skills 仓库里大多是 .sh 文件,每个文件里面包含:

  • SKILL_NAME:技能名称
  • SKILL_DESCRIPTION:技能描述
  • SKILL_RULES:具体的规则列表
  • 加载函数:将规则写入环境变量或临时文件,供 Agent 读取

核心机制是:通过 source 命令将规则注入到当前 shell 会话,然后 Agent 的 system prompt 会引用这些环境变量。例如 Cursor 的 .cursorrules 可以写成:

bash
1 2 3
# 在 .cursorrules 中引用技能文件
source ~/.agent-skills/python-flask.sh
source ~/.agent-skills/git-commit.sh

这样每次 Cursor 启动时,Agent 都能感知到这些规则。

完整可复用的提示词模板

你不需要完全依赖 Shell 脚本。以下是一个通用的技能注入模板,可以直接放在 Cursor 的 .cursorrules、Claude Projects 的 Instructions 或 GitHub Copilot 的 copilot-instructions.md 中:

markdown
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# AI Agent 技能指令包

## 通用规则
- 所有代码必须包含类型注解(Python)或类型声明(TypeScript)
- 每个函数/方法必须有 docstring 或 JSDoc,说明用途、参数、返回值
- 捕获所有可预见的异常,并返回结构化的错误响应
- 禁止硬编码密钥或敏感信息,必须通过环境变量获取
- 单元测试覆盖率不低于 80%,测试放在 tests/ 目录

## 语言/框架特定规则
- Python: 使用 Pydantic 进行数据验证,使用 `pathlib` 处理路径
- TypeScript: 严格模式启用,使用 `zod` 进行运行时校验
- React: 使用函数组件和 Hooks,避免 class 组件

## 工作流程
1. 在实现之前,先写测试用例(TDD 风格)
2. 每次提交前,运行 `npm run lint` 和 `npm test`
3. 代码变更后,更新相关文档

这个模板是“通用版”。如果你想要 Addy 仓库里那种更细粒度的技能分离,可以这样写一个可复用的 Skill 函数(适用于支持函数调用的 Agent 工具):

bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# install-skill.sh — 一键安装多个技能
#!/bin/bash
SKILLS_DIR="$HOME/.agent-skills"
mkdir -p "$SKILLS_DIR"

# 创建 Flask API 技能
cat > "$SKILLS_DIR/flask-api.sh" << 'SKILL'
SKILL_NAME="flask-api"
SKILL_DESC="Professional Flask API with Blueprints, Pydantic, error handling"
SKILL_RULES=$(cat <<RULES
- Use Flask Blueprints to organize routes by module
- Define request/response schemas with Pydantic
- Wrap endpoints in try/except, return JSON with status_code
- Add health-check endpoint at /health
- Type hint all function parameters and return values
RULES
)
export SKILL_RULES
SKILL

# 创建 Git 提交技能
cat > "$SKILLS_DIR/git-commit.sh" << 'SKILL'
SKILL_NAME="git-commit"
SKILL_DESC="Conventional commit message format"
SKILL_RULES=$(cat <<RULES
- Format: <type>(<scope>): <description>
- Types: feat | fix | docs | style | refactor | test | chore
- Use imperative mood, no period at end
- Keep first line under 72 characters
RULES
)
export SKILL_RULES
SKILL

# 加载所有技能
for f in "$SKILLS_DIR"/*.sh; do source "$f"; done

然后在你的 Agent 工具的初始提示中加入:

请首先执行 source ~/.agent-skills/install-skill.sh,然后根据加载的 SKILL_RULES 生成代码。

效果演示:差 Prompt vs 好 Prompt

差 Prompt(无技能注入)

写一个 Flask 路由返回用户列表。

Agent 通常输出:

python
1 2 3 4
@app.route('/users')
def get_users():
    users = User.query.all()
    return jsonify(users)

问题:没有 Blueprint、没有 Pydantic、没有异常处理、没有类型注解、没有健康检查。如果项目本身已有装饰器和错误处理基类,Agent 可能完全忽略。

好 Prompt(先加载技能,再要求生成)

请先加载 flask-api 技能,然后根据技能规则创建一个获取用户列表的 API 端点。

Agent 输出:

python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
from flask import Blueprint, jsonify
from pydantic import BaseModel
from typing import List
from your_project.extensions import db
from your_project.models.user import User
from your_project.errors import APIError

user_bp = Blueprint('users', __name__, url_prefix='/api/v1/users')

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

class UserListResponse(BaseModel):
    code: int = 0
    data: List[UserResponse]

@user_bp.route('/', methods=['GET'])
def get_users() -> tuple:
    """返回所有用户列表"""
    try:
        users = User.query.all()
        response = UserListResponse(
            data=[UserResponse(id=u.id, name=u.name, email=u.email) for u in users]
        )
        return jsonify(response.model_dump()), 200
    except Exception as e:
        raise APIError(str(e), status_code=500)

差异一目了然:类型安全、结构化、异常处理、统一响应格式。这正是“生产级”的含义。

变体和注意事项

  1. 不同工具的加载方式

    • Cursor:将技能规则写入 .cursorrules 文件即可,无需每次都 source
    • Claude Projects:在 Project Instructions 中粘贴技能模板。
    • GitHub Copilot:在仓库根目录添加 .github/copilot-instructions.md
    • 手动加载:在对话开始时粘贴一个包含技能规则的 system prompt。
  2. 技能数量控制:Addy 仓库里放了十几个技能,但我不建议全量加载。GPT 的上下文窗口有限,只加载当前项目最关键的 5-7 条规则。比如前端项目侧重代码风格和测试,后端项目侧重安全和 API 规范。

  3. 动态加载 vs 静态规则:Shell 脚本的方式适合需要根据环境变量变化的场景(如不同分支采用不同规则)。大多数情况下,静态规则更简单可靠——直接写在 .cursorrules 里。

  4. 我的一点看法:Addy 的方法本质上是把隐性工程知识显性化。很多团队一直在做 Code Review,但 Agent 不会自动从 Review 中学乖。技能模板相当于把 Review 的 checklist 直接喂给 Agent,比写文档更有效。但注意:技能规则如果太细太碎,Agent 会变成死板的“遵循者”,丧失创造性。平衡之道是:保留架构决策的自由度,只约束代码质量和规范。

  5. 扩展用法:你可以把技能文件和 CI/CD 结合——在 PR 的 GitHub Action 中,用 diff 对比 Agent 生成的代码是否违反了技能规则。甚至可以写一个 linter 插件,自动检查代码是否符合已加载的技能列表。

总结

Addy Osmani 的 agent-skills 给了我们一个可落地的思路:不要每次和 Agent 对话都唠叨规则,而是把规则打包成 Skill,让 Agent 像加载工具箱一样加载。你可以在 5 分钟内复制上面的模板到你的工具里,立刻看到 Agent 输出质量的提升。

把这个工具加到你的 AI 工作流里,你会发现 Agent 不再是“实习生”,而是“高级工程师”。试试看。