如果你最近在关注 Agent 相关技术,应该会发现一个现象:B站、知乎、公众号上“Agent Skills 开发”类的教程越来越多,甚至已经有“全 259 集”“零基础七天从小白到大神”这样的标题出现。坦白说,我不太建议你迷信“七天速成”的说法,但“Agent Skills”本身值得你花时间认真学,因为它很可能是 Agent 应用从“演示能用”走向“生产可用”的关键一块拼图。
为什么这么说?过去两年,大家讨论 Agent 时最常问的问题是“用哪个框架”“接哪个模型”“要不要 RAG”。但等真正把 Agent 放到业务里,你会发现最卡脖子的往往不是模型智商,而是模型面对具体任务时缺少一套可复用、可维护、可约束的“职业技能”。一个能写诗、能聊天的模型,和一个能帮你按公司规范生成 Git 提交信息、整理周报、巡检日志的模型,差别不在底座模型,而在外面挂了多少高质量的 Skills。
这篇文章我会从开发者的视角,把 Agent Skills 的本质、它与 Tool/Workflow 的区别、零基础学习路线、环境准备、一个完整的 Skill 手写示例、接入与验证方式、常见坑以及工程化建议一次讲透。读完你至少能自己写一个可以跑通的最小 Skill,并且知道后续该往哪个方向深入。
1. 为什么 Agent 会“聊得很好,但干不了活”
先看一个典型场景。你给大模型配了 API Key,让它帮你总结文档、生成代码,它通常表现不错。但如果你让它“帮我把这个仓库的改动整理成符合团队规范的提交信息”,它往往会直接开始编一段看起来很合理、实际无法落地的 commit message,因为它看不到你真正暂存了哪些文件,也不了解你团队的规范。
这就暴露出一个核心问题:大模型本身是一个“推理引擎”,而不是一个“执行引擎”。它知道 commit message 长什么样,但它不知道当前代码仓库发生了什么;它能告诉你“应该怎么做”,但无法直接读取你的 Git 暂存区、文件系统、数据库或内部系统。
于是社区里出现了几种解决方案:
- Function Calling / Tool Calling:让模型在推理时请求调用一个预先定义好的外部函数。
- Agent / Workflow:把多个模型调用和工具调用编排成一条复杂链路。
- MCP 这类协议:让模型能够通过标准接口连接外部数据源和工具。
这些方案都在解决“让模型能做事”的问题。但要做到“做得好、做得稳、可复用”,还需要一个更贴近业务能力表达的封装层。Agent Skills 正是在这个背景下受到关注。
你可以这样理解:Tool 是给 Agent 的“四肢”,解决能不能做到的问题;Skill 是给 Agent 的“岗位说明书 + 工具箱”,解决的是“接到一个任务时,知道该按什么流程、用哪些工具、遵守什么约束来完成”的问题。
所以,判断一个 Agent 能不能真正落地,不要只看它接了哪些模型、有没有 RAG,要看它为具体岗位沉淀了多少个高质量的 Skills。这也是我觉得 Agent Skills 值得单独立项学习的原因。
2. Agent Skills 是什么:它与 Tool、Workflow 的边界在哪里
在开始实践前,先把几个容易混淆的概念理清楚。很多教程讲到后面,会把 Skill、Tool、Prompt 混在一起,导致读者越学越乱。
2.1 Agent Skills 的直观定义
一个 Agent Skill 是一段可描述、可复用、自包含的“能力包”。它通常包含:
- 一个说明文件:告诉模型这个技能是干什么的、什么时候该用、该怎么用。
- 一段或多段实现逻辑:可以是 Python 脚本、Shell 命令、配置文件或文档模板。
- 必要的依赖与资源:例如一个 JSON Schema、一份术语表、一组校验规则。
当一个 Agent 遇到任务时,它会先从已注册的 Skills 列表里找到匹配项,读取该技能的说明,然后按照说明调用实现逻辑,最后把执行结果返回给用户。
2.2 与 Tool 的区别
Tool 通常是原子的,比如“获取天气”“计算两个日期差”“执行一条 SQL”。它输入明确、输出明确,几乎不需要模型做流程判断。
Skill 则是“完成一项任务所需的完整方法”。它内部可能包含多个步骤,也可能调用多个 Tool。比如“给客户生成一封天气预警邮件”是一个 Skill,它可能需要:
- 查询目标客户的联系方式和订阅偏好;
- 获取未来几小时天气预警;
- 按客户模板生成邮件正文;
- 调用发送接口或生成待发送草稿。
如果只给 Agent 一个“查天气”的 Tool,模型仍然不知道完整流程;只有把完整流程封装成 Skill,Agent 才能稳定复现这套行为。
2.3 与 Workflow / 智能体工作流 的区别
Workflow 更像一段预设好的、不可随意跳步的流程,比如“先查库存,再算价格,再生成订单”。其执行路径是预先定义好的。
Skill 则更偏向“能力组件”,可以被不同的 Workflow 复用。同一个“生成周报”的 Skill,既能在一个定时任务里被调用,也能在用户和机器人对话时被调用。
我把它们的关系画成一张简单对应表:
| 名称 | 解决问题的层次 | 典型粒度 | 是否可被多个场景复用 |
|---|---|---|---|
| Prompt | 告诉模型怎么思考 | 指令文本 | 较弱,通常绑定场景 |
| Function / Tool | 让模型能调用外部能力 | 原子动作 | 中等 |
| Workflow | 把多个步骤编排成固定流程 | 流程链路 | 较弱,常为特定业务定制 |
| Agent Skill | 把完成某类任务的知识、工具、规范和实现封装起来 | 能力包 | 强,可被多个 Agent 或场景复用 |
从这张表可以看到,Skill 不是比 Tool 更高级的替代品,而是位于 Tool 之上的组织层。你在实际项目里通常先有一批基础 Tool,再围绕具体业务场景把它们封装成 Skills。
3. 零基础学习 Agent Skills:先认清这条路线,再动手
很多人被“七天从小白到大神”吸引,但实际学习时容易踩两个坑:一是堆概念不写代码,二是直接去看复杂的多 Agent 系统,结果被调度、记忆、编排这些概念劝退。
从工程角度看,我更建议你按照下面这条“从下到上”的路线学习。
3.1 阶段一:先跑通一次“模型调用 Tool”
不要一上来就构建 Skill 平台。建议先在你的开发环境里,用任意一个大模型 API,实现一个最简单的 Function Calling 例子。
目标是搞清楚:当模型说“我想调用获取天气函数”时,API 返回的 tool_call 结构长什么样,你的代码如何根据它执行函数并把结果回传给模型。
这个阶段不需要写很复杂的代码,两三百行以内就够了,但能帮你建立“模型与外部世界通过工具交互”的基础认知。
3.2 阶段二:理解 Skill 是“Prompt + Tool + 流程”的封装
请记住一个公式:
Agent Skill = 清晰的触发描述 + 可执行的实现逻辑 + 必要的约束规范
如果你现在能写出一个可以正确运行的 Tool,下一步就是把它的使用说明写得更结构化、更可被发现。比如不要只给模型一个叫generate_commit_message()的函数,而是给它一段“当用户准备提交代码、需要生成符合团队规范的提交信息时,请先读取暂存区文件列表,再调用 generate_commit_message()”的描述。这就是 Skill 的雏形。
3.3 阶段三:手写一个最小可用的 Skill
建议挑选一个你日常工作里高频、重复、规则明确的小任务。
例如:
- 把一段 Markdown 格式化为团队指定的排版风格;
- 根据 Git 暂存区内容生成提交信息;
- 将 CSV 数据按指定规则清洗并输出报告;
- 提取会议记录中的 TODO 并按负责人分组。
这个阶段最重要的目标是“能在本地跑通”:你的 Skill 文件能被 Agent 正确加载,能被模型主动触发,能返回可用的结果。
3.4 阶段四:加日志、加校验、加安全边界
当 Skill 能跑通后,再回头看工程化问题:脚本出错时是否把错误信息传回给了模型?模型是否会擅自执行危险操作?Skill 是否会把不该暴露的敏感信息读入上下文?
这一阶段决定了你做的到底是“玩具”还是“工具”。
3.5 阶段五:研究复杂场景
做完以上过程后,你再去学多 Agent 系统、复杂 Workflow、MCP、基于记忆的技能编排,都会从容很多。因为你会发现,很多看似高深的概念,本质上都是为了解决某些 Skills 在复杂环境下的协作问题。
所以,与其被视频课程播放量带着走,不如按这条路线给自己定下明确产出:“我第一个能跑的 Skill 是什么”。只要它真的能在对话里被模型调用并产生正确结果,就说明你已经跨过最难的入门门槛了。
4. 环境准备与前置条件
Agent Skills 的各个框架之间没有统一标准,但核心技术栈比较稳定。为了让你后面的示例可以直接运行,我按最通用的开发环境来做说明。
4.1 建议环境清单
| 工具 | 建议要求 | 用途 |
|---|---|---|
| 操作系统 | Windows / macOS / Linux 均可 | 本示例以命令行为主 |
| Python | 3.9 或更高版本,版本请以实际项目为准 | 编写 Skill 脚本与验证 |
| Git | 2.x 及以上 | 演示 Git 相关 Skill,也用于版本管理 |
| 代码编辑器 | VS Code 或任意熟悉编辑器 | 编写 SKILL.md 与脚本 |
| 大模型运行环境 | 支持 Function/Tool Calling 的 API 或本地模型服务 | 后续接入测试 |
注意:本文代码不会依赖某个特定厂商的 SDK,只使用 Python 标准库和 Git 命令,所以你可以先在纯本地环境把 Skill 内容写好、把脚本跑通,然后再接 Agent 运行时。
4.2 需要提前理解的三个概念
第一,工具描述(Tool Description)。模型判断什么时候调用工具,主要靠工具的 name 和 description,描述写得越好,调用命中率越高。
第二,本地执行能力。当前主流的 Agent 客户端的做法,是让 Skill 脚本在本地环境中以受控方式执行,这可能带来权限风险,需要提前做好最小权限设计。
第三,技能目录。多数实现约定:每个 Skill 是一个独立目录,目录里至少要有一个类似SKILL.md的说明文件和对应的实现文件。把目录放到 Agent 能扫描到的位置,技能即被注册。
这里需要提醒一句:不同产品对 Agent Skills 的目录结构和元数据字段可能不同。本文写的是社区常见的通用模式,你在接入具体产品时要以该产品的官方文档为准,但核心思想和流程是一致的。
5. 从零手写一个 Skill:目录、描述、代码完整示例
为了让示例可运行、不涉及真实业务数据,我选了“生成 Git 提交信息”这个任务。它的规则清晰、贴近开发场景,也非常容易验证。
5.1 先建立 Skill 目录结构
假设你准备了一个 Agent 工作目录,名为my-agent-workspace。先创建下面这个结构:
my-agent-workspace/ └── skills/ └── commit-message-generator/ ├── SKILL.md ├── requirements.txt └── generate_commit_message.pyskills/是技能根目录;commit-message-generator/是这个 Skill 的目录;SKILL.md是这个 Skill 的说明文件,也是 Agent 判断何时触发该技能的根本依据;generate_commit_message.py是实际执行逻辑;requirements.txt预留项目依赖声明,如果只用标准库,可以留空;
5.2 编写 SKILL.md
SKILL.md是 Agent Skills 开发中最重要的文件。模型不会直接阅读你的 Python 源码,它先读的是SKILL.md,只有描述匹配当前用户任务时,它才会继续使用技能内提供的脚本。
下面是一个适合放入SKILL.md的内容:
--- name: commit-message-generator description: 根据当前 Git 暂存区变更,生成符合 Conventional Commits 规范的提交信息。当用户需要提交代码、编写 commit message、整理提交记录、查看这次改动的类型时使用。 --- # Commit Message Generator 你的任务是根据 Git 暂存区变更,生成一条简洁、准确的提交信息草稿。 ## 执行步骤 1. 获取暂存区变更文件列表,使用以下命令: git diff --cached --name-only 2. 根据变更文件路径和内容,判断本次提交的类型: - feat: 新功能 - fix: 缺陷修复 - docs: 文档变更 - test: 测试相关变更 - refactor: 重构,不影响功能的代码调整 - chore: 构建、CI、依赖等杂项 3. 生成提交信息,格式如下: <type>(<scope>): <subject> 例如: fix(parser): 修复日期解析边界问题 ## 安全边界 - 只允许读取 Git 暂存区内容; - 不要直接替用户执行 git commit; - 如果用户提供了明确指令要求执行提交,请先生成草稿并让用户确认。为什么description这一段很重要?因为模型在做任务规划时,会遍历所有可用 Skill 的 description,判断哪一个最适合当前任务。“根据 Git 暂存区变更生成提交信息”这句话越具体,模型就越不容易漏选或错选这个 Skill。
5.3 编写实现脚本
接下来创建generate_commit_message.py。这里我刻意让脚本只做“读取暂存区 + 生成建议文本”,不执行git commit,这是合理的默认安全边界。
#!/usr/bin/env python3 """ 文件路径:my-agent-workspace/skills/commit-message-generator/generate_commit_message.py 作用:读取 Git 暂存区变更文件列表,根据 Conventional Commits 规范生成提交信息建议。 安全说明:本脚本只读不写,不会执行 git commit,不会修改任何文件。 """ import subprocess import sys from pathlib import Path def get_staged_files() -> list[str]: """获取当前仓库已暂存的文件列表。""" try: result = subprocess.run( ["git", "diff", "--cached", "--name-only"], capture_output=True, text=True, check=True, ) except (subprocess.CalledProcessError, FileNotFoundError): print("错误:当前目录可能不是 Git 仓库,或者 Git 命令不可用。", file=sys.stderr) print("请先在 Git 仓库中执行 git add 后再运行本脚本。", file=sys.stderr) sys.exit(1) files = result.stdout.strip().splitlines() return [f for f in files if f.strip()] def decide_commit_type(file_paths: list[str]) -> str: """通过文件名和路径特征,粗略推断提交类型。""" joined_text = "\n".join(file_paths).lower() if "test" in joined_text or "spec" in joined_text: return "test" if "doc" in joined_text or ".md" in joined_text: return "docs" if "fix" in joined_text or "bug" in joined_text or "hotfix" in joined_text: return "fix" if "refactor" in joined_text: return "refactor" if "chore" in joined_text or "ci" in joined_text or ".github" in joined_text: return "chore" return "feat" def detect_scope(file_paths: list[str]) -> str: """提取首个文件路径的根目录或一级目录名作为范围,如果没有则返回空字符串。""" for file_path in file_paths: parts = Path(file_path).parts if len(parts) >= 2: return parts[0] return "" def build_commit_message(file_paths: list[str]) -> str: """根据文件列表生成一条提交信息建议。""" commit_type = decide_commit_type(file_paths) scope = detect_scope(file_paths) if scope: header = f"{commit_type}({scope}): 更新 {Path(file_paths[0]).name}" else: header = f"{commit_type}: 更新 {Path(file_paths[0]).name}" body_lines = ["本次变更涉及文件:"] body_lines.extend(f"- {path}" for path in file_paths) body_lines.append("") body_lines.append("请根据真实改动内容,在确认后补充或调整该提交信息。") return "\n".join([header, "", *body_lines]) def main() -> None: staged_files = get_staged_files() if not staged_files: print("当前暂存区为空,请先执行 git add。") sys.exit(0) print(build_commit_message(staged_files)) if __name__ == "__main__": main()这段代码的核心逻辑如下:
get_staged_files()通过git diff --cached --name-only读取已暂存文件,这里只读不写;decide_commit_type()根据路径中的关键词推断feat、fix、docs等类型;detect_scope()用文件路径的第一层目录作为 scope;build_commit_message()最终生成一条提交信息草稿;- 如果当前目录不是 Git 仓库或没有暂存任何文件,脚本会明确提示,而不是静默输出错误结果。
你可以用一个真实仓库来实验:随便改一个文件,执行git add .,再运行这个脚本。虽然生成结果比较简单,但它已经让 Agent 具备了“基于实际仓库状态生成规范提交信息”的能力,而不是让模型凭空编造。
6. 把 Skill 接入 Agent:配置式与编程式两种方式
Skill 写好之后,下一步是让 Agent 在对话中能看到它。不同 Agent 平台接入方式不同,从实现原理上分,主要有配置式和编程式两类。
6.1 配置式接入
如果你的 Agent 客户端支持技能目录配置,那么直接把skills/根目录告诉 Agent 即可。常见的配置大概是这个样子:
{ "agent_name": "local-coding-assistant", "skill_registry": "./skills", "enabled_skills": [ "commit-message-generator" ], "permission": { "allow_commands": [ "git diff --cached", "git status" ], "deny_commands": [ "git push", "git commit" ] } }注意,这里deny_commands的作用是安全兜底。即使SKILL.md已经声明“不要主动执行 git commit”,运行时也应在权限层面对敏感命令做二次限制。
6.2 编程式接入
如果你使用的是 Function Calling 风格的框架,你可以把 Skill 脚本封装成一个本地工具函数,并注册成模型的可用工具。
以下代码用通用结构示意,不依赖特定 SDK:
# 文件路径:my-agent-workspace/agent_skill_adapter.py """ 将某个 Skill 脚本包装成模型可调用的工具函数。 这段代码使用通用伪接口,实际使用时请替换为对应框架的 Tool 注册方式。 """ import subprocess from pathlib import Path def run_commit_message_generator() -> str: """运行技能脚本并返回输出。""" script_path = Path(__file__).parent / "skills" / "commit-message-generator" / "generate_commit_message.py" result = subprocess.run( ["python", str(script_path)], capture_output=True, text=True, check=False, ) return result.stdout if result.returncode == 0 else result.stderr # 在接入大模型时,可以注册为如下形式的 function: commit_message_tool = { "type": "function", "function": { "name": "commit_message_generator", "description": "根据当前 Git 暂存区变更文件,生成符合 Conventional Commits 规范的提交信息建议。", "parameters": { "type": "object", "properties": {}, "required": [] } } } # 模拟工具分发:当模型返回需要调用 commit_message_generator 时执行 def dispatch_tool_call(tool_name: str) -> str: if tool_name == "commit_message_generator": return run_commit_message_generator() raise ValueError(f"未知工具: {tool_name}")这段代码要理解三个点:
description保持和SKILL.md一致,让模型知道何时调用;- 实际执行时不直接把任意模型参数传给 Shell,而是固定调用预先写好的脚本;
- dispatch 层只允许白名单内的技能名,避免模型通过工具名注入额外命令。
6.3 两种接入方式如何选
配置式适合用现成 Agent 产品的场景,你只需要维护好技能目录;编程式适合自研 Agent 或需要深度控制运行边界的场景。从学习角度,我建议你都跑通一遍:先用配置式快速验证效果,再用编程式理解底层工具分发逻辑。
7. 运行与效果验证:三层验证法
很多初学者把 Skill 写完,复制进去之后就直接试对话,发现 Agent 不调用,于是开始乱改。正确的验证方式应该是分层推进,先验证脚本,再验证注册,最后验证模型对话链路。
7.1 第一层:验证脚本本身
先不启动任何 Agent,直接在本地仓库运行脚本。准备步骤:
cd my-agent-workspace # 先进入任意一个 Git 仓库,或者把这个目录初始化为仓库 git init # 创建一个测试文件 echo "test content" > sample.txt # 暂存变更 git add sample.txt # 直接执行 Skill 脚本 python skills/commit-message-generator/generate_commit_message.py预期输出结果类似:
feat: 更新 sample.txt 本次变更涉及文件: - sample.txt 请根据真实改动内容,在确认后补充或调整该提交信息。如果看到这个输出,说明脚本本身可用。如果在这一层就报错,不要再往下排查 Agent,先把“目录是否在 Git 仓库内”和“文件是否已 git add”这两个问题解决。
这里也补充一个易错点:不要在一个没有.git目录的普通文件夹里运行这个脚本,结果会提示“当前目录可能不是 Git 仓库”。
7.2 第二层:验证技能是否被注册加载
这一层取决于你使用的 Agent 客户端。通常做法是打开调试模式或技能管理面板,确认commit-message-generator出现在技能列表中。
如果列表里找不到这个技能,优先检查:
- 技能目录是否放在 Agent 指定扫描的根目录下;
- 目录名和
SKILL.md文件名是否拼写正确; SKILL.md是否包含合法的 metadata 字段,如name和description。
7.3 第三层:验证模型是否会主动调用
在对话窗口输入类似:
“我刚改完一个文件,已经 git add 了,帮我生成一条提交信息。”
如果 Agent 正确触发技能,你应该能在调试日志中看到类似“skill selected: commit-message-generator”的记录,然后看到脚本执行输出。如果没有触发,先不要怀疑模型能力,回看description中的触发条件是否足够清楚。这是最常见的问题,后面会专门说。
7.4 如何判断效果达标
一个合格的“最小 Skill 闭环”应该满足三个条件:
- 脚本在本地可直接运行;
- 技能出现在 Agent 的技能注册列表中;
- 通过自然语言提问,Agent 确实完成了技能调用并返回结果。
三个条件全部满足,你的第一个 Agent Skill 就算真正跑通了。
8. 常见问题与排查思路
实际开发中,新手遇到的大部分问题并不在算法层面,而在描述、路径、权限和运行环境这几类。下面整理了一份高频问题排查表。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 模型从不调用该技能 | SKILL.md的 description 太宽泛,或只写了功能名词,没有写触发场景 | 查看 Agent 调试日志,确认它是否能看到该技能 | 重写 description,让它包含“当用户需要……时使用”句式 |
| 技能出现但执行报错“目录不存在” | SKILL.md 中的脚本路径使用相对路径,且 Agent 工作目录与脚本所在目录不一致 | 在技能目录内执行一次脚本,检查相对路径是否成立 | 统一使用基于技能根目录的绝对路径,或采用运行时变量注入 |
| 脚本在命令行能跑,Agent 调用却失败 | Agent 运行在沙箱中,缺少 Git、Python 或被限制访问本地文件 | 在 Agent 环境中先执行python --version与git --version | 为技能补充环境检查;必要时调低沙箱限制或在隔离环境内安装依赖 |
| 模型调用了技能,但输出内容不准 | 模型的返回结果被截断,或脚本把错误信息打印到了 stdout 而不是 stderr | 看完整返回日志,确认执行结果是否完整回传 | 关键错误消息输出到 stderr;把脚本输出标准化为文本或结构化 JSON |
| 技能把过多敏感信息带回上下文 | 脚本读取了大范围文件内容,比如整份 diff 或整个目录 | 审计脚本读取范围,查看日志中的输入 token 消耗 | 收紧读取范围,只读取完成当前任务必需的最小字段 |
| 两个技能可以同时解决同一个任务 | 技能职责边界重叠 | 检查两个技能的 description 是否描述相近的触发场景 | 合并为一个技能,或为每个技能划定更窄的使用前提 |
| 技能能跑,但结果不符合团队规范 | SKILL.md 中没有写清楚团队约束或规范示例 | 人工检查一次输出,找出规则缺口 | 把团队规范原文和正反示例写入 SKILL.md |
从这些案例里能看出一个共性:Agent Skills 开发调试过程,很大一部分是在调试“信息如何被模型理解”,而不只是“函数能不能跑”。所以每次出问题时,建议先问自己一句:模型在读我的 SKILL.md 和日志时,它看到的信息是否足够明确?
9. 工程落地、最佳实践与后续学习建议
如果你已经跑通了一个最小 Skill,接下来最重要的不是再多写十个类似技能,而是建立工程化意识。下面这些实践建议,是我认为 Agent Skills 开发中最值得花时间去做的部分。
9.1 技能命名与目录规范
技能目录名建议使用小写字母加中划线,比如commit-message-generator。名字要能直接体现业务能力,不要叫tool1、test_skill这类无法判断用途的名字。
SKILL.md中的 name 字段要保持稳定,因为运行时注册、日志追踪和版本升级都依赖这个标识。如果重命名,需要同步更新所有引用该技能的地方,否则会出现“技能已安装但调用不到”的隐蔽问题。
另外,每个 Skill 目录里建议放一个简短的README.md,记录该技能的维护人、适用场景、禁止行为。这个文件主要给人类开发者看,避免技能越改越模糊。
9.2 description 的写法是重中之重
模型是否调用某个技能,首先靠 description 做路由。这里分享一个实践中的写法模板:
当用户需要<完成某个任务>时,使用本技能。 适用场景包括:<列举3到5个典型用户表达>。 不适用场景:<写出边界,避免误触发>。好的 description 应该是“行为触发式”的,而不是“名词解释式”的。
弱写法:
一个用于生成提交信息的工具。强写法:
当用户准备提交代码、需要生成 git commit message、或想要把当前暂存区改动整理成规范提交说明时使用。后一种写法把动作和场景都写清楚了,模型匹配的准确率会明显提高。
9.3 从第一天就做好最小权限与安全边界
Agent Skills 最让人担心的问题不是模型不够聪明,而是模型在本地执行时可能触碰到你不想让它碰的东西。下面几条建议务必尽早养成:
- 每个技能只授予完成自己任务所需的权限;
- 有破坏性风险的命令,如删除文件、推送远端、执行写操作,默认禁止,必要时让用户二次确认;
- 不要让技能读取范围之外的敏感文件,比如密钥文件、配置中的密码字段;
- 对于批量修改和外部调用的技能,先在小范围测试集上验证;
- 日志里不要完整记录敏感字段,可做脱敏处理。
以本文的提交信息生成技能为例,它只做“读取暂存区 + 输出建议”,不代执行git commit,这就是一个刻意设计过的安全边界。真实业务中,绝大部分技能都应该遵循类似原则:先给用户一个可审查的结果,再由用户决定是否执行。
9.4 为技能建立版本和质量评估机制
当技能数量多起来之后,你会发现改动一个 SKILL.md 可能会改变模型在大量场景下的行为。因此,最好给技能目录纳入 Git 版本管理,并在改动时记录“变更原因”。
评估一个技能质量,不建议只看“技能数量”,更建议看这四类指标:
| 指标 | 含义 |
|---|---|
| 触发命中率 | 用户提出相关任务时,模型是否选择该技能 |
| 执行成功率 | 选中技能后,脚本是否无错跑通 |
| 结果被采纳率 | 模型产生的结果是否真实可用 |
| 副作用次数 | 是否出现误执行、越权、泄露等风险行为 |
在团队协作时,最好每个技能有一个明确负责人。技能的改动走 review 流程,和代码改动同样严肃。很多 Agent 项目从“demo”走向“生产”时,最大的管理成本往往不是模型参数,而是这些技能的版本和质量控制。
9.5 下一步你可以这样实践
如果你现在想继续深入,建议按顺序做下面三件事:
第一,把本文的commit-message-generator改成你团队实际使用的提交规范。比如加入任务号关联、审核人提醒、Breaking Change 提示。这一步能帮你体会“把隐式规则显式化”的价值。
第二,挑一个你日常工作里最花时间的信息处理任务,把它设计成 Skill。可以从“整理会议待办”“汇总多个日志文件异常”“生成项目周报框架”这类规则较清晰的任务开始。
第三,尝试让你的多个 Skill 组合成一个完整流程。比如“读取 Git 变更 + 生成提交信息 + 按模块维度汇总提交记录”,观察多个技能之间如何协作。
写 Agent Skills 最忌讳的是沉迷框架和概念,迟迟不写第一个自己真正会用的技能。它和学习其他工程技术的路径完全一致:先把最小闭环跑通,再在真实反馈里修正,最后才谈得上规模化。
如果你能亲手完成一个“从脚本编写、说明文件编写、Agent 接入、日志验证到安全边界收紧”的完整流程,你对 Agent 应用开发的理解就已经超过大多数只看教程的初学者了。希望这篇文章能让你少走一点弯路,也建议收藏起来,真正动手时照着做一遍。