从 Skill 到 Agent 专家团:AI 工作流的工程化进阶

本文是《WorkBuddy AI 工作流实战》系列第 3 篇,也是进阶篇。
前两篇解决了两个问题:如何理解 Agent、Skill、Tool,以及如何编写第一个
SKILL.md。这一篇继续向前一步,把单文件 Skill 升级为包含脚本、配置、参考资料和质量检查的工程化工作流,并讨论跨工具分发、MCP 接入与多 Agent 协作。
一、什么时候需要把 Skill 工程化?
第 2 篇创建的 doc-to-tasks 只有一个 SKILL.md。对于“读取内容 → 整理摘要 → 输出待办”这类任务,单文件已经足够。
但有些任务不只是生成文字。例如:
读取当前分支的代码改动,根据团队规范生成 PR 描述和变更日志,并在交付前检查格式是否合格。
这项任务需要:
- 调用 Git 获取真实改动;
- 读取团队 PR 规范;
- 根据配置决定输出目录和语言;
- 生成 PR 描述与变更日志;
- 运行程序检查输出;
- 校验失败时修正并重新检查。
此时,仅靠 SKILL.md 描述步骤仍然可以工作,但执行逻辑会越来越长,也难以单独测试。更稳妥的做法,是把确定性的操作下沉到脚本,把规则和资料拆到独立文件。
可以采用下面这套推荐结构:
pr-generator/
├── SKILL.md
├── config.json
├── scripts/
│ ├── collect_diff.py
│ └── verify_output.py
└── references/
├── pr-template.md
└── team-conventions.md
| 组件 | 负责什么 | 是否必需 |
|---|---|---|
SKILL.md |
触发场景、执行步骤、工具选择和完成标准 | 核心文件 |
config.json |
输出目录、语言、模板路径等可调整参数 | 按需添加 |
scripts/ |
获取数据、转换格式、校验结果等确定性操作 | 按需添加 |
references/ |
团队规范、模板和领域资料 | 按需添加 |
这不是所有平台强制规定的“四件套”,而是一种便于维护的工程结构。核心原则是:
需要推理的事情交给 Agent,需要稳定重复的事情交给脚本,需要长期维护的规则放进配置和参考资料。

