AI时代前端工程师实战指南:Agent工作流
本文定位不一样——不是教你怎么给 Agent 写 Prompt,而是教你怎么设计一套能被 Agent 自动执行的 Skill 体系。
把开发流程拆成可复用的指令模块,让 Agent 按工作流自动运转,你从”操作者”变成”设计者”。
5.1 从”写 Prompt”到”设计 Skill”
上一章我们讲了 Prompt 工程——如何写出结构清晰、约束明确的 Prompt,让 AI 输出更可靠。这是一个巨大的进步,从”随便问两句”到”系统化地写 Prompt”,已经是质的飞跃。
但用过一段时间后,你会发现一个新问题:每次都要重复写几乎一样的 Prompt。
比如你有一个开发习惯——写任何代码之前先做需求分析,然后出技术方案,再动手编码,最后加测试。这个流程你每次都要在 Prompt 里重申一遍:
1 2 3 4 5
| ❌ 每次重复: "先分析需求,列出所有功能点和边界条件" "然后出技术方案,考虑组件拆分和数据流" "再开始编码,遵循项目规范" "最后加测试,覆盖正常路径和异常路径"
|
这种做法的弊端很明显:
- 不一致 — 今天记得说”先分析需求”,明天可能忘了,Agent 的行为就变了
- 遗漏步骤 — 流程有 5 步,你只说了 3 步,Agent 就按 3 步执行
- 依赖个人记忆 — 换一个人用,他不知道你的流程是什么,重新摸索
- 不可复用 — 换个项目,同样的流程要再写一遍
这就引出了本文的核心概念:Skill。
Skill 的本质是什么?是把”怎么做”固化为一个可加载的指令模块。你把开发流程封装成 Skill 文件放在项目里,Agent 按需加载,不需要你每次口头交代。
| 对比维度 |
Prompt |
Skill |
| 生命周期 |
一次性,用完即弃 |
持久化,可反复使用 |
| 一致性 |
每次重新写,可能遗漏 |
固化在文件中,始终一致 |
| 可复用性 |
仅限当前对话 |
跨项目、跨团队共享 |
| 组合性 |
单次输入,难以串联 |
多个 Skill 可编排为 Workflow |
| 维护性 |
改一次 Prompt 只有你知道 |
改一个文件,所有人都受益 |
打个比方:Prompt 就像你每次下厨都要翻菜谱,Skill 就像你把菜谱写成一本食谱书放在厨房——不仅你自己不用再翻,其他人也能按这本书做出同样的菜。
在 OpenCode 这类 Agent 编程工具中,Skill 以 .opencode/skills/ 目录下的 SKILL.md 文件形式存在。Agent 启动时自动扫描这些文件,根据当前任务匹配合适的 Skill 加载。这就是”设计 Skill”的本质:把你的开发方法论写成 Agent 可读、可执行的标准文档。
5.2 Skill 的设计原则
既然 Skill 是一份给 Agent 读的操作指南,那它应该怎么设计?下面是我在实践中总结的五个核心原则。
原则一:单一职责
每个 Skill 只做一件事,并且把它做好。
一个 Skill 如果既要做需求分析、又要写代码、还要做测试,它就会像一个人同时扮演三个角色——每个角色都演不到位。Agent 加载这样的 Skill 后,会在多个目标之间摇摆,哪一步都做不深入。
正确做法是把一个大流程拆成多个 Skill,每个 Skill 专注一个环节:
1 2
| ❌ 不推荐:full-development-skill(包含分析、设计、编码、测试) ✅ 推荐:requirement-analysis-skill → tech-design-skill → coding-skill → test-skill
|
原则二:声明边界
明确告诉 Agent 什么能做、什么不能做。
Agent 没有人类常识,你说”分析需求”,它可能真的去改代码了。你需要用 MUST DO / MUST NOT DO 来定义行为边界。
1 2 3 4 5 6 7
| MUST DO: - 仅读取 src/ 和 docs/ 目录下的文件 - 输出格式必须为 Markdown
MUST NOT DO: - 不要修改任何源代码文件 - 不要执行 npm install 或修改 package.json
|
原则三:可验证
每个 Skill 的产出物必须有明确的检查标准。
Agent 执行完 Skill 后,怎么知道它做对了?靠人的直觉判断是不够的。你需要在 Skill 中嵌入验证步骤,让 Agent 自己检查自己的输出。
1 2 3 4
| 验证标准: - 所有功能点都有对应的测试用例 - LSP diagnostics 零错误 - 测试覆盖率 ≥ 80%
|
原则四:可组合
多个 Skill 可以串联成工作流,前一个的输出是后一个的输入。
Skill 之间应该通过”文件”或”标准输出格式”传递信息。比如需求分析 Skill 输出一份 spec.md,技术设计 Skill 读取这份 spec.md 作为输入。这样 Skill 之间松耦合,可以灵活编排。
原则五:自包容
Skill 自带完整上下文,不依赖外部假设。
一个 Skill 文件应该让一个不了解项目的 Agent 也能执行。不要在 Skill 里写”参考我们之前讨论过的 X 方案”——Agent 不知道”之前”是什么。所有必需的背景信息、参考文件路径、技术栈说明,都要写在 Skill 文件本身。
5.3 Skill 文件结构
一个标准的 SKILL.md 文件包含以下几个部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SKILL.md ├── 1. Metadata(元数据) │ ├── 名称 — Skill 的唯一标识 │ ├── 适用场景 — 什么情况下触发此 Skill │ └── 输入/输出 — 前置条件和后置产出 ├── 2. 执行步骤(Step by step) │ └── 按顺序排列的操作指令 ├── 3. 约束规则 │ ├── MUST DO — Agent 必须做的事情 │ └── MUST NOT DO — Agent 绝不能做的事情 ├── 4. 验证标准 │ └── 如何判断产出物是否合格 └── 5. 参考和依赖 └── 相关文件、文档、其他 Skill
|
下面给出三个完整的 SKILL.md 示例,覆盖了前端开发中最常见的三个环节。
示例一:需求分析 Skill
这个 Skill 负责将模糊的需求描述转化为结构化的功能规格说明。它不做编码,只做分析和文档输出。
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| # Requirement Analysis Skill
## Metadata
- **名称**: requirement-analysis - **适用场景**: 收到一个新的功能需求,需要先理清需求边界和功能点 - **前置条件**: 用户提供了需求描述(可以是几句话、一段文字或一个 Issue 链接) - **输出产物**: `docs/ specs/<feature-name>/requirement.md`
## 执行步骤
1. **读取上下文** - 如果用户提到了相关文件,先读取这些文件了解背景 - 如果用户没有提供,询问并提供模板:需求背景、目标用户、核心功能
2. **需求拆解** - 列出所有功能点,每个功能点用一句话描述 - 标注每个功能点的优先级:P0(必须有)/ P1(应该有)/ P2(可以有)
3. **边界条件识别** - 列出正常路径(Happy Path) - 列出异常路径(Error Path) - 列出边界情况(空数据、大数据量、并发操作)
4. **输出规范文档** - 使用以下格式写入 `docs/ specs/<feature-name>/requirement.md`
```markdown # <功能名称> 需求规格说明
## 概述 [一句话描述这个功能]
## 功能点列表 | 功能点 | 优先级 | 描述 | |--------|--------|------| | ... | P0 | ... |
## 验收标准 ### Happy Path - [ ] ...
### Error Path - [ ] ...
### 边界条件 - [ ] ...
## 技术约束 - 技术栈:[项目技术栈] - 兼容性要求:[浏览器/设备] - 性能要求:[加载时间/响应时间]
|
约束规则
MUST DO
- 必须输出到
docs/ specs/<feature-name>/requirement.md
- 必须区分 P0/P1/P2 优先级
- 必须包含验收标准
MUST NOT DO
- 不要修改任何源代码文件
- 不要输出代码实现
- 不要执行终端命令
验证标准
参考
- 项目 README:
README.md
- 现有功能规格示例:
docs/specs/example.md
1 2 3 4 5
| ### 示例二:测试生成 Skill
  这个 Skill 负责为已有组件或功能生成测试文件。它读源码,写测试,不修改业务代码。
|
Test Generation Skill
- 名称: test-generation
- 适用场景: 为一个已有的组件、Hook、工具函数生成单元测试
- 前置条件: 目标文件的路径已确定
- 输出产物:
src/**/__tests__/<name>.spec.ts 或 .test.ts
执行步骤
读取目标文件
- 读取完整的目标源码文件
- 识别导出的函数、组件、类型
分析测试需求
- 对于函数:参数类型、返回值类型、边界条件
- 对于组件:Props、Slots、Emits、状态变化
- 对于 Hook:输入参数、返回状态、副作用清理
生成测试文件
- 在
__tests__/ 目录下创建对应的测试文件
- 测试文件命名规则:
<原名>.spec.ts
编写测试用例
- 至少覆盖以下场景:
- 正常渲染/调用(Happy Path)
- 空状态(无数据/null/undefined)
- 错误处理(异常输入、失败回调)
- 边界条件(极限值、特殊字符)
约束规则
MUST DO
- 测试文件必须放在
__tests__/ 目录下
- 使用项目已有的测试框架和工具(从
package.json 中识别)
- 每个测试用例必须有明确的
describe 和 it 描述
- 测试描述使用中文
MUST NOT DO
- 不要修改被测源文件
- 不要安装新的测试依赖
- 不要生成集成测试或 E2E 测试(那是别的 Skill 的工作)
验证标准
参考
- 项目测试配置:
vitest.config.ts
- 现有测试示例:
src/components/__tests__/example.spec.ts
1 2 3 4 5
| ### 示例三:代码审查 Skill
  这个 Skill 负责审查代码变更,从多个维度评估代码质量并输出审查报告。
|
Code Review Skill
- 名称: code-review
- 适用场景: 一个功能开发完成,需要审查代码质量后再提交
- 前置条件: 代码变更已在工作区中,未提交
- 输出产物:
docs/reviews/<feature-name>-review.md
执行步骤
获取变更范围
- 运行
git diff --name-only 获取变更文件列表
- 运行
git diff --stat 了解变更规模
逐文件审查
检查维度
- 类型安全:是否有
any 类型?是否有未使用的变量?
- 错误处理:异步操作是否有 try/catch?边界情况是否有防御?
- 性能:是否有不必要的重渲染?是否有内存泄漏风险?
- 可维护性:函数是否过长?是否有重复代码?命名是否清晰?
- 安全:是否有 XSS 风险?是否有敏感信息泄露?
输出审查报告
- 使用以下格式写入
docs/reviews/<feature-name>-review.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| # <功能名称> 代码审查报告
## 概述 - 审查者:[Skill 名称] - 变更范围:[文件数量] files changed - 审查结果:✅ 通过 / ⚠️ 有条件通过 / ❌ 不通过
## 文件审查详情 ### `<文件路径>` | 维度 | 评级 | 问题描述 | |------|------|----------| | 类型安全 | ✅/⚠️/❌ | ... | | 错误处理 | ✅/⚠️/❌ | ... | | 性能 | ✅/⚠️/❌ | ... | | 可维护性 | ✅/⚠️/❌ | ... | | 安全 | ✅/⚠️/❌ | ... |
## 需要修复的问题 1. **[严重/中等/轻微]** 问题描述 2. ...
## 改进建议 - ...
|
约束规则
MUST DO
- 每个变更文件都必须审查
- 问题必须标注严重等级(严重/中等/轻微)
- 必须提供具体的改进建议,而不是笼统的批评
MUST NOT DO
- 不要修改代码(只审查,不修改)
- 不要运行破坏性命令
- 不要审查非本次变更的文件
验证标准
参考
- 项目代码规范:
docs/coding-standards.md
- 之前的审查报告:
docs/reviews/
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| ---
## 5.4 从 Skill 到 Workflow:AGENTS.md 的总控配置
  单个 Skill 解决的是"怎么做一件事"的问题。但实际开发中,一个功能要从需求走到上线,需要多个 Skill 串起来。这时候就需要 AGENTS.md 来当"总控"。
  AGENTS.md 的核心作用有三点:
1. **定义你是谁** — Agent 的角色和核心能力 2. **声明你会什么** — 可用的 Skill 清单 3. **规定按什么流程工作** — Skill 的执行顺序和触发条件
  下面是一个完整的 AGENTS.md 示例,它定义了一个前端开发的完整工作流:
```markdown # AGENTS.md — Agent 层级知识库
你是 Sisyphus — 一个资深的 AI 赋能前端架构师。
## 你的核心能力
1. **需求分析** — 将模糊需求转化为结构化规格文档 2. **技术设计** — 组件拆分、状态管理、接口设计 3. **代码生成** — Vue 3 / React / TypeScript / Tailwind CSS 4. **测试编写** — 单元测试、组件测试 5. **代码审查** — 类型安全、性能、可维护性检查
## 技能清单
以下技能按执行顺序排列,通常按 ①→②→③→④→⑤ 的顺序执行。
### ① requirement-analysis - **位置**: `.opencode/skills/requirement-analysis/SKILL.md` - **触发条件**: 收到新功能需求,或用户说"帮我分析一下 X" - **输出**: `docs/specs/<feature-name>/requirement.md` - **完成后触发**: tech-design
### ② tech-design - **位置**: `.opencode/skills/tech-design/SKILL.md` - **触发条件**: requirement-analysis 完成,或用户说"出一下设计方案" - **前置条件**: 存在 `docs/specs/<feature-name>/requirement.md` - **输入**: 读取 requirements.md - **输出**: `docs/specs/<feature-name>/design.md` - **完成后触发**: coding
### ③ coding - **位置**: `.opencode/skills/coding/SKILL.md` - **触发条件**: tech-design 完成,或用户说"开始编码" - **前置条件**: 存在 `docs/specs/<feature-name>/design.md` - **输入**: 读取 design.md 和 requirements.md - **输出**: 源代码文件变更 - **完成后触发**: test-generation
### ④ test-generation - **位置**: `.opencode/skills/test-generation/SKILL.md` - **触发条件**: coding 完成,或用户说"加测试" - **前置条件**: 源代码已变更 - **输出**: 测试文件 - **完成后触发**: code-review
### ⑤ code-review - **位置**: `.opencode/skills/code-review/SKILL.md` - **触发条件**: test-generation 完成,或用户说"审查代码" - **前置条件**: 测试通过 - **输出**: `docs/reviews/<feature-name>-review.md`
## 行为规则
1. **流程优先** — 任何功能开发,默认按 ①→②→③→④→⑤ 顺序执行 2. **可跳过** — 如果某个 Skill 不适用(如纯 Bug 修复不需要需求分析),用户说"跳过 X"即跳过 3. **可循环** — 如果 code-review 未通过,回到 coding 步骤修复问题 4. **验证驱动** — 每个 Skill 完成后必须运行自身的验证标准 5. **人在环路** — 关键决策点(架构选型、技术方案)输出后等待人工确认
## 工作流示意
|
用户需求
│
▼
① requirement-analysis ──→ docs/specs/requirement.md
│
▼
② tech-design ──→ docs/specs/design.md
│
▼
③ coding ──→ 源代码变更
│
▼
④ test-generation ──→ 测试文件
│
▼
⑤ code-review ──→ docs/reviews/review.md
│
├── ✅ 通过 → 完成,可供提交
└── ❌ 不通过 → 返回 ③ 修复
1 2 3 4 5 6
| ## 参考文档
- 项目文档: `docs/` - 组件设计规范: `docs/component-guidelines.md` - 代码风格: `.eslintrc.cjs`
|
这份 AGENTS.md 就是 Agent 的”总设定”。Agent 启动后读取它,就知道:
- “我是一个前端架构师”
- “我手上有 5 个 Skill”
- “处理功能的流程是分析→设计→编码→测试→审查”
- “每个步骤结束后自动触发下一个”
你不需要再说”先分析需求”——AGENTS.md 已经替你说好了。你要做的只是告诉 Agent:”实现搜索功能”。然后它就会自动走完整个工作流。
5.5 Agent 如何”自动决策”工具和 MCP
到这里你可能有一个疑问:Skill 只规定了”做什么步骤”和”不能做什么”,但它没有规定具体用什么工具来执行。Agent 怎么知道该用什么?
这就是 Skill 设计的精妙之处——它只规定”什么”,不规定”怎么”。
举个例子,看前面 test-generation Skill 中的一条指令:
1 2 3 4 5
| 编写测试用例: - 正常渲染/调用(Happy Path) - 空状态(无数据/null/undefined) - 错误处理(异常输入、失败回调) - 边界条件(极限值、特殊字符)
|
这条指令没有说”用 Vitest 的 describe 和 it“,也没有说”运行 npm run test“。Agent 加载 SKILL.md 后,会自主决策:
- 读项目配置 —
package.json 中发现测试框架是 Vitest
- 读现有测试 — 发现项目中使用
describe / it / expect 模式
- 选择工具 — 决定用 Vitest 的 API 编写测试
- 执行验证 — 运行
npm run test -- --run 来确认测试通过
再举一个更直观的例子。假设你有一个 Skill 要求”验证 UI 表现”:
1 2 3 4 5
| 验证步骤: 3. 打开浏览器检查页面渲染效果 - 确认组件在不同视图尺寸下的布局 - 确认交互动效正常 - 截图保存到 docs/screenshots/
|
Agent 加载这条指令后,会做以下决策:
- 分析需求 — “打开浏览器” → 需要浏览器自动化工具
- 扫描可用 MCP — 发现
opencode.json 中配置了 Playwright MCP
- 调用 MCP — 通过 Playwright MCP 启动浏览器、导航到页面、截图
- 保存结果 — 将截图写入
docs/screenshots/
这个过程完全不需要你告诉 Agent “用 Playwright MCP”。它从 Skill 的步骤描述中推断出需要浏览器操作,然后自主选择可用的 MCP Server 来完成。
这种设计带来了极大的灵活性。同样的 Skill,在不同环境中可能使用不同的工具:
1 2 3 4 5 6 7 8
| Skill 说:"读取数据库中的数据" ├── 开发环境 → Agent 选择 SQLite MCP ├── 测试环境 → Agent 选择测试数据库 MCP └── 生产环境 → Agent 选择只读副本 MCP(因为 MUST NOT 中禁止了写操作)
Skill 说:"发起 PR" ├── GitHub 项目 → Agent 选择 GitHub MCP └── GitLab 项目 → Agent 选择 GitLab MCP
|
把”工具选择”的决策权交给 Agent,Skill 就不需要绑定具体的工具实现。这使得 Skill 在不同的项目、不同的技术栈中都能复用。
MCP 在其中扮演的角色类似于”设备驱动”。Agent 是操作系统,SKILL.md 是应用程序,MCP Server 就是驱动程序:
1 2 3 4 5 6 7 8
| Agent(操作系统) ├── SKILL.md(应用程序)→ 规定步骤和约束 ├── 读文件工具(内置驱动) ├── 写文件工具(内置驱动) ├── 执行命令工具(内置驱动) ├── Playwright MCP(浏览器驱动) ├── GitHub MCP(代码仓库驱动) └── 其他 MCP(自定义驱动)
|
这就是你想要的——给 Agent 总设定和工作流,它自行做决策、选工具、调 MCP,自动完成整个开发流程。
5.6 实战:构建一个完整的 Skill 工作流
理论讲完了,来看一个真实场景。假设我们要给一个电商项目添加”商品搜索功能”。我们一步步看 Agent 如何利用前面设计的 Skill 工作流自动完成任务。
Step 1:触发需求分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 用户输入: "给商城加一个商品搜索功能,支持关键词搜索和分类筛选"
Agent → 读取 AGENTS.md Agent → 识别这是一个"新功能需求" Agent → 加载 requirement-analysis Skill Agent → 按 Skill 步骤执行:
1. 读取上下文 → 读取项目 README 和现有页面结构 2. 需求拆解 → 列出功能点: - P0: 搜索输入框(支持关键词输入) - P0: 搜索结果列表展示 - P0: 按分类筛选(下拉选择) - P1: 搜索历史记录 - P2: 搜索联想/自动补全 3. 边界条件 → 空搜索、无结果、搜索词过长 4. 输出 → docs/specs/search/requirement.md ✅
Agent → requirement-analysis 验证通过 Agent → 自动触发下一个 Skill:tech-design
|
Step 2:技术设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| Agent → 加载 tech-design Skill Agent → 读取 requirement.md 作为输入 Agent → 按 Skill 步骤执行:
1. 组件拆分: - SearchBar(搜索输入框 + 分类筛选) - SearchResults(结果列表) - SearchFilter(筛选面板) - SearchHistory(搜索历史) 2. 状态管理设计: - useSearch(params) → 搜索请求 - useSearchHistory() → 本地存储 3. 接口设计: - GET /api/products/search?q=&category=&page= 4. 输出 → docs/specs/search/design.md ✅
Agent → tech-design 验证通过 Agent → 输出设计文档后等待人工确认
|
这里注意:AGENTS.md 中设置了”人在环路”,所以 Agent 不会直接进入编码,而是先把设计方案给你看。你确认后告诉它”可以开始编码”。
Step 3:编码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 用户确认: "可以了,开始编码"
Agent → 加载 coding Skill Agent → 读取 design.md Agent → 按 Skill 步骤执行:
1. 创建 SearchBar 组件 → src/components/search/SearchBar.tsx 2. 创建 SearchResults 组件 → src/components/search/SearchResults.tsx 3. 创建 useSearch Hook → src/hooks/useSearch.ts 4. 创建 API 层 → src/api/search.ts 5. 创建类型定义 → src/types/search.ts 6. 注册路由 → src/router/index.ts
Agent → coding 验证通过(LSP 零错误) Agent → 自动触发 test-generation
|
Step 4:生成测试
1 2 3 4 5 6 7 8 9 10 11
| Agent → 加载 test-generation Skill Agent → 读取 coding 产出的源文件 Agent → 按 Skill 步骤执行:
1. 分析 useSearch Hook → 生成 src/hooks/__tests__/useSearch.spec.ts 2. 分析 SearchBar 组件 → 生成 src/components/search/__tests__/SearchBar.spec.ts 3. 分析 SearchResults 组件 → 生成 __tests__/SearchResults.spec.ts
Agent → 运行 npm run test -- --run → ✅ All tests passed Agent → test-generation 验证通过 Agent → 自动触发 code-review
|
Step 5:代码审查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Agent → 加载 code-review Skill Agent → 运行 git diff --name-only 获取变更范围 Agent → 逐文件检查:
SearchBar.tsx: 类型安全 ✅ | 错误处理 ✅ | 性能 ✅ | 可维护性 ✅ | 安全 ✅ SearchResults.tsx: 类型安全 ✅ | 错误处理 ⚠️ | 性能 ✅ | 可维护性 ✅ | 安全 ✅ useSearch.ts: 类型安全 ✅ | 错误处理 ✅ | 性能 ✅ | 可维护性 ✅ | 安全 ✅ search.ts (API): 类型安全 ✅ | 错误处理 ✅ | 性能 ✅ | 可维护性 ✅ | 安全 ✅
Agent → 发现 SearchResults 在空数据时缺少友好的空状态提示 Agent → 标注为"中等"问题,提供修改建议 Agent → 自动回到 coding 步骤修复此问题 Agent → 修复后重新运行 test-generation → ✅ Agent → 重新运行 code-review → ✅ 全部通过 Agent → 输出审查报告 docs/reviews/search-review.md ✅
|
完整工作流示意图
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 37 38 39 40 41
| 用户: "给商城加商品搜索功能" │ ▼ ┌──────────────────────────────────────────────────────────┐ │ ① requirement-analysis Skill │ │ 读取项目背景 → 拆解功能点 → 识别边界条件 │ │ 输出: docs/specs/search/requirement.md │ └────────────────────────────────┬─────────────────────────┘ │ 自动触发 ▼ ┌──────────────────────────────────────────────────────────┐ │ ② tech-design Skill │ │ 读取 requirement.md │ │ 组件拆分 → 接口设计 → 状态管理方案 │ │ 输出: docs/specs/search/design.md │ └────────────────────────────────┬─────────────────────────┘ │ 人工确认 ▼ ┌──────────────────────────────────────────────────────────┐ │ ③ coding Skill │ │ 读取 design.md │ │ 创建组件 → 创建 Hook → 创建 API → 注册路由 │ │ 输出: 源代码变更 │ └────────────────────────────────┬─────────────────────────┘ │ 自动触发 ▼ ┌──────────────────────────────────────────────────────────┐ │ ④ test-generation Skill │ │ 读取源文件 → 生成单元测试 → 运行测试 │ │ 输出: __tests__/*.spec.ts │ └────────────────────────────────┬─────────────────────────┘ │ 自动触发 ▼ ┌──────────────────────────────────────────────────────────┐ │ ⑤ code-review Skill │ │ 逐文件审查 → 发现问题 → 修复 → 重新验证 │ │ 输出: docs/reviews/search-review.md │ └────────────────────────────────┬─────────────────────────┘ │ ▼ ✅ 功能完成,可供提交
|
整个过程,你只说了两句话:
- “给商城加一个商品搜索功能”
- “可以了,开始编码”
剩下的需求分析、技术设计、编码、测试、审查、修复,全部由 Agent 按 Skill 工作流自动完成。这还不是 AI 替你写代码——这是 AI 替你跑了一套完整的开发流程。
5.7 Skill 的迭代与管理
写完了 Skill,是不是就一劳永逸了?不是。Skill 和代码一样,需要持续迭代。
测试一个 Skill
新写的 Skill 怎么验证它好不好用?给 Agent 一个 mock 输入,观察它的表现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 测试用例 1:requirement-analysis Skill 输入: "帮我看一下这个需求,实现用户登录功能" 期望行为: - Agent 先读取项目结构 - 拆解登录功能的功能点 - 输出一份完整的 requirement.md 检查点: - 是否包含了 P0/P1/P2 优先级标注? - 是否包含了边界条件? - Agent 有没有修改代码?(不应该)
测试用例 2:test-generation Skill 输入: "给 src/hooks/useAuth.ts 生成测试" 期望行为: - Agent 读取 useAuth.ts 源码 - 在 __tests__/ 下生成 useAuth.spec.ts - 运行测试并验证通过 检查点: - 测试是否覆盖了正常/异常/边界? - 是否保持了原有业务代码不变?
|
如果某个测试用例中 Agent 的行为不符合预期,说明 Skill 的指令不够清晰或约束不够严格。这时候需要迭代 Skill 文件。
Skill 版本管理
Skill 文件应该放在项目的 .opencode/skills/ 目录下,通过 Git 管理版本:
1 2 3 4 5 6 7 8 9 10 11 12 13
| .opencode/ ├── AGENTS.md └── skills/ ├── requirement-analysis/ │ └── SKILL.md ├── tech-design/ │ └── SKILL.md ├── coding/ │ └── SKILL.md ├── test-generation/ │ └── SKILL.md └── code-review/ └── SKILL.md
|
这样做的好处:
- 团队共享 — 所有人使用同一套 Skill,输出一致
- 版本追溯 — 通过
git log 可以看到 Skill 的演进历史
- 代码审查 — Skill 的变更可以走正常的 MR 流程
- 分支隔离 — 实验性 Skill 可以在分支上测试
什么时候需要新建/更新 Skill
| 场景 |
动作 |
原因 |
| 一个流程反复手动操作 3 次以上 |
新建 Skill |
值得固化为自动化流程 |
| Agent 执行某个步骤总是出错 |
更新 Skill |
指令不够清晰,需要细化 |
| 技术栈升级了 |
更新 Skill |
约束条件和技术参考需要更新 |
| 团队制定了新的规范 |
更新 Skill |
验证标准需要更新 |
| 发现某个步骤可以优化 |
更新 Skill |
流程优化应当及时反映在 Skill 中 |
| 新项目使用不同的框架 |
新建 Skill |
编码方式不同,需要专门的 Skill |
一个实用建议:刚上手时不要追求完美,先写最简可用版本(MVP Skill)。只包含核心步骤和关键约束,然后在实际使用中逐步完善。比花一周时间设计一个”完美”的 Skill 更有价值。
5.8 总结
回顾整篇文章,我们从”每次都给 Agent 写 Prompt”的困境出发,提出了一个更系统化的解决方案:把开发流程拆解成可复用的 Skill,在 AGENTS.md 中编排为完整 Workflow,让 Agent 自主决策工具和 MCP,自动完成整个开发流程。
这个转变的意义在于:
- 从”使用者”变成”设计者” — 你不再每次告诉 Agent 怎么做,而是设计一套让 Agent 自己知道怎么做的体系
- 从”单次对话”变成”永久资产” — Prompt 是一次性的,Skill 是随着项目积累的
- 从”个人经验”变成”团队能力” — Skill 可以共享、审查、迭代,成为团队的工程资产
最后分享一组公式,我觉得可以概括 Agent 工作流的精髓:
1 2 3 4
| Agent 的执行质量 ≈ Skills 的质量 × Workflow 的设计
Skills 的质量 = 指令清晰度 × 约束完整度 × 可验证性 Workflow 的设计 = 流程完整性 × 衔接流畅度 × 容错能力
|
你的 Skill 写得越清晰、约束越完整、验证越严格,Agent 的执行就越可靠。你的 Workflow 设计得越完整、衔接越流畅、容错越完善,Agent 就越能独立完成复杂任务。
这个时代最大的杠杆,不是你用 AI 写了多少代码,而是你设计了多少能让 AI 自动运转的流程。
下一章我们会聊到深度使用 AI 时一定会遇到的坑——AI 幻觉、安全风险、过度依赖等问题,以及对应的防御策略。从设计到避坑,才算完整的 Agent 工作流闭环。