一句话定位:读完这篇,团队里从产品经理到研发架构师,所有人对"Skill 到底是什么"将达成共识。
1. 引言:从一个真实场景开始
假设你正在为一个微服务架构的工程团队构建 DevOps Agent。某天,研发同学在群里发了一句:
"master 上的流水线又挂了,这次不知道是依赖问题还是测试挂了,帮我看看。"
面对这个请求,如果只是一个传统的大模型,它可能会回复一段通用建议:"建议您检查构建日志、确认依赖版本、查看测试报告……"然后,什么实际帮助都没有。
但作为一个真正能干活的 DevOps Agent,它需要做到:
① 理解意图:这不是在问问题,而是请求诊断流水线故障
② 获取信息:调用 CI/CD 平台 API,拉取本次构建的完整日志和状态
③ 分类诊断:分析日志,判断是依赖下载失败、编译错误、测试未通过还是部署超时
④ 定位根因:如果是测试失败,定位到具体的失败用例和代码变更;如果是依赖问题,识别冲突的包版本
⑤ 尝试修复:根据故障类型自动执行修复动作 —— 回滚依赖、跳过 flaky test、触发重试
⑥ 生成报告:汇总诊断结论、修复动作和后续建议,回复研发同学
这六个步骤横跨了意图理解、日志分析、故障分类、根因定位、自动修复、结果汇报六个能力维度。单靠任何一种技术抽象都搞不定:
- 一条 Prompt[1] 能帮你分析日志文本,但它调不了 CI/CD 平台的 API 去拉日志。
- 一个 Tool[2](比如
get_pipeline_logs)能拉日志,但它不知道拿到日志后该怎么分类、怎么判断根因。 - 一个传统 Workflow[3] 能串起"拉日志→分析→修复"的流程,但面对"依赖冲突同时伴随一个 flaky test"这种复合故障时,它无法动态决定先处理哪个。
我们需要一种更高层的抽象,把这六种能力打包在一起。
这就是我们深入拆解的对象:Agent Skill。
2. Skill 的正式定义
2.1 一句话定义
Skill 是对 Agent 能力的结构化封装,它将意图理解、执行逻辑、工具调用、异常处理和安全约束打包为一个可独立开发、测试、部署和治理的能力单元。[1][2]
这个定义中的每个词都有其重量:
- 结构化封装:Skill 不是一段随意编写的脚本,它有严格的接口规范和元数据描述。
- 意图理解:Skill 明确声明自己能处理哪类问题,决定它是否会被 Agent 选中。
- 执行逻辑:包含具体的 Prompt 策略、流程编排与推理链。
- 工具调用:可以绑定外部的 API、数据库或本地函数,但工具只是能力的一部分。
- 异常处理:CI/CD 平台 API 超时怎么办?日志太长超出上下文窗口怎么办?Skill 内部需要有预案。
- 安全约束:自动回滚依赖、触发重试这些操作具有一定风险,哪些可以自动执行,哪些必须经过人工确认,都要内建在 Skill 中。
2.2 展开定义:Skill 的六大构成要素
任何 Skill,无论复杂与否,都可以被拆解为六个固定要素。它们构成了 Skill 的"解剖图",也是后续三篇文章展开的主线骨架。
┌─────────────────────────────────────────────────────────────┐
│ Skill 解剖图 │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ ① Identity(身份标识) │ │
│ │ 名称 · 版本 · 描述 · 标签 · Owner · 创建时间 │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
│ │ ② Intent(意图定义) │ │ ③ Contract(输入输出契约)│ │
│ │ 触发条件 · 意图槽位 │ │ Input Schema · Output │ │
│ │ 置信度要求 │ │ Schema · 对话契约 │ │
│ └──────────────────────┘ └──────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ ④ Logic(执行逻辑) │ │
│ │ Prompt 策略 · 推理链 · 流程编排 · 条件分支 │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────┐ │
│ │ ⑤ Bindings(工具绑定)│ │ ⑥ Guardrails(安全护栏) │ │
│ │ 依赖的 Tool / API │ │ 权限 · 限流 · 熔断 │ │
│ │ 超时 · 重试 · 降级 │ │ 人机协同 · 审计日志 │ │
│ └──────────────────────┘ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
我们以贯穿本系列的 "流水线故障诊断 Skill" 为例,看看这六个要素在实际工程中长什么样。
SKILL.md:Skill 的唯一核心文件
一个 Skill 的全部定义,体现在一个 SKILL.md 文件中。这是所有主流 AI Agent 平台采用的标准格式[1][2]:YAML front matter 声明元数据,正文编写操作指令。
SKILL.md 的结构
┌────────────────────────────────────────────────────────┐
│ --- │
│ name: <skill-name> ← front matter │
│ description: <what this skill │ 由 Agent 平台解析 │
│ does and when to trigger it> │ 用于注册和语义检索 │
│ --- │
│ │
│ <Operational instructions for ← 正文 │
│ the agent to execute step by │ Agent 被触发后 │
│ step when this skill is │ 按此指令逐步执行 │
│ triggered.> │
└────────────────────────────────────────────────────────┘
front matter 必须包含两个字段[1]:
name:Skill 的唯一标识符,使用 kebab-case 命名(如pipeline-diagnosis)description:Skill 功能的自然语言描述。这是决定 Skill 能否被 Agent 正确召回的关键字段——Agent 平台通过对description的语义匹配来判断用户输入是否应触发此 Skill
正文 是给 Agent 执行的操作指令。它不是给人看的 README 文档,而是一份可执行的操作规程——告诉 Agent 被触发后具体一步步做什么、遇到异常怎么处理、输出什么格式的结果。
以下是一个最简 Skill 的示例,展示基础格式[1]:
---
name: roll-dice
description: Roll dice using a random number generator. Use when asked to roll a die (d6, d20, etc.), roll dice, or generate a random dice roll.
---
To roll a die, use the following command that generates a random number from 1
to the given number of sides:
```bash
echo $((RANDOM % <sides> + 1))
```
```powershell
Get-Random -Minimum 1 -Maximum (<sides> + 1)
```
Replace `<sides>` with the number of sides on the die (e.g., 6 for a standard
die, 20 for a d20).
下面是一个完整的复杂 Skill 示例——本文贯穿案例 "流水线故障诊断 Skill"。它展示了当 Skill 的业务逻辑较复杂时,SKILL.md 如何通过结构化的步骤、条件分支和安全约束来承载全部六个要素:
---
name: pipeline-diagnosis
description: When a CI/CD pipeline build fails, fetch the build logs, diagnose the failure type (dependency conflict, compile error, test failure, or deploy timeout), locate the root cause, and attempt auto-fix or provide fix suggestions.
---
When this skill is triggered, follow these steps in order.
## Step 1: Obtain pipeline information
Confirm you have the following parameters. If any required parameter is
missing, ask the user before proceeding.
- `pipeline_id` (required): the pipeline run ID, e.g. `pl-20260706-a3f7`
- `service_name` (optional): the microservice name (useful for monorepos)
- `branch` (optional, defaults to `master`): the git branch
If `pipeline_id` is missing, ask: "What is the pipeline ID or build link?"
If the user cannot provide it, fall back to querying the CI/CD platform for
the most recent failed build matching `service_name` and `branch`.
Maximum 2 rounds of clarification. After that, use the fallback strategy.
## Step 2: Fetch build logs
Call the CI/CD platform API to retrieve the full build log for the given
`pipeline_id`:
```bash
cicd-cli logs --pipeline-id <pipeline_id> --format json
```
In parallel, fetch the commit diff associated with this build:
```bash
git diff <base_commit>..<head_commit> --stat
```
If the CI/CD API times out, retry up to 2 times. If still failing, compare
against the last successful build's log instead.
If the log exceeds 500KB, stop and return an error asking the user to
download the log manually.
## Step 3: Diagnose failure type
Analyze the build log and classify the failure into one of these categories.
Use the diagnostic prompt at `prompts/system.md` for structured analysis.
- **dependency**: version conflicts, missing packages, resolution failures
- **compile**: syntax errors, type errors, missing symbols
- **test**: assertion failures, flaky tests, timeout on test suites
- **deploy**: health check failures, image pull errors, resource exhaustion
- **unknown**: none of the above patterns match
For each category, extract:
- The root cause (one paragraph)
- Affected files (list of file paths)
- Failed test names (if applicable)
- The commit that likely introduced the failure (from the diff)
## Step 4: Execute fix based on failure type
### If dependency:
1. Identify the conflicting package and versions from the log.
2. Query available versions:
```bash
dependency-cli versions --package <pkg_name>
```
3. Roll back to the last stable version:
```bash
dependency-cli rollback --package <pkg_name> --to-version <last_stable>
```
4. Trigger a rebuild:
```bash
cicd-cli trigger --pipeline-id <pipeline_id> --branch <branch>
```
**STOP and ask for user confirmation before executing the rollback.**
### If compile:
1. Locate the error file and line number from the log.
2. Cross-reference with the commit diff to identify who introduced the error.
3. Provide a fix suggestion in this format:
```
Error: <error_message>
File: <file_path> line <line_number>
Introduced by: <commit_hash> (<author>, <date>)
Suggestion: <fix_description>
```
Do NOT modify code automatically. Only provide suggestions.
### If test:
1. Extract the list of failed test names and their error messages.
2. Check if each failed test is a flaky test:
- A test is flaky if it has failed in fewer than 30% of the last 10 builds
AND the current commit does not modify its related code.
3. If flaky: rerun the build skipping those tests:
```bash
cicd-cli rerun --pipeline-id <pipeline_id> --skip-tests <flaky_test_names>
```
4. If not flaky: provide a failure analysis (same format as compile errors).
### If deploy:
1. Check the target environment status:
```bash
kubectl get pods -n <namespace> --field-selector=status.phase!=Running
```
2. If environment issue confirmed, prepare a rollback command:
```bash
kubectl rollout undo deployment/<service_name> -n <namespace>
```
**STOP and ask for on-call engineer confirmation before executing deploy
rollback.**
### If unknown:
Output the last 50 lines of error logs and recommend manual investigation.
## Step 5: Generate report
Summarize all findings and actions into a single report using this template:
```
## Pipeline Diagnosis Report
**Pipeline**: <pipeline_id>
**Branch**: <branch>
**Service**: <service_name>
**Failure Type**: <failure_type>
**Status**: <fixed / needs_manual_action>
### Root Cause
<root_cause_description>
### Action Taken
<action_description>
### Recommendation
<long_term_suggestion>
```
Output both the human-readable report above and a structured JSON object:
```json
{
"diagnosis": {
"failure_type": "<dependency|compile|test|deploy|unknown>",
"root_cause": "<string>",
"affected_files": ["<path>", "..."],
"failed_tests": ["<name>", "..."]
},
"fix_action": {
"action_taken": "<string>",
"fix_result": "<success|partial|failed>",
"new_pipeline_id": "<string or null>"
},
"summary": "<human-readable summary>"
}
```
六大要素在 SKILL.md 中的体现
回过头来看,六个要素全部在一个 SKILL.md 中得到了体现。SKILL.md 本身就是 Skill 的完整载体:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 要素 在 SKILL.md 中的位置 │
│ │
│ ① Identity front matter │
│ name = 唯一标识符 │
│ description = 功能描述 + 触发场景 │
│ │
│ ② Intent front matter 的 description 描述了触发场景 │
│ Step 1 定义了意图槽位(必填/选填参数) │
│ Step 1 的追问策略处理槽位缺失的情况 │
│ │
│ ③ Contract Step 1 定义了输入参数(名称、类型、必填/选填) │
│ Step 5 定义了输出结构(报告模板 + JSON 格式) │
│ Step 1 的追问策略 = 对话契约 │
│ │
│ ④ Logic Step 2 ~ Step 4 = 核心执行逻辑 │
│ Step 3 的分类规则 = Prompt 策略 │
│ Step 4 的条件分支 = 流程编排 │
│ Step 3 引用 prompts/system.md = 推理模板 │
│ │
│ ⑤ Bindings Step 2 中的 cicd-cli / git 命令 = 工具调用 │
│ Step 4 中的 dependency-cli / kubectl = 工具调用 │
│ 每个调用隐含了超时和重试策略(由 Agent 平台执行)│
│ │
│ ⑥ Guardrails Step 1 "Maximum 2 rounds" = 追问限制 │
│ Step 2 "log exceeds 500KB, stop" = 资源保护 │
│ Step 4 "STOP and ask for confirmation" = 人机协同│
│ Step 4 "Do NOT modify code automatically" = 操作边界│
│ │
└─────────────────────────────────────────────────────────────────┘
可以看到,六个要素不需要额外的配置文件来承载。front matter 提供了 Identity 和 Intent 的元数据入口;正文的五个步骤依次覆盖了 Contract(Step 1 输入 + Step 5 输出)、Logic(Steps 2-4)、Bindings(Steps 2-4 中的命令调用)和 Guardrails(嵌入在各步骤中的安全约束)。
这就是 SKILL.md 格式的设计精髓:用一个文件、一种统一的结构,同时满足机器解析(front matter)和 Agent 执行(正文)的双重需求。
2.3 工程目录结构
在实际工程中,Skill 以目录的形式组织。SKILL.md 是目录中唯一必须存在的文件,其他文件都是可选的支撑资源:
skills/
└── pipeline-diagnosis/ # 每个 Skill 一个独立目录(kebab-case)
│
├── SKILL.md # ★ 必须:Skill 的完整定义
│ front matter(注册检索)+
│ 正文(执行指令)
│
├── prompts/ # 可选:外部 Prompt 模板
│ ├── system.md # 当 SKILL.md 中引用外部 Prompt 时
│ └── few_shots/ # (如 Step 3 的 "Use the prompt
│ ├── dependency.md # at prompts/system.md")
│ └── test_failure.md #
│
├── scripts/ # 可选:可执行脚本
│ └── check_flaky.py # 当 SKILL.md 中引用外部脚本时
│
├── references/ # 可选:参考资料
│ └── failure_patterns.md # 故障模式速查表等
│
└── assets/ # 可选:其他资源文件
└── report_template.md # 报告模板等
各目录的作用:
- SKILL.md(必须):Skill 的全部定义,是 Agent 平台加载 Skill 的唯一入口[1]
- prompts/(可选):当 Skill 的执行逻辑中需要调用外部 Prompt 模板时使用。例如,SKILL.md 中写"Use the diagnostic prompt at
prompts/system.md",Agent 执行到该步骤时会加载对应的 Prompt 文件 - scripts/(可选):当 Skill 需要执行自定义脚本时使用[2]
- references/(可选):当 Skill 需要引用领域知识文档时使用[2]
- assets/(可选):其他支撑资源,如报告模板、配置文件等[2]
关键原则:所有支撑目录的存在都是因为 SKILL.md 中引用了它们。如果 SKILL.md 不引用任何外部文件,那整个 Skill 目录中就只有一个 SKILL.md——这也是完全合法的。
3. Skill 的边界辨析
在团队沟通中,最容易混淆的是 Skill、Tool、Prompt、Workflow 甚至 Agent 这几个概念。概念混淆会导致架构混乱——你会在设计时做出错误的抽象层级判断。我们需要逐一划清边界。
3.1 Skill vs Tool
- Tool(工具):一个原子操作,比如"调用 CI/CD 平台的
get_pipeline_logsAPI"、"执行一条 SQL 查询"。它是无状态的、机械的,不包含业务理解。[2] - Skill(技能):一整套能力。Skill 是 Tool 的消费者。一个"流水线故障诊断 Skill"内部调用了"CI/CD 平台 Tool"、"Git Tool"和"依赖仓库 Tool",并在这之上包裹了日志分析、故障分类、修复策略选择和异常处理逻辑。
关系:把 Tool 当成 Skill,就像把万用表当成整个故障排查服务——工具只是能力的组成部分,不是能力本身。
3.2 Skill vs Prompt
- Prompt(提示词):单次模型推理的指令文本。它不绑定任何工具,也不包含流程控制逻辑。[1]
- Skill(技能):是一个可运行的能力实体。Prompt 只是它内部 ④ Logic 的一个组件,Skill 还包含工具绑定、输入输出契约、对话交互协议和安全约束等工程化支撑。
关系:如果把 Agent 比作一个工程师,Skill 是他的"专业能力"(比如"能排查 CI/CD 故障"),Prompt 是他执行该能力时的"思维框架"。只有 Prompt 没有 Skill 的工程支撑,Agent 就只能给你分析建议但接不进你的 CI/CD 系统。
3.3 Skill vs Workflow(传统工作流)
- Workflow(工作流):预定义的固定流程(如 BPMN),节点之间的路由关系在设计时确定,运行时机械执行。[3]
- Skill(技能):Skill 内部可以包含 LLM 的动态决策,执行路径可以在运行时根据上下文改变。
这个区别比"灵活 vs 死板"更本质:Workflow 的流程在设计时就写死了;Skill 的流程在运行时由 LLM 根据上下文动态决定。
举个例子:同样是处理构建失败,Workflow 预设了"拉日志 → 分析 → 重试"的标准路径。但如果日志显示"依赖冲突且存在一个 flaky test",Skill 可以让 LLM 判断应该先处理依赖冲突(因为它是阻塞性的),跳过 flaky test 后再重试——而不是按 Workflow 预设的顺序一步步走。这种基于上下文的动态决策能力是 Skill 区别于 Workflow 的本质。
3.4 Skill vs Agent
这是读者最容易产生的疑问:"流水线故障诊断"看起来已经是一套完整的逻辑了,为什么不直接做成一个 Agent?
答案在于理解 Agent 和 Skill 的本质关系。最简明的类比:
Agent = 一个"人"(有大脑,能思考,能做决策)
Skill = 这个人掌握的"一项技能"
Tool = 这个人使用的"一件工具"
一个 DevOps Agent(人)可能掌握多项技能(Skill):
┌─────────────────────────────────────────────────────────────┐
│ DevOps Agent │
│ │
│ "我是一个 DevOps 工程师,当用户问我问题时, │
│ 我判断该用哪项技能来帮忙。" │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 流水线故障诊断 │ │ 数据库迁移 │ │ Code Review │ │
│ │ Skill │ │ Skill │ │ Skill │ │
│ │ │ │ │ │ │ │
│ │ 内部用: │ │ 内部用: │ │ 内部用: │ │
│ │ CI/CD API │ │ DB CLI │ │ Git API │ │
│ │ Git API │ │ Schema Diff │ │ Lint 工具 │ │
│ │ 依赖仓库 API │ │ 工具 │ │ LLM │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
那如果把"流水线故障诊断"做成独立的 Agent 会怎样?
问题 1:复用困难。 值班机器人也需要诊断 CI 故障。做成 Agent,你得复制整套系统;做成 Skill,值班机器人直接调用同一个 Skill 即可。
问题 2:演进困难。 CI/CD 平台 API 升级了 v2。做成 Agent,你需要改 DevOps Agent 里的诊断逻辑、改值班机器人里的诊断逻辑、改 ChatOps 工具里的诊断逻辑——三处都改,漏了一处就是线上 Bug。做成 Skill,只改一处,灰度发布,所有调用方自动生效。
问题 3:测试困难。 你只想验证"日志分析准不准",做成 Agent 你得启动整个系统(对话管理、上下文管理、响应生成……),做成 Skill 你直接对它跑 100 条测试用例。
一句话总结:
Agent 是雇主,Skill 是员工。你不会因为需要有人能修水管,就专门成立一家"修水管公司"(Agent),而是雇一个会修水管的工人(Skill),让他可以在不同的公司(Agent)里干活。
那什么时候应该做成 Agent 而不是 Skill?当一个能力同时满足以下条件时:
- 它有自己的完整交互流程(不只是被调用,还需要主动发起对话)
- 它有独立的部署和运行需求(作为独立服务 7×24 运行)
- 它不打算被其他 Agent 复用
- 它的价值在于"作为一个智能体持续运行"而不是"作为一项能力被按需调用"
"流水线故障诊断"不满足这些条件——它解决的是一个具体问题,需要被多个系统复用,需要独立演进和独立测试——所以它应该做成 Skill,而不是 Agent。
3.5 对比总结表
| 维度 | Agent(智能体) | Skill(技能) | Tool(工具) | Prompt(提示词) | Workflow(工作流) |
|---|---|---|---|---|---|
| 本质 | 一个运行中的"角色"系统 | 一个可被调用的"能力"模块 | 一个原子操作接口 | 一次推理的指令文本 | 一个预定义的流程 |
| 粒度 | 系统级 | 能力级 | 操作级 | 指令级 | 流程级 |
| 角色 | 调度者 + 决策者 | 执行者 | 被调用者 | 推理引导者 | 流程编排者 |
| 包含 LLM 决策 | 是(核心) | 是(核心) | 否 | 是(全部) | 通常无 |
| 包含工具调用 | 通过 Skill 间接使用 | 显式声明依赖 | 自身即服务 | 否 | 可能 |
| 执行路径 | 运行时动态选择 Skill | 运行时动态决策 | 固定 | 单次推理 | 设计时确定 |
| 可独立测试 | 需要启动整个系统 | 是(轻量级) | 是 | 否 | 是 |
| 可被复用 | 困难(整体系统) | 容易(能力单元) | 容易 | 不适用 | 通常不跨系统 |
| 有安全机制 | 是(系统级) | 是(能力级) | 通常无 | 无 | 可能 |
| 有版本治理 | 是(整体版本) | 是(独立版本,可灰度) | 是 | 通常无 | 是 |
4. Skill 的分类体系
并非所有 Skill 都长一个样。理解 Skill 的类型,有助于在设计阶段做出正确的粒度与职责划分决策。
4.1 按复杂度分
┌─────────────────────────────────────────────────────────────┐
│ │
│ Atomic Skill Composite Skill Orchestrator │
│ (原子技能) (复合技能) (编排技能) │
│ │
│ 单步完成 多步骤编排 不直接干活 │
│ 内部无 Skill 调用 内部可调用其他 Skill 负责拆解任务 │
│ 并分配 │
│ ┌──────────┐ ┌──────────────┐ ┌───────────┐│
│ │查询构建 │ │流水线故障诊断 │ │发布保障 ││
│ │日志 │ │分类→定位→修复│ │编排者 ││
│ └──────────┘ └──────────────┘ └───────────┘│
│ │
│ ┌──────────┐ ┌──────────────┐ 先调"故障诊断"│
│ │检查依赖 │ │数据库迁移 │ 再调"变更审批"│
│ │版本冲突 │ │校验→生成→执行 │ 再调"灰度发布"│
│ └──────────┘ └──────────────┘ 再调"监控验证"│
│ │
└─────────────────────────────────────────────────────────────┘
- Atomic Skill(原子技能):最小的能力单元,单步完成。例如 "查询构建日志 Skill"——输入 pipeline_id,返回日志内容,没有中间步骤。复用性最高。
- Composite Skill(复合技能):多步骤编排,涉及条件判断和分支。例如本文贯穿案例 "流水线故障诊断 Skill",它是"拉取日志 → 分类故障 → 定位根因 → 执行修复"的复合体。大部分业务场景的 Skill 属于这一类。
- Orchestrator(编排技能):自己不直接干活,职责是理解复杂需求、拆解为子任务、分配给合适的 Skill 执行。例如 "发布保障 Skill"——一次完整的发布保障流程,需要依次调用"故障诊断"、"变更审批"、"灰度发布"、"监控验证"等多个 Skill。
设计时的经验法则:优先设计 Composite Skill。只有当任务确实需要跨多个独立能力进行动态决策时,才引入 Orchestrator。过早引入 Orchestrator 会增加不必要的复杂度。
4.2 按触发方式分
-
主动调用:Agent 明确判断需要使用该 Skill 并显式调用。最常见的模式。
例:开发者说"帮我看看 CI 为什么挂了",Agent 主动调用 "流水线故障诊断 Skill"。
-
被动匹配:系统根据上下文自动关联,无需 Agent 显式决策。
例:CI/CD Webhook 检测到构建失败时,自动在 Slack 频道注入 "流水线故障诊断 Skill" 的执行结果。
-
事件驱动:由外部事件触发,而非用户当前对话。
例:构建失败后 30 分钟无人处理,自动触发 "工单升级 Skill" 将问题升级为 P1 事件。
4.3 按复用范围分
-
通用型:跨业务线复用,需要高度参数化,保持无业务逻辑绑定。
例:"发送通知 Skill"(CI 告警用、监控告警用、值班排班变更也用)、"代码搜索 Skill"。
-
领域型:特定业务领域专用,包含领域知识和规则。
例:"流水线故障诊断 Skill"(DevOps 领域)、"数据库迁移 Skill"(数据库领域)、"安全漏洞扫描 Skill"(安全领域)。
-
定制型:单一场景专用,通常生命周期较短,复用价值低。
例:"双十一压测自动扩缩容 Skill"(仅大促期间使用)、"年度安全合规审计 Skill"。
5. Skill 在 Agent 架构中的位置
引入 Skill 概念后,整个 Agent 系统的架构会变得更加清晰。我们可以将其分为四层:
┌─────────────────────────────────────────────────────────────────┐
│ 用户交互层 │
│ Chat(Slack / IM)· CLI 命令行 · CI/CD Webhook 注入 │
├─────────────────────────────────────────────────────────────────┤
│ Agent 编排层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 意图识别 │ │ 对话管理 │ │ 上下文 / │ │ 响应生成 │ │
│ │ │ │ │ │ 记忆管理 │ │ │ │
│ └────┬─────┘ └──────────┘ └────┬─────┘ └──────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Skill 调度与编排 │ │
│ │ 匹配 → 选择 → 加载 → 安全校验 → 执行 → 结果返回 │ │
│ │ ↑ 上下文注入(会话历史、服务画像) │ │
│ │ ↓ 结果回写(更新上下文、记录状态) │ │
│ └──────────────────────┬──────────────────────────────────┘ │
├──────────────────────────┼──────────────────────────────────────┤
│ ▼ │
│ Skill 能力层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │流水线 │ │数据库 │ │安全漏洞 │ │代码搜索 │ │
│ │故障诊断 │ │迁移 │ │扫描 │ │ │ │
│ │Skill │ │Skill │ │Skill │ │Skill │ │
│ │①②③④⑤⑥ │ │①②③④⑤⑥ │ │①②③④⑤⑥ │ │①②③④⑤⑥ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
├────────┼─────────────┼─────────────┼─────────────┼──────────────┤
│ ▼ ▼ ▼ ▼ │
│ Tool / API 基础层 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │CI/CD 平台│ │数据库管理 │ │漏洞库 │ │代码仓库 │ │
│ │API │ │工具 API │ │API │ │API │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Git API │ │消息队列 │ │监控平台 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
各层职责和关键边界:
用户交互层:接收用户输入(Chat 消息、CLI 命令、Webhook 事件等),展示 Agent 输出(诊断报告、修复结果等)。纯展示层,不含业务逻辑。
Agent 编排层:大模型大脑所在之处。负责理解用户意图,然后从 Skill 层中选择并执行合适的 Skill。其中,上下文/记忆管理贯穿全链路——它在 Skill 调用前注入会话历史和服务画像("这个服务上周也出现过类似的依赖问题"),调用后回写诊断结果和修复状态,确保多个 Skill 之间的信息不会断裂。
Skill 能力层:将基础层的 Tool 包装成 Agent 能理解的"业务能力卡片"。每个 Skill 都是六大要素齐全的独立单元。
Tool / API 基础层:企业已有的数字化资产——CI/CD 平台、代码仓库、监控系统、数据库管理工具等。纯粹的接口,不含业务理解。
为什么要单独设立 Skill 能力层? 如果把业务逻辑写在编排层,Agent 就和特定业务耦合了——换个团队想用你的 Agent,发现"故障诊断"的逻辑混在 Agent 代码里,拆不出来。如果散落在各个 Tool 里,CI/CD 平台的 Tool 不知道何时该被调用、调失败了怎么降级,每个 Tool 各自为政。设立清晰的能力层抽象,让 Agent 只负责"调度",Skill 负责"干事",Tool 负责"接接口",是 Agent 规模化工程实践的必经之路。
6. 为什么需要 Skill 这层抽象?
为什么不直接把一堆 Tool 的 API 丢给 Agent,让它自行组合?增加 Skill 这层抽象究竟带来了什么价值?
如果没有 Skill 层,把所有 Tool 的 API 描述直接暴露给大模型会怎样?
- Token 爆炸:你的 DevOps 平台可能有上百个 API endpoint(CI/CD、Git、监控、日志、配置中心……),全部塞进上下文窗口,模型根本处理不过来。[2]
- 幻觉加重:模型不知道该调哪个 API,甚至编造不存在的参数组合——比如把
get_pipeline_logs的参数和trigger_build的参数混在一起。 - 无法治理:API 是各个后端团队的事,Agent 的行为逻辑散落在各种 Prompt 里,出了问题不知道该找谁。
引入 Skill 这层抽象后,五个核心收益随之而来:
可复用。同一个"流水线故障诊断 Skill"可以被 DevOps Agent、值班机器人、ChatOps 工具、CI/CD 平台内置 AI 助手同时使用。没有这层抽象,每个场景各写一套,重复劳动,质量参差不齐。
可测试。Skill 可以脱离 Agent 独立测试。你可以给"流水线故障诊断 Skill"构建 100 条测试用例——依赖冲突日志、编译错误日志、测试失败日志、超长日志截断、空日志、恶意输入——验证它在各类情况下的表现,而不必启动整个 Agent 系统。
可演进。CI/CD 平台 API 从 v1 升级到 v2,返回格式变了?只需要修改 Skill 内部的 Bindings 和日志解析逻辑,发布新版本灰度上线,Agent 编排层和其他 Skill 完全无需感知。
可治理。有了 Skill 这个管理单元,权限、限流、监控、审计就可以精确到具体能力粒度。你可以单独查看"故障诊断 Skill"的成功率和平均诊断耗时,而不必对整个 Agent 一刀切。每个 Skill 有明确的 Owner,出了问题知道找谁。
可发现。通过 Skill Registry 和统一的 Identity 与 Intent 描述,Agent 可以在运行时动态发现和加载新上线的 Skill,而不需要修改 Agent 代码。当新的"数据库慢查询分析 Skill"注册上线后,DevOps Agent 自动获得这个能力。这是 Skill 能力层真正发挥威力的地方,我们会在第三篇详细展开。
7. 本系列路线图
围绕 Skill 的生命周期,本系列共分为四篇文章。每一篇聚焦 Skill 六大要素中的不同部分,形成从设计到治理的完整闭环:
Skill 的完整生命周期
设计时 运行时 治理时
───── ────── ──────
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 第一篇 │ │ 第三篇 │ │ 第四篇 │
│ 定义与 │ ────▶ │ 运行与 │ ────▶ │ 治理与 │
│ 架构 │ │ 生效 │ │ 演进 │
│ │ │ │ │ │
│ Skill 是 │ │ Skill 怎 │ │ Skill 上 │
│ 什么 │ │ 么被选中 │ │ 线后怎么 │
│ 由什么构成│ │ 加载执行 │ │ 保障质量 │
│ 在哪一层 │ │ 怎么保障 │ │ 持续优化 │
│ │ │ 安全 │ │ 有序退役 │
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ ┌──────────┐ │ │
└───▶│ 第二篇 │◀────────┘ │
│ 设计与 │ │
│ 封装 │◀─────────────────────────────────┘
│ │ (第四篇的优化反馈到第二篇)
│ Skill 怎 │
│ 么造好 │
└──────────┘
各篇覆盖的 Skill 要素分布:
| 要素 | 第一篇(本篇) | 第二篇:设计与封装 | 第三篇:运行与生效 | 第四篇:治理与演进 |
|---|---|---|---|---|
| ① Identity | 定义 | 定义模板与规范 | 运行时注册与发现 | 版本管理 |
| ② Intent | 定义 | 设计方法与最佳实践 | 匹配机制 | 召回测试 |
| ③ Contract | 定义(含对话契约) | 核心重点:Schema 设计 | 加载策略与校验 | 回归测试 |
| ④ Logic | 概念 | 核心重点:Prompt + 编排 | 执行监控 | 优化闭环 |
| ⑤ Bindings | 概念 | 依赖管理与容错设计 | 动态编排时的上下文传递 | 变更适配 |
| ⑥ Guardrails | 概念 | 内部防线设计 | 运行时安全(权限、限流、熔断) | 审计与合规 |
为了让读者更容易跟随整个生命周期,我们选取了 DevOps 场景中的 "流水线故障诊断 Skill" 作为贯穿全系列的核心案例。你将在每一篇文章中看到它的身影:从设计、加载、执行,到监控和优化。
8. 小结
Agent Skill 不是简单的提示词堆砌,也不是粗糙的 API 代理。它是大模型时代连接"智能大脑"与"工程系统"的标准能力接口。
本文从一个 CI/CD 流水线故障的真实场景切入,引出了 Skill 的概念。我们给出了它的严格定义,解剖了 Identity、Intent、Contract、Logic、Bindings、Guardrails 六大构成要素,并揭示了它们在执行过程中的协作关系——①② 先行匹配、③ 前后校验、④⑤ 协同执行、⑥ 贯穿全程。
我们用 SKILL.md 这一所有主流 AI Agent 平台采用的标准格式[1][2],展示了六个要素如何在单个文件中完整体现:front matter 中的 name 和 description 承载 Identity 和 Intent,正文的分步指令覆盖 Contract、Logic、Bindings 和 Guardrails。从最简的 roll-dice 到复杂的"流水线故障诊断",同一个格式可以承载任意复杂度的 Skill。
通过将 Skill 与 Tool、Prompt、Workflow 和 Agent 逐一辨析,我们划清了四条边界:
- Skill ≠ Tool:Tool 是原子操作,Skill 是 Tool 的消费者
- Skill ≠ Prompt:Prompt 是 Skill 内部的一个组件
- Skill ≠ Workflow:Workflow 的流程设计时确定,Skill 的路径运行时由 LLM 动态决策
- Skill ≠ Agent:Agent 是调度者和决策者,Skill 是 Agent 掌握的一项能力;同一个 Skill 可以被多个 Agent 复用
最后,我们把 Skill 放入四层架构中,明确了它与用户交互层、Agent 编排层和 Tool/API 基础层的关系,以及 Skill 能力层独立存在的必要性。
现在,你已经拥有了对 Skill 的统一认知。
接下来的问题是:怎么把这六个要素组装成一个高质量的 SKILL.md? description 怎么写才能让 Agent 准确召回?执行指令怎么组织才清晰可控?幂等性怎么保证?异常怎么处理?——这些封装层面的设计决策,就是下一篇的主题。
参考来源
本文的概念框架综合参考了以下公开技术文档与行业标准:
- OpenAI Function Calling & Tool Use — 结构化工具调用、JSON Schema 参数定义、模型动态选择工具的机制。OpenAI Docs
- Microsoft Semantic Kernel — Skill(Plugin)的结构化能力封装概念:Skill = Prompt + Native Function + Semantic Function 的组合思想。GitHub: microsoft/semantic-kernel
- LangChain Agent & Tools — Agent-Tool 交互模式、ReAct 推理策略、工具链编排。Docs: langchain.com
- NVIDIA NeMo Guardrails — LLM 应用的安全护栏设计思路,包括输入校验、输出审核、对话流控制。GitHub: NVIDIA/NeMo-Guardrails
- Semantic Versioning 2.0.0 — 语义化版本规范。semver.org
- Martin Fowler — Circuit Breaker — 熔断器设计模式:关闭→打开→半开状态机。martinfowler.com
- OpenAPI Specification 3.0 — API Schema 定义规范(type、required、enum、pattern 等)。OpenAPI Initiative
- NIST RBAC Standard (INCITS 359-2004) — 基于角色的访问控制模型。
- Google Vertex AI Agent Builder — Agent 分层架构、意图匹配与 Fulfillment 机制。Cloud Docs
- Anthropic Tool Use — Claude 的工具集成模式与多工具编排。Anthropic Docs
- GitHub Copilot Custom Instructions / Custom Skills — SKILL.md 的 front matter 格式规范(name + description)及操作指令模式。GitHub Docs
本文将上述来源中的理念融合为统一的"Skill 六要素"框架,这不是任何单一来源的原样复现,而是面向 Agent 工程化实践的综合提炼与原创架构设计。后续各篇将在具体章节中对引用来源做脚注标注。