二、实战案例:从代码改动生成 PR 描述
下面用 pr-generator 串起完整流程。
1. 先定义完成标准
在写脚本之前,先明确最终产物:
fix: 修复支付回调重复处理
## 变更点
- 增加支付回调幂等检查
- 补充重复通知测试
## 验证
- [x] 单元测试通过
- [x] 本地回调测试通过
## 风险
- 需要观察旧订单数据的兼容情况
这个例子的质量要求是:
- 首行必须包含允许的类型标签;
- 必须包含“变更点”和“验证”章节;
- 变更点不能是空内容或“待补充”;
- 输出必须来源于真实改动,不能虚构测试结果。
2. 在 SKILL.md 中编排流程
---
name: pr-generator
description: 根据当前 Git 代码改动生成结构化 PR 描述和变更日志。当用户要求总结分支改动、编写 PR 描述或生成 changelog 时使用。
---
# PR 描述生成器
## 工作流
1. 确认当前目录是 Git 仓库,并检查工作区状态。
2. 使用 `scripts/collect_diff.py` 获取待描述的代码改动。
3. 阅读 `references/team-conventions.md` 和 PR 模板。
4. 按“标题、变更点、验证、风险”结构生成 PR 描述。
5. 只记录能够从代码、测试结果或用户输入中确认的信息。
6. 将结果保存到配置指定的位置。
7. 使用 `scripts/verify_output.py` 校验输出。
8. 校验失败时根据错误修正,并重新执行校验。
## 约束
- 不执行提交、推送或创建 PR,除非用户明确要求。
- 不把密钥、令牌、个人信息或无关 diff 写入结果。
- 未实际运行的测试必须标记为“未运行”。
- 无法确认的风险应标记为“待确认”。
这里有两个重要设计:
- 生成与发布分离:生成 PR 文案不等于提交代码或创建远程 PR,外部操作应单独确认。
- 事实与推断分离:测试是否通过、风险是否存在,都需要证据;没有证据就明确标记未知。
3. 用脚本实现质量门禁
下面是精简但可以运行的 verify_output.py:
from pathlib import Path
import re
import sys
ALLOWED_TYPES = "feat|fix|docs|refactor|test|build|chore"
REQUIRED_SECTIONS = ("变更点", "验证")
PLACEHOLDERS = ("待补充", "TODO", "TBD")
def section_body(text: str, heading: str) -> str:
pattern = rf"^##\s+{re.escape(heading)}\s*$\n(.*?)(?=^##\s+|\Z)"
match = re.search(pattern, text, flags=re.MULTILINE | re.DOTALL)
return match.group(1).strip() if match else ""
def validate(text: str) -> list[str]:
errors = []
first_line = text.splitlines()[0].strip() if text.splitlines() else ""
if not re.match(rf"^({ALLOWED_TYPES})(\(.+?\))?:\s+\S+", first_line):
errors.append("标题必须以允许的类型标签开头,例如 fix: 修复登录异常")
for heading in REQUIRED_SECTIONS:
body = section_body(text, heading)
if not body:
errors.append(f"缺少内容完整的“{heading}”章节")
elif any(marker.lower() in body.lower() for marker in PLACEHOLDERS):
errors.append(f"“{heading}”章节仍包含占位内容")
return errors
def main() -> int:
if len(sys.argv) != 2:
print("用法: python verify_output.py <pr-description.md>")
return 2
path = Path(sys.argv[1])
if not path.is_file():
print(f"文件不存在: {path}")
return 2
errors = validate(path.read_text(encoding="utf-8"))
if errors:
for error in errors:
print(f"ERROR: {error}")
return 1
print("校验通过")
return 0
if __name__ == "__main__":
raise SystemExit(main())
运行方式:
python scripts/verify_output.py output/pr-description.md
质量门禁的意义,不是让脚本判断文案“写得好不好”,而是让它检查那些能够明确判断的条件:文件是否存在、章节是否完整、格式是否符合规范、占位符是否清除。
4. 为脚本本身添加测试
既然校验脚本承担“门禁”职责,它本身也需要被验证。至少覆盖三类用例:
| 测试用例 | 预期结果 |
|---|---|
| 合法标题且章节完整 | 返回成功 |
| 缺少“验证”章节 | 返回失败并指出缺失章节 |
“变更点”仍含 TODO |
返回失败并指出占位内容 |
这一步经常被忽略。没有测试的门禁脚本,也可能把错误内容放过去。
三、参数怎么管理:明确优先级
当同一个 Skill 被不同项目复用时,输出目录、语言和模板可能不同。可以将默认值放入 config.json:
{
"output_dir": "docs/pr",
"language": "zh-CN",
"template": "references/pr-template.md"
}
建议采用清晰的覆盖顺序:
用户本次明确要求 > 命令行参数 > 项目配置 > 内置默认值
例如,默认输出到 docs/pr,但用户本次明确要求写入 /tmp/pr.md,就只覆盖本次输出位置,不修改项目配置。
配置设计还要注意:
- 路径应相对于 Skill 或项目根目录解析,不要依赖某台电脑的绝对路径;
- 对配置值进行类型和范围校验;
- 不要把令牌、密码等敏感信息写进可提交的配置文件;
- 缺少可选配置时,应有明确默认行为。
四、跨平台不只是准备 .sh 和 .ps1
原稿把跨平台简化为“同时提供 Shell 和 PowerShell 入口”,但真正的兼容性还包括路径、编码、依赖和命令差异。
更实用的策略是:
- 核心逻辑优先使用跨平台语言:例如 Python 或 Node.js。
- 平台脚本只做薄封装:
.sh和.ps1负责定位运行时并传递参数。 - 使用标准路径 API:避免手工拼接
/或\。 - 固定文本编码:读写文件时显式使用 UTF-8。
- 启动时检查依赖:缺少 Git、Python 或必要包时给出可执行的错误信息。
- 在目标系统上测试:文件看起来兼容,不代表实际运行兼容。
如果团队环境统一,只支持一种平台反而更简单。跨平台是一项真实需求,不是工程成熟度的装饰。
五、一份源如何分发给多个 AI 工具?
不同 AI 工具对 Skill 的目录、文件格式和发现机制可能不同,不能假设把同一个目录软链接过去就一定可用。
更稳妥的方案是维护一个“规范源目录”,再通过安装脚本适配各目标平台:
workflow-library/
├── skills/ # 唯一维护源
│ └── pr-generator/
├── adapters/ # 各工具的格式或目录适配
├── install.py # 安装、更新、检查
└── manifest.json # 版本与目标清单

