不吹不黑,Agent Skill 这个概念在圈子里已经火了大半年了。但有个现象很有意思:大家都在聊“怎么写一个 Skill”,聊得最多的却是“怎么把一堆 prompt 塞进一个文件夹”。真正能把一个垂直领域的需求做成标准技能包、并且让 Claude、Codex 这类 Agent 顺畅调用的案例,其实不多。
今天我想借一个真实可落地的项目标题来复盘:security-audit-skill。这个项目不是花架子,而是把“安全审计”这个专业度极高的场景,彻底拆解成 Agent 能理解、能执行、能输出的技能包。如果你正准备给自己的 Agent 编写第一个真正能用在生产环境的 Skill,或者想搞明白“Skill 和普通提示词到底差在哪”,这篇内容会把思路、结构、踩坑点一次讲透。
1. 先搞明白:Agent Skill 是什么,安全审计为什么要单独做成 Skill
很多同学第一次接触 Skill 时,最容易犯的错是把它当成“高级一点的预设提示词”。我在实际开发 security-audit-skill 之前也走过这段弯路,所以先把概念理清楚,后面才不会跑偏。
1.1 Skill 与普通提示词的本质区别
普通提示词是“一次性指令”,你把需求发给模型,它基于上下文临时发挥。适合聊天、翻译、写文案这类任务。但安全审计完全不同,它要求 Agent 在一套固定的方法论指导下,按顺序执行多个检查步骤,每个步骤都要有可追溯的证据。
Skill 的本质,是把“方法论 + 知识库 + 检查脚本 + 输出模板”打包成一个可复用的目录结构。当 Agent 识别到当前任务匹配某个 Skill 时,它会自动加载这个技能包,而不是每次都临时拼凑提示词。
用一个生活化的类比:普通提示词就像你临时叫一个实习生去“查一下代码有没有安全问题”,他可能东翻西看,凭感觉给你几条建议。而 Skill 相当于你递给他一本《安全审计操作手册》,手册里写清楚了“第一步看哪、第二步查什么、发现什么问题用什么格式记录”,实习生照着做,产出的质量稳定得多。
1.2 安全审计场景为什么要做成 Skill,而不是普通对话
安全审计有几个特性,让它天然适合以 Skill 形态承载:
其一,知识密度高。一次完整的代码安全审计,涉及依赖漏洞检查、硬编码密钥扫描、注入风险识别、越权逻辑分析、配置项安全性验证等多个维度。如果靠模型临时发挥,相当一部分关键检查项会被遗漏,因为模型的注意力是分布式的,不会天然按照审计清单来。
其二,流程固定可标准化。无论是 OWASP Top 10 还是企业内部的发布安全规范,审计步骤都是相对固定的。把这些步骤固化成规则文件,能让 Agent 每次都按照同样的标准执行,不会因为对话上下文长度、模型版本变化而产生结果漂移。
其三,输出需要结构化。安全审计的产出是一份可供开发团队直接修改代码的报告,包含风险等级、问题位置、成因分析、修复建议。这种格式适合预先定义好模板,让 Agent 按模板填充,而不是自由发挥写一段散文。
所以当我设计 security-audit-skill 时,核心目标就很明确了:让任何一个支持 Skill 机制的 Agent,都能在拿到代码仓库后,以审计员的思维完成一次结构化安全检查。
2. 做 Skill 前的关键设计:审计范围、知识边界与目录规划
确定方向后,先别急着写文件,至少拿出半天时间做设计。我在第一次做这个项目时,因为跳过设计直接编码,导致后面返工了三次,每次都是因为范围没有界定清楚。
2.1 先明确安全审计到底审什么
文档化、结构化的审计范围,建议整理成一棵“审计能力树”,至少包含五个主干:
- 依赖安全:检查项目依赖是否存在已知高危漏洞。对 Python 项目看 requirements.txt / pyproject.toml,对 Node.js 项目看 package-lock.json,对 Java 项目看 pom.xml。这项主要依赖漏洞库比对,属于确定性较高的检测。
- 敏感信息泄露:扫描代码中是否硬编码了 API Key、数据库密码、私钥、Token 等。常见模式包括
password =、api_key =、BEGIN RSA PRIVATE KEY等。 - 注入类风险:识别 SQL 注入、命令注入、模板注入、路径遍历等风险点。重点检查字符串拼接 SQL、直接传给 eval/exec 的输入、未过滤的用户参数。
- 认证与授权:审查登录逻辑、会话管理、越权漏洞。重点关注未鉴权的接口、JWT 实现中的算法混淆、基于前端隐藏元素的权限控制。
- 配置安全:检查服务配置是否存在默认口令、调试模式未关闭、CORS 配置过宽、安全响应头缺失等问题。
这个能力树是 Skill 的骨架,后续所有规则文件、检查脚本、输出模板都围绕它展开。
2.2 Skill 目录结构:让 Agent 和人都能一眼看懂
一个规范的 Agent Skill,从顶层到内部必须有清晰的信息层级。我最终定的目录结构如下:
security-audit-skill/ ├── SKILL.md # 技能入口,Agent 优先读取 ├── rules/ # 审计规则库 │ ├── dependency-audit.yaml # 依赖安全规则 │ ├── secret-detection.yaml # 敏感信息规则 │ ├── injection-audit.yaml # 注入类风险规则 │ ├── auth-audit.yaml # 认证授权规则 │ └── config-audit.yaml # 配置安全规则 ├── scripts/ │ ├── scan_dependencies.py # 依赖漏洞比对脚本 │ ├── scan_secrets.py # 敏感信息正则扫描 │ └── generate_report.py # 报告生成脚本 ├── templates/ │ ├── audit_report.md # 审计报告模板 │ └── issue_card.md # 单个问题卡片模板 └── references/ └── owasp_top10.md # 知识库,供 Agent 查阅这套结构的特点在于:规则、脚本、模板完全解耦。规则文件告诉 Agent“查什么”,脚本告诉 Agent“怎么查”,模板告诉 Agent“怎么输出”,三者通过 SKILL.md 串联。后续无论是新增一种漏洞类型,还是修改报告格式,都只需要改动对应目录,不影响整体。
2.3 元数据声明:决定 Skill 何时被自动触发
绝大多数 Skill 框架(包括 Claude、Codex、OpenCode 等)都支持通过 YAML frontmatter 声明元数据。这个部分容易被忽略,但它直接决定了 Agent 能否在合适的场景下自动想起这个 Skill。
我在 SKILL.md 顶部这样声明:
--- name: security-audit-skill description: 对代码仓库执行系统化安全审计,覆盖依赖漏洞、敏感信息泄露、注入风险、认证授权、配置安全五大维度。当用户要求进行安全审计、漏洞扫描、代码安全检查、上线前安全评估、风险排查时,优先使用该技能。 ---描述部分建议写得具体,包含明确的“触发场景词”,但不要堆砌太多,否则模型在语义匹配时会出现误触发。
3. SKILL.md 怎么写,Agent 才肯“听话”
SKILL.md 是整个 Skill 的指挥中心,它的质量直接决定了 Agent 的审计行为是否可控。很多教程只告诉你“写清楚步骤就行”,但实际开发中你会发现,Agent 经常会在某个细节上自由发挥。
3.1 指令文件的三段式结构:角色约束、主流程、兜底逻辑
我的 SKILL.md 编写经验是,必须把指令拆成三个层次,缺一层 Agent 都会跑偏。
第一层是角色与目标约束。明确告诉 Agent:“你现在是一名资深应用安全审计员,你需要依据本技能包中的规则文件完成审计。”这一步是给 Agent 设置思维框架,避免它跳出审计视角,变成普通的代码解读。
第二层是主流程。这个部分必须像菜谱一样精确,我用的是“阶段编号 + 动作要求 + 结果要求”的写法,例如:
## 审计主流程 请严格按照以下阶段执行,每完成一个阶段,必须先向用户briefly汇报该阶段发现,再进入下一阶段: ### 阶段一:项目信息收集 - 列出仓库根目录下的全部文件和依赖清单文件 - 识别项目的语言/框架类型 - 输出:项目技术栈概览 ### 阶段二:依赖安全扫描 - 调用 scripts/scan_dependencies.py 扫描依赖清单 - 将扫描结果与 rules/dependency-audit.yaml 中的漏洞库进行比对 - 输出:高危/中危依赖清单及影响版本 ### 阶段三:敏感信息检测 - 对仓库全部文本文件执行 scripts/scan_secrets.py - 重点检查 .env 文件、配置文件、测试代码中的凭据 - 输出:疑似泄露的敏感信息列表,标注文件路径和行号每一步都包含“动作 + 产出”两个要素。Agent 只会在做完并汇报当前阶段后,才被允许进入下一阶段,这能有效避免它跳过检查直接生成结论。
第三层是兜底逻辑。比如当 Agent 遇到无法解析的依赖文件,或者脚本执行失败时,要明确规定行为:“如果某阶段无法执行,请在报告中标记为 UNKNOWN,并在‘审计限制说明’中注明原因,不得自行编造扫描结果。”
3.2 把 OWASP Top 10 这类知识库转化为 Skill 规则
说到安全审计,离不开 OWASP Top 10 这类行业知识库。但知识库不能直接丢给 Agent,它的形态是一份 PDF 或网页,Agent 即使在上下文中也无法高效调用。正确做法是把知识库转化为规则文件。
比如在rules/injection-audit.yaml中,我会用结构化格式描述漏洞特征:
rules: - id: SYS-001 type: sql-injection title: SQL 注入 - 字符串拼接 severity: high patterns: - "SELECT.*FROM.*WHERE.*\\+" - "select * from .* where .*\\+" - "executeQuery\\(.*\\+" hints: - "使用参数化查询替换字符串拼接。" - "对用户输入做白名单校验。" references: - "OWASP A03:2021 - Injection"这样的规则文件,既能让 Agent 在扫描阶段参照模式匹配,也能在生成报告时引用“参考规范”。后续如果漏洞库更新,只需要增删规则条目,不需要改动主指令文件。
3.3 审计清单设计:每一步都能被检查有没有执行
为了确保 Agent 不偷懒,我建议在 SKILL.md 的末尾附上一份“审计自检清单”:
## 审计自检清单(完成报告前必查) - [ ] 是否已扫描全部依赖清单文件? - [ ] 是否已执行敏感信息正则扫描并检查误报? - [ ] 是否审查了所有需要认证的 API 路由? - [ ] 是否验证了 CORS、安全响应头等配置项? - [ ] 是否在报告中标注了无法审计的模块及其原因? 如果以上任一问题答案为“否”,请回到对应阶段继续审计。这一步非常有效。实测下来,加入自检清单后,Agent 遗漏检查项的概率明显下降,因为它需要在生成报告前“逐项确认”。
4. 规则引擎与脚本实现:让 Skill 从“会说”变成“会做”
SKILL.md 写得再好,如果 Skill 只能依靠模型自己的代码理解能力做检查,那它仍然只是个“高级提示词”。要让它真正跑到生产环境,必须把确定性检查交给脚本。
4.1 用脚本处理确定性检查,用模型处理逻辑判断
我经常跟人讲,Skill 的开发原则是“能算的不要让模型猜,需要理解的才让模型想”。依赖漏洞比对、正则模式匹配这类确定性任务,脚本远比模型可靠。而越权判断、业务逻辑漏洞分析这类需要业务上下文的任务,则适合让 Agent 基于规则和知识库做推理。
以敏感信息扫描为例,我写了一个纯 Python 脚本,只依赖标准库,不需要额外 pip 安装:
#!/usr/bin/env python3 import os import re import json import sys # 从 rules/secret-detection.yaml 中读取的匹配模式做简化演示 PATTERNS = { "aws_access_key": r"AKIA[0-9A-Z]{16}", "private_key": r"-----BEGIN (RSA|EC|OPENSSH) PRIVATE KEY-----", "generic_password": r"(?i)(password|passwd|pwd)\s*[=:]\s*['\"][^'\"]{8,}['\"]", "api_key": r"(?i)(api[_-]?key|apikey|secret[_-]?key)\s*[=:]\s*['\"][^'\"]{8,}['\"]", "connection_string": r"(?i)(jdbc|mysql|postgres|mongodb)://[^\s'\"@]+\s*[@][^\s'\"]+", } def scan_file(filepath, patterns): findings = [] try: with open(filepath, "r", encoding="utf-8", errors="ignore") as f: for line_no, line in enumerate(f, 1): for name, pattern in patterns.items(): if re.search(pattern, line): findings.append({ "file": filepath, "line": line_no, "type": name, "match": line.strip()[:120], }) except Exception as exc: findings.append({ "file": filepath, "line": 0, "type": "scan_error", "match": str(exc), }) return findings def main(root_dir): all_findings = [] for dirpath, _, filenames in os.walk(root_dir): if any(part in dirpath for part in [".git", "node_modules", "vendor", ".venv"]): continue for filename in filenames: ext = os.path.splitext(filename)[1].lower() if ext not in {".py", ".js", ".ts", ".java", ".go", ".php", ".rb", ".env", ".json", ".yaml", ".yml", ".toml", ".ini", ".conf", ".properties", ".kt", ".cs", ".html", ".vue", ".jsx", ".tsx"}: continue filepath = os.path.join(dirpath, filename) all_findings.extend(scan_file(filepath, PATTERNS)) print(json.dumps(all_findings, ensure_ascii=False, indent=2)) if __name__ == "__main__": main(sys.argv[1])这个脚本的设计逻辑很直接:按文件扩展名过滤目标,逐个文件做匹配,输出带文件路径和行号的 JSON 结果。Agent 拿到 JSON 后,再对结果做误报筛选和修复建议补充。
4.2 依赖漏洞比对:用真实漏洞库,不瞎编版本号
依赖漏洞是最容易“看似专业实则放飞”的环节。如果你在规则文件里手写几个 CVE 编号让 Agent 比对,它极有可能编造出并不存在的漏洞信息。我推荐的做法是,让 Skill 优先调用系统已安装的扫描工具。
比如 Node.js 项目可以用 npm 自带的审计命令,Python 项目可以用 pip-audit。如果本地网络允许,也可以让脚本请求 OSV API 做校验。以下是一个简化版实现:
import subprocess import json import sys def audit_python(requirements_path): cmd = ["pip-audit", "-r", requirements_path, "--format", "json"] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: return json.loads(result.stdout) return {"error": result.stderr} def audit_node(lockfile_path): cmd = ["npm", "audit", "--json", "--prefix", lockfile_path] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: return json.loads(result.stdout) return {"error": result.stderr}这里有一个我踩过的坑:某些仓库的依赖锁定文件非常大,直接让 Agent 读取文本再交给模型分析,既慢又容易截断。正确做法是由脚本读取并解析,只把“漏洞摘要”和“受影响版本范围”输出给 Agent 做后续处理,原始数据留在临时文件中备用。
4.3 报告生成:结构统一,开发团队才愿意看
安全审计报告最忌讳“自定义风格”,每个字段都必须有明确含义。我在templates/audit_report.md中定义了统一模板:
# 安全审计报告 - 审计目标:{{repo_path}} - 审计时间:{{timestamp}} - 审计工具:security-audit-skill v{{version}} ## 审计范围 - 覆盖语言/框架:{{language}} - 依赖清单文件:{{dep_files}} - 排除目录:{{excluded_dirs}} ## 风险统计 | 风险等级 | 数量 | 说明 | | --- | --- | --- | | 严重 | {{critical_count}} | 可被直接利用或已确认泄露 | | 高危 | {{high_count}} | 存在明确攻击路径 | | 中危 | {{medium_count}} | 可能存在攻击面 | | 低危 | {{low_count}} | 需注意安全加固 | ## 问题明细 {{issue_cards}} ## 审计限制说明 {{limitations}}Agent 在生成报告时,会为每个问题填充一张issue_card.md卡片,包含问题描述、证据(文件 + 行号)、风险等级、修复建议。这样开发团队拿到报告后,可以直接按卡片修复而不是重新人工调查。
5. 实战复盘:从零构建一个最小可用的 security-audit-skill
理论讲完,下面进入真正的手把手环节。这一节我把从空目录到跑通完整审计的最小实现路径走一遍,包括我实际测试时遇到的问题。
5.1 边界版本的“最小可用”包含哪些文件
很多人一开始就想做全家桶,结果几个星期过去了什么都写不出来。我建议第一版只保留三件事:能识别项目语言、能扫敏感信息、能出报告。依赖漏洞和注入分析都可以在后续迭加。
最小可用文件清单如下:
security-audit-skill/ ├── SKILL.md ├── rules/ │ └── secret-detection.yaml ├── scripts/ │ └── scan_secrets.py └── templates/ └── audit_report.md就这四个文件,已经能跑一个闭环:Agent 读取 SKILL.md → 了解流程 → 调用脚本扫描 → 汇总发现 → 按模板吐报告。
5.2 实操:手写 SKILL.md 与规则的完整过程
我先写一个精简版 SKILL.md,保留必须的三段式结构:
--- name: security-audit-skill description: 对代码仓库执行安全审计,当前版本聚焦敏感信息泄露检测。当用户要求安全审计、泄漏扫描、密钥检查时使用。 --- # Security Audit Skill ## 角色 你是一名应用安全审计员,必须保持客观、严谨。 ## 审计流程 ### 步骤 1:项目信息识别 - 查看仓库根目录,确定项目类型和语言 - 列出需要扫描的文件清单(排除 .git、node_modules 等目录) ### 步骤 2:敏感信息扫描 - 运行 `python3 scripts/scan_secrets.py <仓库路径>` - 读取 JSON 输出,将命中项与 rules/secret-detection.yaml 中的规则描述关联 - 对每条命中,检查上下文以排除明显误报(例如测试夹具、Mock 数据、文档示例) ### 步骤 3:结果汇总 - 按照 templates/audit_report.md 模板生成报告 - 每条发现必须包含:文件路径、行号、风险等级、修复建议 ## 重要约束 - 不得编造扫描结果,如果脚本报错则记录错误并继续 - 除本项目指定目录外,不得扫描其他目录这个版本的 SKILL.md 只有约 40 行,但它已经把 Agent 的行为边界定义清楚了。实测中,Agent 会严格按照“步骤 1→2→3”的顺序执行,并且每一阶段的输出格式稳定。
5.3 联调测试:模拟一次真实审计,看输出是否符合预期
写完后,我找了一个包含模拟密钥的测试仓库做联调。项目结构大概是这样的:
demo-project/ ├── config.py ├── app.py ├── .env └── requirements.txt其中.env故意写了一段假 AWS Key,config.py里写了一个硬编码数据库密码。调用 Agent 并输入“对 demo-project 做一次安全审计”后,我记录的 Agent 实际行为如下:
- 第一阶段,Agent 列出了项目文件清单,同时识别出这是一个 Python 项目。
- 第二阶段,Agent 执行了
scan_secrets.py,脚本输出 JSON 中有两条命中:一条在.env的 AWS Key,一条在config.py的数据库连接串。 - 第三阶段,Agent 检测到
.env中的命中是真实风险等级为“严重”,原因是该文件按惯例不应提交到版本库;config.py中的命中被Agent识别为“中危”,因为上下文显示它用于本地开发配置,但也提出了改为环境变量注入的建议。 - 最终报告按照模板生成,包含问题卡片、修复建议,以及 audit 范围说明。
这个结果基本符合预期。唯一的瑕疵是 Agent 在识别“配置文件中硬编码密钥”时,风险等级给得有点犹豫,上下文提示词如果加上“硬编码凭据即使用于本地开发也应标记为中危以上”这类规则,输出会更稳定。
5.4 与 Semgrep 这类工具结合:把外部工具变成 Skill 的“眼睛”
如果想要更强的静态分析能力,不建议自己写规则覆盖所有语言。更聪明的方式是让 Skill 调用现成工具。例如在 SKILL.md 中增加一个阶段,指示 Agent 在检测到 Python 或 Java 项目时先检查本地是否安装 Semgrep:
### 步骤 2.5:可选静态分析增强 - 如果环境中存在 semgrep,运行 `semgrep scan --config=auto <仓库路径>` - 只保留错误级别为 ERROR 和 WARNING 的规则命中 - 将这些命中合并到问题明细中这一步的思想,是让通用工具负责广覆盖,让自建规则负责针对性检查。自建的secret-detection.yaml里,我会额外加入几条能覆盖企业自研框架安全规则的检测项,这是通用工具扫不出来的。
6. 调试排障实录:我在开发 security-audit-skill 时踩过的 7 个坑
做这个项目的过程中,我记录了不少调试经历,挑几个最有代表性的分享,希望能帮你少走弯路。
6.1 坑一:Agent 完全没加载 Skill
症状:输入触发词后,Agent 只是普通对话,完全没有调用 Skill 的行为。
排查思路:首先确认 SKILL.md 的文件名和路径是否符合平台规范(这一点不同平台有差异,例如 Claude 要求必须命名为 SKILL.md 放在技能包根目录)。其次检查 frontmatter 中的 name 字段是否与文件夹名称一致。最后看 description 里是否包含足以触发匹配的高频词,例如“安全审计”“漏洞扫描”。
这个坑最磨人,因为你写的指令再完美,Agent 根本不去加载等于零。
6.2 坑二:Agent 调用了 Skill,但审计流程乱序
症状:Agent 跳过了阶段一,直接开始扫描敏感信息;或者还没产出中间结果就直接生成最终报告。
排查思路:这是我早期 SKILL.md 写法太“宽松”导致的。如果你写的是“你应当依次完成以下步骤”,Agent 就可能在步骤数较多时选择性忽略部分环节。改成强约束表达后明显好转,例如“严格遵守以下阶段顺序,任何阶段未完成不得进入下一阶段”。每段后面加“输出:……”也能起到锚定作用。
6.3 坑三:扫描脚本在 Agent 环境中找不到解释器
症状:Agent 尝试执行python3 scripts/scan_secrets.py,但报错找不到 python3。
排查思路:不同宿主机的 Python 路径可能不同,有些环境只有python没有python3。我的做法是,在 SKILL.md 中写一条统一约定:“执行脚本时优先使用 python3,若失败使用 python”,同时在脚本头部加上 shebang#!/usr/bin/env python3。另外脚本本身最好做到无第三方依赖,这样基本能在任何环境运行。
6.4 坑四:规则文件命中太多,误报率居高
症状:扫描结果一大半是误报,Agent 原样呈现给用户,可信度大打折扣。
排查思路:误报主要集中在“文档示例代码”和“测试夹具”。解决办法是让脚本自动忽略常见测试目录和文档目录,并且在规则文件中加入“排除上下文”提示。比如对于数据库连接串,如果所在文件位于tests/或文件名包含example,Agent 应判定为低危或直接标记为“需人工复核”。另外,通过正则的字符边界控制也可以大幅降低误报,比如password只匹配赋值场景而不匹配方法名check_password。
6.5 坑五:大仓库扫描时间过长,触发超时
症状:Agent 在扫描一个几千文件的中型仓库时中途卡住,或报告不完整。
排查思路:扫描耗时主要消耗在“让 Agent 直接读文件分析”,而不是脚本执行。务必把“遍历文件、读内容、做匹配”全部下沉到脚本中,Agent 只消费 JSON 结果。同时限制扫描扩展名白名单,避免把图片、二进制文件、打包产物也不必要地读入上下文。针对超大仓库,建议在 SKILL.md 中定义最大扫描深度或文件数阈值,超限时提示用户分段审计。
6.6 坑六:Agent 生成报告时编造 CVE 编号
症状:依赖安全检测环节,Agent 输出了一个不存在的 CVE 编号,且影响版本范围明显不合理。
排查思路:这是最不能容忍的错误。根治办法是在 SKILL.md 中明确禁止自行编造漏洞编号,并且要求所有漏洞编号必须来自脚本输出。如果脚本未调用漏洞库,则依赖安全板块标记为“未执行”,而不是由 Agent 自行脑补。
6.7 坑七:模板变量替换逻辑混乱
症状:报告里频繁出现{{repo_path}}之类的未替换变量。
排查思路:原因是 Agent 有时会直接把模板原样输出,尤其是模板中变量名本身包含双大括号时,模型可能识别不到替换语义。我的经验是:SKILL.md 中给出明确的替换规则示例,例如“将{{repo_path}}替换为实际项目绝对路径,若不存在则填 N/A”。另外,变量名尽量用用户看得懂的英文,避免用{{var1}}这类无意义缩写。
7. 我在实际项目中的应用心得
这个 security-audit-skill 从原型到在团队内部小规模使用,经历了三轮迭代。第一版只有敏感信息扫描,效果一般;第二版加入了规则库与报告模板,已经开始有人愿意看输出;第三版引入外部静态分析工具联动后,它才真正成为日常开发中会主动使用的工具。
一个比较深的体会是,Skill 开发和普通开发有一个很大的不同:普通开发面向的是确定性的代码执行,而 Skill 开发面向的是一个概率模型的“行为调教”。所以 Skill 里面写的每一句话,都是用来约束模型自由度的。约束粒度太粗,Agent 会发挥;约束粒度太细,Agent 会僵化。这个分寸感,只能靠反复实测去掌握。
如果你正在规划自己的第一个 Skill,我建议从一个你能拿到真实反馈的小场景切入,比如代码安全审计就是一个不错的领域。它既有客观标准(漏洞是否存在、严重程度如何),又有主观判断空间(修复优先级、业务影响分析),非常适合用来理解“哪些环节该交给脚本,哪些环节该交给模型”。
最后分享一个小技巧:如果你在调试时发现 Agent 行为总是不稳定,不妨把 SKILL.md 里的内容减少 30% 再测试。很多时候,“不稳定”不是内容不够,而是约束太多导致模型不知道该优先听哪条。删掉那些可有可无的描述,给 Agent 留出清晰的执行主线,输出的稳定性往往反而更高。