AI时代前端工程师实战指南:Agent工作流

AI时代前端工程师实战指南:Agent工作流

本文定位不一样——不是教你怎么给 Agent 写 Prompt,而是教你怎么设计一套能被 Agent 自动执行的 Skill 体系
把开发流程拆成可复用的指令模块,让 Agent 按工作流自动运转,你从”操作者”变成”设计者”。


5.1 从”写 Prompt”到”设计 Skill”

  上一章我们讲了 Prompt 工程——如何写出结构清晰、约束明确的 Prompt,让 AI 输出更可靠。这是一个巨大的进步,从”随便问两句”到”系统化地写 Prompt”,已经是质的飞跃。

  但用过一段时间后,你会发现一个新问题:每次都要重复写几乎一样的 Prompt

  比如你有一个开发习惯——写任何代码之前先做需求分析,然后出技术方案,再动手编码,最后加测试。这个流程你每次都要在 Prompt 里重申一遍:

1
2
3
4
5
❌ 每次重复:
"先分析需求,列出所有功能点和边界条件"
"然后出技术方案,考虑组件拆分和数据流"
"再开始编码,遵循项目规范"
"最后加测试,覆盖正常路径和异常路径"

  这种做法的弊端很明显:

  1. 不一致 — 今天记得说”先分析需求”,明天可能忘了,Agent 的行为就变了
  2. 遗漏步骤 — 流程有 5 步,你只说了 3 步,Agent 就按 3 步执行
  3. 依赖个人记忆 — 换一个人用,他不知道你的流程是什么,重新摸索
  4. 不可复用 — 换个项目,同样的流程要再写一遍

  这就引出了本文的核心概念: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

&emsp;&emsp;这个 Skill 负责为已有组件或功能生成测试文件。它读源码,写测试,不修改业务代码。

Test Generation Skill

Metadata

  • 名称: test-generation
  • 适用场景: 为一个已有的组件、Hook、工具函数生成单元测试
  • 前置条件: 目标文件的路径已确定
  • 输出产物: src/**/__tests__/<name>.spec.ts.test.ts

执行步骤

  1. 读取目标文件

    • 读取完整的目标源码文件
    • 识别导出的函数、组件、类型
  2. 分析测试需求

    • 对于函数:参数类型、返回值类型、边界条件
    • 对于组件:Props、Slots、Emits、状态变化
    • 对于 Hook:输入参数、返回状态、副作用清理
  3. 生成测试文件

    • __tests__/ 目录下创建对应的测试文件
    • 测试文件命名规则:<原名>.spec.ts
  4. 编写测试用例

    • 至少覆盖以下场景:
      • 正常渲染/调用(Happy Path)
      • 空状态(无数据/null/undefined)
      • 错误处理(异常输入、失败回调)
      • 边界条件(极限值、特殊字符)

约束规则

MUST DO

  • 测试文件必须放在 __tests__/ 目录下
  • 使用项目已有的测试框架和工具(从 package.json 中识别)
  • 每个测试用例必须有明确的 describeit 描述
  • 测试描述使用中文

MUST NOT DO

  • 不要修改被测源文件
  • 不要安装新的测试依赖
  • 不要生成集成测试或 E2E 测试(那是别的 Skill 的工作)

验证标准

  • 测试文件编译无类型错误
  • 测试运行全部通过(npm run test -- --run
  • 覆盖了正常路径、空状态、错误处理、边界条件
  • 没有修改任何业务代码

参考

  • 项目测试配置: vitest.config.ts
  • 现有测试示例: src/components/__tests__/example.spec.ts
1
2
3
4
5

### 示例三:代码审查 Skill

&emsp;&emsp;这个 Skill 负责审查代码变更,从多个维度评估代码质量并输出审查报告。

Code Review Skill

Metadata

  • 名称: code-review
  • 适用场景: 一个功能开发完成,需要审查代码质量后再提交
  • 前置条件: 代码变更已在工作区中,未提交
  • 输出产物: docs/reviews/<feature-name>-review.md

执行步骤

  1. 获取变更范围

    • 运行 git diff --name-only 获取变更文件列表
    • 运行 git diff --stat 了解变更规模
  2. 逐文件审查

    • 对于每个变更文件,依次检查:
  3. 检查维度

    • 类型安全:是否有 any 类型?是否有未使用的变量?
    • 错误处理:异步操作是否有 try/catch?边界情况是否有防御?
    • 性能:是否有不必要的重渲染?是否有内存泄漏风险?
    • 可维护性:函数是否过长?是否有重复代码?命名是否清晰?
    • 安全:是否有 XSS 风险?是否有敏感信息泄露?
  4. 输出审查报告

    • 使用以下格式写入 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 的总控配置

&emsp;&emsp;单个 Skill 解决的是"怎么做一件事"的问题。但实际开发中,一个功能要从需求走到上线,需要多个 Skill 串起来。这时候就需要 AGENTS.md 来当"总控"。

&emsp;&emsp;AGENTS.md 的核心作用有三点:

1. **定义你是谁** — Agent 的角色和核心能力
2. **声明你会什么** — 可用的 Skill 清单
3. **规定按什么流程工作** — Skill 的执行顺序和触发条件

&emsp;&emsp;下面是一个完整的 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 的 describeit“,也没有说”运行 npm run test“。Agent 加载 SKILL.md 后,会自主决策

  1. 读项目配置package.json 中发现测试框架是 Vitest
  2. 读现有测试 — 发现项目中使用 describe / it / expect 模式
  3. 选择工具 — 决定用 Vitest 的 API 编写测试
  4. 执行验证 — 运行 npm run test -- --run 来确认测试通过

  再举一个更直观的例子。假设你有一个 Skill 要求”验证 UI 表现”:

1
2
3
4
5
验证步骤:
3. 打开浏览器检查页面渲染效果
- 确认组件在不同视图尺寸下的布局
- 确认交互动效正常
- 截图保存到 docs/screenshots/

  Agent 加载这条指令后,会做以下决策:

  1. 分析需求 — “打开浏览器” → 需要浏览器自动化工具
  2. 扫描可用 MCP — 发现 opencode.json 中配置了 Playwright MCP
  3. 调用 MCP — 通过 Playwright MCP 启动浏览器、导航到页面、截图
  4. 保存结果 — 将截图写入 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 │
└────────────────────────────────┬─────────────────────────┘


✅ 功能完成,可供提交

  整个过程,你只说了两句话:

  1. “给商城加一个商品搜索功能”
  2. “可以了,开始编码”

  剩下的需求分析、技术设计、编码、测试、审查、修复,全部由 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

  这样做的好处:

  1. 团队共享 — 所有人使用同一套 Skill,输出一致
  2. 版本追溯 — 通过 git log 可以看到 Skill 的演进历史
  3. 代码审查 — Skill 的变更可以走正常的 MR 流程
  4. 分支隔离 — 实验性 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 工作流闭环。