安装脚本可以按环境选择两种策略:
| 策略 | 优点 | 注意事项 |
|---|---|---|
| 软链接 | 源文件更新后立即反映到目标目录 | Windows 权限、容器和部分同步工具可能不支持 |
| 复制安装 | 兼容性更好,目标目录相互隔离 | 更新时需要重新执行安装并防止版本漂移 |
推荐流程是:
读取 manifest → 识别目标工具 → 转换格式或目录
→ 安装到目标位置 → 校验文件 → 输出安装报告
不要在文章或脚本里硬编码某个工具的目录后就宣称“全平台通用”。目标路径和格式应以对应工具当前版本的官方说明为准,并在安装前检查。
六、MCP 在工作流中负责什么?
MCP(Model Context Protocol,模型上下文协议)用于让兼容的 AI 客户端连接外部工具和数据源,例如代码托管平台、数据库、浏览器或内部服务。
需要分清三层职责:
Skill:描述什么时候调用、按什么顺序调用
Tool / MCP Server:提供具体操作能力
Agent:结合目标和返回结果进行决策
例如,PR 工作流可以这样扩展:
读取本地 git diff
→ 通过代码托管 MCP 查询关联 Issue
→ 生成 PR 描述
→ 本地脚本执行格式校验
→ 用户确认后再调用远程工具创建 PR
这里有三个边界:
- MCP 服务需要先在客户端正确配置,写一个 Skill 不会自动获得外部权限;
- 能调用工具不代表应该调用,写操作仍要遵循授权和确认规则;
- 外部返回值不一定可信,Agent 仍需验证错误、空结果和权限失败。
因此,MCP 不是“联网开关”,而是标准化工具接入的一种方式。
七、什么时候该创建 Agent?
Skill 适合沉淀一类任务的方法;Agent 适合承担持续决策、需要明确职责边界的角色。
| 需求 | 更适合 Skill | 更适合 Agent |
|---|---|---|
| 固定步骤整理文档 | 是 | 否 |
| 按模板生成 PR 描述 | 是 | 可选 |
| 审查一组跨模块改动并持续追踪问题 | 可提供审查 Skill | 是 |
| 协调测试、审查和发布多个环节 | 可作为能力模块 | 是 |
不要仅仅为了拥有“人格”就创建 Agent。一个 Agent 至少应该明确:
- 它负责解决什么问题;
- 在什么条件下介入;
- 可以使用哪些 Skill 和 Tool;
- 哪些操作必须确认;
- 输出采用什么结构;
- 何时停止并交付。
下面是一个精简的代码审查 Agent 示例。具体 frontmatter 字段和存放目录应以当前客户端支持的格式为准:
---
name: code-reviewer
description: 审查代码或 PR 中的正确性、安全性、性能和可维护性问题。当用户明确要求代码审查或合并前检查时使用。
---
# 代码审查 Agent
## 职责
识别会导致错误、行为回归、安全问题或维护成本上升的具体问题。
## 工作流
1. 理解改动目标和影响范围。
2. 阅读 diff 及必要的关联代码,不只检查单个片段。
3. 运行与风险相匹配的测试或静态检查。
4. 按严重程度排列发现:阻断、重要、建议。
5. 每条发现提供文件位置、触发条件、影响和修改建议。
6. 没有发现问题时明确说明,并列出尚未验证的风险。
## 约束
- 只报告能够用代码或执行结果支持的问题。
- 不把个人风格偏好描述成缺陷。
- 未经要求不修改代码、不提交、不推送。
- 不编造不存在的文件、API 或测试结果。
## 输出格式
先列发现,按严重程度排序;然后列开放问题和验证情况;最后给出简短总结。
与原稿中“10 年经验”“不留情面”等人格描述相比,职责、证据标准和停止条件更能决定 Agent 是否可靠。
八、如何组建多 Agent 专家团?
多 Agent 的价值不是“角色越多越强”,而是把不同目标、工具权限或上下文边界分开。
以发布流程为例,可以设置三个角色:
代码审查 Agent ─┐
测试 Agent ─────┼→ 汇总结果 → 人工确认 → 发布 Agent
文档 Agent ─────┘

| Agent | 主要输入 | 主要产出 | 不负责什么 |
|---|---|---|---|
| 代码审查 | diff、关联代码、规范 | 按严重程度排列的问题 | 不发布代码 |
| 测试 | 改动范围、测试配置 | 测试结果和失败证据 | 不替测试失败找借口 |
| 文档 | 功能变化、用户影响 | 更新说明和迁移提示 | 不臆造功能行为 |
| 发布 | 已确认的版本与检查结果 | 发布操作及结果记录 | 未确认时不发布 |
多 Agent 协作应补齐四个机制:
- 输入输出契约:上一个 Agent 交付什么,下一个 Agent 才能开始。
- 单一责任边界:避免两个 Agent 同时修改同一文件或重复做同一判断。
- 失败处理:测试失败、工具不可用或信息不足时如何停止和报告。
- 人工确认点:提交、推送、发布和外部通知等操作应明确确认。
如果任务只需一个 Agent 加几个 Skill 就能完成,不要为了“专家团”增加调度成本。
九、数量与 token:不要用简单结论代替测量
Agent 和 Skill 对上下文的影响取决于具体客户端实现:有的只暴露名称和描述,命中后才加载正文;有的会预加载更多元数据;子 Agent 是否使用独立上下文,也因产品和配置而异。
因此,不能笼统地说“安装 100 个 Agent 几乎不耗 token”。更可靠的优化方向是:
- 缩短重复、空泛的角色描述;
- 避免多个 Skill 的
description大面积重叠; - 简单任务不要无意义地派发子 Agent;
- 控制循环次数和工具返回的数据量;
- 对长日志和大文件先筛选,再送入模型;
- 使用客户端提供的上下文或用量信息进行实测。
关注“实际加载了什么、调用了几次、每次返回多少内容”,比只统计 Agent 数量更有意义。
十、从能运行到可维护:一份检查清单
工程化工作流交付前,可以按下面的清单检查:
功能
- 正常输入可以得到预期结果
- 缺少输入时会询问或明确失败
- 不相关请求不会误触发
质量
- 输出格式有明确标准
- 校验失败会阻止交付
- 校验脚本自身有测试
安全
- 不记录或输出敏感信息
- 写文件、提交、推送和发布的边界明确
- 外部操作有必要的授权与确认
可移植性
- 路径没有绑定某台电脑
- 编码和依赖要求明确
- 已在目标系统实际运行
维护
- 配置、脚本和规范职责清晰
- 有版本或更新策略
- 失败信息能够指导排查
这份清单比“文件数量够不够”更能判断一个工作流是否接近生产可用。
总结
从单文件 Skill 走向工程化,可以沿着下面这条路线推进:
单文件 Skill
→ 引入脚本与质量门禁
→ 拆分配置和参考资料
→ 适配不同工具与平台
→ 接入 MCP 外部能力
→ 按职责引入 Agent 协作
→ 持续测试和迭代
记住四个结论:
- 工程化不是凑齐固定文件,而是分离推理、执行、配置和规范。
- 生成之后必须校验,能够自动判断的条件应交给程序。
- 跨工具分发需要适配层,软链接只是安装策略之一。
- 多 Agent 的核心是职责和契约,不是角色数量和人格包装。
系列收官
《WorkBuddy AI 工作流实战》三篇完成了从概念到工程实践的闭环:
- 第 1 篇:理解 Agent、Skill、Tool 和 Agent Loop;
- 第 2 篇:写出并验证第一个
SKILL.md; - 第 3 篇:加入脚本、质量门禁、跨工具分发、MCP 和 Agent 协作。
下一步不必一次搭建庞大的系统。选择一个经常重复、步骤明确、结果可检查的任务,从单文件 Skill 开始;只有当真实需求出现,再逐步加入脚本、配置和 Agent。
先让流程可用,再让结果可验,最后让系统可维护。
更多推荐
所有评论(0)