---
url: /wave-agent/tutorials.md
---

# 教程 & 最佳实践

## 一、研发场景实用工具推荐

本文面向实际研发场景，整理并推荐了一组可直接应用于日常开发流程的 Agent 工具——既有开箱即用的 Skill（技能），也有 MCP 服务器与 LSP 等能力。分别针对具体任务提供明确的能力边界与使用场景说明，帮助你在不同阶段选择合适的工具，提高开发效率。

CodeWave IDE 的能力主要来自**内置**（开箱即用，无需安装）与**插件市场**（在对话中输入 `/plugin` 打开插件市场，搜索插件名并安装）两部分，涵盖 Skill（技能）、MCP 服务器与 LSP 等。其中技能由 AI 根据任务描述自动匹配调用，也可以显式点名或用 `/技能名` 直接触发；MCP / LSP 安装后由 AI 按需自动调用。此外，`gh` / `glab` 这类平台 CLI 工具装好并认证后，AI 可直接驱动它们完成 PR / MR 相关操作，推荐一并配置。

### 1. 需求与规划

这一阶段的重点是：把模糊的想法变成清晰的规格，让后续编码有据可依。

* **SDD（内置）**——规格驱动开发：把模糊需求自动整理成功能规格说明（用户故事 + 验收场景），内置校验脚本统计规格完整性，并用单选衔接「技术方案（可选）→ 执行」。SDD 插件默认关闭，先在「设置 → 项目设置」启用「SDD」开关（写入项目 .wave/settings.json）。
  * 场景：新功能从想法到可执行规格的全过程。
  * 示例："把'支付模块改造'的需求写成规格说明，先 clarify 一下有哪些歧义。"
* **/plan（内置）**——进入计划模式：AI 只允许修改计划文件（`.wave/plans/` 目录），用于协作制定和完善开发计划，不直接改动项目代码。`/plan` 查看当前计划，`/plan <描述>` 切换计划模式并立即开始规划。
  * 场景：动手写代码前先明确方案；规划阶段限制 AI 只产出计划。
  * 示例："用 /plan 先出一份支付模块迁移方案。"

### 2. 编码实现

进入编码阶段，以下技能帮助你设计高质量方案并落地实现。

* **frontend-design**（插件市场）——创建独特的、生产级的前端界面，避免千篇一律的"AI 风格"。
  * 场景：网页、着陆页、海报、React 组件等一切需要视觉设计的界面。
  * 示例："做一个分享海报"。
* **typescript-lsp**（插件市场）——TypeScript/JavaScript 语言服务器，提供代码补全、跳转定义、查找引用、符号搜索、类型提示与错误诊断。
  * 场景：大型 TS 项目的精准代码智能（对 IDE 内置能力的补充）。
  * 示例："用 typescript-lsp 检查这个接口的调用方有哪些，类型是否有误。"

### 3. 代码质量与提交

写完之后，用这一组技能把代码打磨干净并安全合入。

* **gh / glab（CLI 工具）**——GitHub CLI 与 GitLab CLI，分别对应 GitHub 与 GitLab / 内部 GitLab 仓库。安装并认证（`gh auth login` / `glab auth login`）后，AI 可以直接创建与查看 PR / MR、发表审查评论、查询 CI 状态，不必再手工复制粘贴链接；内置的 `code-review` 与插件市场的 `commit-skills`（提交、推送 MR/PR、等待合并）都依赖它们。
  * 场景：提交后自动开 PR / MR、按审查意见逐条回复、盯 CI 与合并状态。
  * 示例："把这次改动推上去开个 MR，并回复刚才的审查意见。"
* **code-review**（内置）——审查当前 diff，按力度查找正确性 bug 与简化机会，并直接给出修改建议。
  * 场景：提交前的自查、合并请求评审。
  * 示例："用 code-review 审查这次改动。"（`/code-review` 直接触发）
* **simplify**（内置）——审查并直接修复代码的复用、简化与效率问题（不找 bug）。
  * 场景：代码重复、过度设计、可读性差的清理。
  * 示例："用 simplify 优化这个模块，去掉重复逻辑。"
* **commit-skills**（插件市场）——简化 Git 工作流，包含 `commit`（提交）、`commit-push-mr` / `commit-push-pr`（提交并推送 MR/PR）、`watch-merge-mr` / `watch-merge-pr`（等待合并）5 个技能，覆盖从提交到合并的全流程。
  * 场景：规范的提交信息与自动化的 MR/PR 流程。
  * 示例："用 commit-skills 提交这次改动并推送 PR。"

### 4. 测试与调试

* **先诊断再修复（提示词实践）**——遇到 bug 时明确要求 AI 先定位根因、给出证据，再动手改，避免盲试；新功能先用测试驱动，先写能复现的失败用例，实现后再确认转绿。
  * 场景：疑难 bug、测试失败、易回归的核心逻辑。
  * 示例："先写一个能复现这个偶发超时的测试，再修到它转绿。"
* **Playwright CLI**（命令行工具）——通过 Bash 直接驱动真实浏览器：页面导航、抓取可交互元素快照、点击、填充、执行脚本与断言。命令按需取数，不必把工具 schema 与整棵页面无障碍树塞进上下文，**比 MCP 方案更省 token**（安装：`npm install -g @playwright/cli@latest`）。
  * 场景：Web 应用端到端验证、抓取接口请求、复现前端问题。
  * 示例："用 playwright-cli 打开本地页面，检查登录流程的接口请求。"（详见[第四部分](#四、实现网页自动化测试)）

### 5. 文档与知识沉淀

代码之外，文档质量同样决定团队效率。下面这些工具负责把成果沉淀成文档；至于「AI 怎么读到团队已有的知识」，见[第七部分：研发知识库](#knowledge-base)。

* **deep-wiki**（插件市场）——AI 驱动的 Wiki 生成器，支持 Mermaid 图表、源码引用、入职指南与 llms.txt 生成，内置 3 个子代理（wiki-architect / wiki-researcher / wiki-writer）。
  * 场景：为新仓库快速搭建团队 Wiki、维护架构文档。
  * 示例："用 deep-wiki 为这个仓库生成一份带架构图的 Wiki。"
* **document-skills**（插件市场）——办公文档处理套件：docx（Word）、xlsx（Excel）、pptx（PowerPoint）、pdf，可读取、创建、编辑并支持格式转换。
  * 场景：需求文档、表格数据、汇报 PPT、PDF 解析。
  * 示例："帮我把这份 docx 转成带修订标记的版本。"
* **artifact**（内置）——把本地 HTML 或 Markdown 发布成可分享的网页链接，一键生成、可更新、默认私有。
  * 场景：把报告、原型、迁移计划分享给团队。
  * 示例："把这份 Markdown 做成可分享的网页。"
* **init**（内置）——分析代码库并生成 AGENTS.md，沉淀项目级与用户级指令，让 AI 在不同会话间保持一致。
  * 场景：新仓库起步、接手陌生项目。
  * 示例："用 init 分析这个仓库并生成 AGENTS.md。"
* **llms.txt**（文档站约定）——在文档站根目录放一份 Markdown 索引 `llms.txt`，把站点结构与关键链接交给 agent，业界已在广泛采用（`deep-wiki` 也支持直接生成）。
  * 场景：让外部 agent 与工具快速理解你们的文档站结构，而不只是给人看。
  * 示例："给这个文档站生成一份 llms.txt。"

### 6. 调研与日常效率

* **tavily-search**（插件市场）——Tavily AI 搜索引擎 MCP 服务器，为 Agent 提供实时网络搜索能力。
  * 场景：需要最新资料、文档查询、版本信息确认。
  * 示例："用 tavily-search 查一下这个 API 的最新变更。"
* **loop**（内置）——定时循环执行指令，适合轮询、监控、定期检查。
  * 场景：监控服务状态、定时跑检查脚本。
  * 示例：`/loop 5m 检查服务状态`
* **settings**（内置）——管理 Wave 配置（settings.json、hooks、MCP、插件等）。
  * 场景：调整模型、配置钩子、注册 MCP 服务。
  * 示例：`/settings 帮我加一个 PreToolUse 钩子`

> 提示：能力支持叠加使用——例如先用 SDD 把需求写成规格，再用 `frontend-design` 实现界面，最后用 `commit-skills` 走完提交到合并的流程（依赖 `gh` / `glab` 完成实际的 PR / MR 操作）。描述任务时直接说明目标，AI 会自动匹配合适的能力。

***

## 二、将 Figma 设计稿转化为前端代码

设计稿还原是前端开发的高频场景。通过 MCP（Model Context Protocol），CodeWave IDE 可以连接 Figma 设计稿数据，让 AI 直接读取设计稿的布局、颜色、字体与图片资源，一键生成与设计稿高度一致的响应式页面。

本教程以 Figma 的 MCP 服务器（`figma-developer-mcp`，社区版）为例，演示从配置到出码的完整流程。Figma 官方也提供 MCP 服务器，如果条件允许，官方 MCP 同样极力推荐。

### 1. 准备：获取 Figma Access Token

Figma 通过 Personal Access Token 授权第三方应用访问设计稿数据。

1. 登录 [Figma](https://www.figma.com/)，点击左上角用户头像 → **Settings**。
2. 在顶部菜单选择 **Security**，滚动到 **Personal access tokens** 部分，点击 **Generate new token**。
3. 输入 Token 名称（如 `codewave-figma`）、设置有效期，并勾选所需权限，点击 **Generate token**。
4. 复制生成的 Token（只显示一次，请妥善保存）。

> 注意：Token 仅授权访问其持有者账号有权限的设计稿；分享设计稿给该账号后再使用。

### 2. 在 CodeWave IDE 中添加 Figma MCP 服务器

打开 CodeWave IDE 设置 → **MCP**，点击「添加 MCP 服务」，选择类型并填写配置：

* **stdio 类型**（推荐，本地运行）：
  ```json
  {
    "mcpServers": {
      "figma": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "figma-developer-mcp", "--stdio"],
        "env": { "FIGMA_API_KEY": "你的 Access Token" }
      }
    }
  }
  ```
* **http 类型**：如果使用远程托管的 Figma MCP 服务，填写服务 URL 并在 headers 中携带 Token。

保存后服务器自动连接，列表显示连接状态。

![MCP 设置页](/screenshots/desktop-settings-mcp.webp)

> 也可以直接在项目根目录创建 `.mcp.json`（同上的 `mcpServers` 结构），启动时自动加载。更多配置方式见 [桌面版文档 - MCP](/desktop#_5-1-mcp)。

### 3. 对话中粘贴设计稿链接，提出需求

在本地打开项目文件夹（CodeWave IDE 桌面端「打开项目」，或插件端中打开工作区），然后把 Figma 设计稿的选中区域链接复制到对话中：

1. 打开 Figma 设计稿，选中要还原的 Frame。
2. 右键 → **Copy/Paste as** → **Copy link to selection**，复制设计稿链接。
3. 在 CodeWave IDE 输入框中粘贴链接并描述需求，例如：

> 请严格按照这个 Figma 链接生成登录页的响应式 HTML，视觉细节要跟设计稿一致：https://www.figma.com/design/9xYkZ0vF/Login-Page（含移动端与桌面端两套布局）

AI 会自动匹配并调用 Figma MCP 工具：先读取设计稿布局信息（`get_figma_data`），再下载其中的图标与图片资源（`download_figma_images`），最后生成 `index.html`：

![Figma 设计稿转代码](/screenshots/desktop-figma-mcp.webp)

**首次调用需授权**：MCP 工具首次使用时弹出权限确认，勾选「总是允许」后存为信任规则，后续调用免确认：

![MCP 工具确认](/screenshots/desktop-mcp-confirm.webp)

### 4. 预览与迭代

生成完成后，在预览面板（或浏览器中）打开 `index.html` 查看效果，继续对话迭代优化：

* "背景色跟设计稿再贴近一点，改成 #4A90D9 的渐变"
* "移动端断点下把表单挤成单列"
* "图标用设计稿里的 SVG，不要用 iconfont"

每一次反馈都会在同一个对话上下文里继续，AI 会基于设计稿数据与你的意见持续调整。

### 常见问题

* **工具调用失败**：确认 Token 有效且对设计稿有访问权限，服务器连接状态正常（设置 → MCP 可查看）。
* **链接无法读取**：使用 **Copy link to selection** 复制的链接，而不是浏览器地址栏的链接；确保设计稿已分享给 Token 所属账号。
* **生成的样式与设计稿有偏差**：在设计稿中确认 Frame 命名与图层结构清晰，描述需求时补充关键要求（如响应式断点、主色值）。

***

## 三、SDD开发案例

SDD（规格驱动开发）是随 CodeWave 内置的插件：在写代码之前先用功能规格说明（用户故事 + 验收场景）明确设计，走完「规格 → 技术方案（可选）→ 执行」的完整工作流。下面介绍插件的启用方式与工作流全流程。

### 1. 启用 SDD 插件

SDD 插件默认关闭，不干扰日常使用。启用方式：在设置页「项目设置」视图切换「SDD（规格驱动开发）」开关，开关状态与项目 `.wave/settings.json` 的 `enabledPlugins` 保持同步。**插件变更不会自动生效**：切换后当前对话仍按旧配置运行，在对话框里输入 `/reload-plugins` 即可在本对话内就地生效（不用重启会话、也不打断正在进行的回复）；也可以什么都不做，直接新开一个对话，它会自动按新配置装载。详见 [桌面端文档 - 项目设置](/desktop#_6-4-项目设置)：

![项目设置视图 SDD 开关](/screenshots/desktop-settings-project.webp)

### 2. 规格驱动开发工作流

启用 SDD 插件后，当你提出新的功能需求或修改需求时，AI 会引导你走完「规格 → 技术方案（可选）→ 执行」的工作流：先编写或更新功能规格说明并请你确认，再按需制定技术方案，最后选一种执行方式开始实现。各阶段之间的衔接均通过单选按钮完成。

**第一阶段：规格编写与确认**

提出需求后，AI 自动编写功能规格说明（用户故事 + 验收场景）；编写完成后通过单选弹窗请你决策——选择「直接实现」即直接进入执行、选择「制定技术方案」进入可选的技术方案阶段；如需调整规格，选择弹窗末尾的「其他」并输入修改意见，AI 会按反馈更新规格后再次请求决策。

![规格编写阶段](/screenshots/desktop-sdd-workflow-spec.webp)
*规格编写阶段：AI 产出规格说明并写入 `docs/specs/` 文件，点击消息中的文件路径可在右侧文件面板预览完整 spec；编写完成后通过单选弹窗请你决策（「直接实现 / 制定技术方案」，「其他」用于输入调整意见）*

**第二阶段（可选）：技术方案**

在规格决策弹窗中选择「制定技术方案」后，进入技术方案模式制定技术方案（技术选型、架构设计、实现步骤）。方案全文在桌面端的计划面板中展示（与对话并排的右侧面板）；确认框保持紧凑，方案正文不进入对话消息列表，方案经你批准后才开始执行。

![技术方案预览](/screenshots/desktop-sdd-plan-preview.webp)
*技术方案预览：方案全文在右侧计划面板中展示，对话与方案并排对照；确认框保持紧凑（方案正文不进入消息列表），提供「批准并继续」「批准并自动接受后续修改」「提供反馈」等选项，批准后开始执行*

**第三阶段：执行实现**

方案批准后进入执行阶段，入口先选一次执行方式：普通执行（本会话逐项写完，最后整体评审）、子代理驱动（每个任务一个子代理实现 + 一个评审）、工作流编排（用 Workflow 按任务清单跑，后台执行、可用 `/workflows` 看进度）。选定后按规格里的验收场景逐项实现，中途不再询问是否继续，全部完成后做一次整体评审。

**迭代已有需求：更新既有规格**

当需求是对已有功能的修改时，AI 不会另起新规格，而是直接更新对应的既有规格文件（沿用已有的规格目录与分组命名，新增用户故事和验收场景）；更新完成后同样通过单选弹窗请你决策——选择「其他」并输入意见时按反馈继续调整，选择「直接实现」或「制定技术方案」后按更新后的规格重新汇入相应阶段。

![迭代需求-更新规格](/screenshots/desktop-sdd-iterate-update.webp)
*迭代已有需求：AI 更新既有规格文件（Edit 修改以 diff 形式在消息中展示），右侧差异面板预览 spec 文件的具体改动；更新完成后通过单选弹窗请你决策（「直接实现 / 制定技术方案」，「其他」用于输入调整意见）*

具体规格详见：[docs/specs/](/specs/)。

***

## 四、实现网页自动化测试

功能验证与回归测试是保证页面质量的关键。CodeWave IDE 可以让 AI 直接驱动真实浏览器完成"打开页面 → 操作元素 → 校验结果"的自动化测试，并把结论整理成测试报告。

本教程推荐 **Playwright CLI**（`playwright-cli`）：它由 AI 通过 Bash 工具直接调用，无需安装插件或配置 MCP；命令简短、只在需要时抓取页面数据，**不必把工具 schema 与整棵页面无障碍树塞进模型上下文，因此比 MCP 方案更省 token**。

### 1. 安装 Playwright CLI

```bash
npm install -g @playwright/cli@latest   # 需要 Node.js 18+
playwright-cli --help                   # 确认安装成功
```

可选：把它的用法安装成技能，AI 会自动匹配加载（写入项目 `.agents/skills/`，Wave 会识别该目录）：

```bash
playwright-cli install --skills=agents
```

不装技能也可以——直接让 AI 读 `playwright-cli --help` 自己上手。

### 2. 对话驱动自动化测试

直接用自然语言描述测试目标即可。AI 会用 `open` 打开页面、`snapshot` 抓取可交互元素快照（每个元素带 `ref`）、再用 `fill` / `click` / `select` / `press` 操作元素，最后用 `screenshot` / `eval` 校验结果：

> 打开登录页 https://example.com/login，填写账号密码点击登录，检查是否跳转成功并截图，最后把测试结论写成 test-report.md

对应的命令大致如下：

```bash
playwright-cli open https://example.com/login --browser chrome
playwright-cli snapshot          # 拿到页面上各元素的 ref
playwright-cli fill e3 "dev@example.com"
playwright-cli fill e4 "******"
playwright-cli click e5
playwright-cli screenshot        # 校验渲染结果并留证
```

几个容易踩的点：

* **ref 每次都变**：页面一变就重新 `snapshot`，不要复用旧 ref。
* **本地服务优先用 `127.0.0.1`**：部分环境下 `localhost` 会连接异常。
* **`--headed` 可以看着浏览器跑**（调试时好用）；`--device "iphone 15"` / `--mobile` 用于移动端视口校验。
* 快照文件默认落在当前目录的 `.playwright-cli/`。

> Bash 命令首次执行时可能弹出权限确认，勾选「总是允许」后存为信任规则，后续免确认。

### 3. 常用测试指令

* **打开并校验页面**："打开 https://example.com，检查标题和加载状态"
* **表单流程测试**："注册流程：填写表单、提交、校验成功提示"
* **元素交互**："点击首页的『了解更多』按钮，确认跳转到文档页"
* **视觉校验**："对移动端视口截图，检查布局是否有溢出"
* **控制台检查**："检查这个页面控制台有没有报错，把错误列出来"

### 4. 测试报告与回归

AI 会把测试结果整理为结构化的测试报告（用例、步骤、结果、控制台错误、截图），写入项目文件，便于跟踪与回归：

* **首次测试**：让 AI 生成覆盖核心流程的测试步骤并执行
* **回归测试**：修复后让 AI 重跑关键用例："按 test-report.md 里的用例重新跑一遍登录流程"
* **持续集成**：把生成的测试脚本接入 CI，配合定时循环技能（`/loop`）定期巡检页面可用性

***

## 五、云端编程：远程主机上的后台会话 {#cloud-programming}

把会话放到 SSH 远程主机上跑，就是这里的「云端编程」：代码、依赖、构建环境都在远端，本地只负责看和指挥。会话由远端 daemon 托管——**关掉桌面端，它仍在远端继续运行**。

### 1. 连接远程主机 {#cloud-connect}

在新对话里，点工作目录选择器左侧的主机下拉 →「添加主机」，填 `ssh user@hostname -p port` 形式的连接串，连上后点「浏览…」选远端目录即可开始会话。整个 CLI 子进程经 `ssh <host> -- wave --stdio` 在远端执行，读写文件、搜索、bash、git 等工具全部作用在远端文件系统，右侧的终端与差异面板同样跑在远端机器上（体验与 VS Code Remote-SSH 一致）。远端**不需要预装 Node.js**，也不必 npm 装包：桌面端会经 ssh 推送本机内置的同一份 CLI（按字节比对，不一致才推），以及与远端平台匹配的 Node 运行时。

![主机选择器](/screenshots/desktop-ssh-host-selector.webp)

### 2. 关掉桌面端，任务继续跑 {#cloud-background}

* **断线不停**：ssh 中断、锁屏睡眠、直接退出桌面端，远端会话照常生成与执行；远端 daemon 空闲也不退出，任务跑完后再连上还是同一个进程。
* **回来即接上**：重新打开应用连上该主机，侧边栏直接列出后台会话并标注「运行中」/「待确认」，点进去是**接入**而不是重放历史——断线期间产生的消息、正在流式输出的回复都补回来，发送、中断、审批照常；应用还开着时断线（网络闪断、锁屏唤醒）会自动重建隧道接回，不必手动点侧边栏。
* **审批会等你**：没有客户端连接时遇到需要确认的步骤，会话挂起为「待确认」不继续推进；接回后弹出确认框，确认即继续。
* **删除即终止**：删掉一条后台会话，远端对应的 agent 一并终止。

![远程后台会话](/screenshots/desktop-ssh-background-sessions.webp)
*侧边栏中该主机的会话：运行中显示转圈、等待确认显示琥珀点*

### 3. 边界 {#cloud-limits}

* 通信全走 ssh 隧道，远端 daemon 不监听公网，也不新增凭据体系（沿用现有 ssh 密钥）。
* 远端机器重启、或 CLI 升级重启 daemon 时，断线前正在进行的任务会终止；历史会话仍能从远端转录恢复，不会留下假的「运行中」状态。
* 后台保活只对远程会话生效：本地会话在退出应用时照常终止。

细节见[桌面端文档 - 打开项目](/desktop#_1-2-打开项目)与[功能规格说明：桌面端会话管理](/specs/desktop/desktop-sessions)。

***

## 六、接入本地模型 {#local-model}

默认模型请求走 CodeWave 服务端网关。把网关地址、密钥与模型名换成自建的 OpenAI 兼容端点（vLLM、Ollama、私有网关等，需提供 `/v1/chat/completions`），就接入了本地模型。配置写在用户级 `~/.wave/settings.json`：

```json
{
  "env": {
    "WAVE_BASE_URL": "https://gw.customer.com/v1",
    "WAVE_API_KEY": "sk-xxxxxxxxxxxxxxxx",
    "WAVE_MODEL": "qwen3.8-max",
    "WAVE_FAST_MODEL": "qwen3.5-flash",
    "WAVE_VISION_MODEL": "qwen3.8-max",
    "WAVE_CONTEXT_WINDOW": "200000"
  },
  "models": {
    "qwen3.8-max": {
      "capabilities": { "vision": true, "promptCaching": true }
    },
    "qwen3.5-flash": { "capabilities": { "vision": false } }
  }
}
```

> ⚠️ **直接接入本地模型会丢失大量服务端能力**：artifact 发布与评论、遥测与「研发效能」看板、远程控制（手机 / Web 端接管）、企业管控台、托管配置下发等都依赖 CodeWave 服务端与登录态，换成自建端点后这些能力没有数据或直接不可用；并且登录状态下请求固定走服务端网关（`{服务端}/api/v1`），自建端点不生效，用本地模型需先退出登录。确实需要接入本地模型时，**建议私有化采购部署服务端**——模型可以自建，服务端能力保留。

字段说明：

* `WAVE_BASE_URL` 填到 `/v1` 这一层；本地服务不校验密钥时也要给 `WAVE_API_KEY` 一个非空值，否则客户端直接报 `Missing credentials`。
* `WAVE_MODEL` / `WAVE_FAST_MODEL` / `WAVE_VISION_MODEL`：主模型、轻量任务（子代理摘要、网页取内容等）用的快模型、内置 vision 子代理用的读图模型（后者仅在主模型声明 `vision: false` 时才注册）。
* `WAVE_CONTEXT_WINDOW` 按模型上下文窗口设；需要逐模型不同就写 `models[<模型名>].contextWindow`，压缩阈值与用量显示都按它算。
* `models[<模型名>].capabilities`：`vision`（能否读图，默认 `true`）、`promptCaching`（是否注入 Anthropic 风格的 `cache_control` 缓存标记，默认 `false`，端点不支持就别开）、`apiType`（该模型的请求走哪种协议，默认 `"chat"`，可选 `"chat"` / `"responses"` / `"messages"`——`"responses"` 表示发到 Responses 端点 `/v1/responses`：GPT-5.4 之后带工具的请求只允许 `reasoning_effort: "none"`，而没有 `none` 档的模型（如 `gpt-6.1-sol`）会一律返回 400，这类模型必须选它；`"messages"` 表示发到原生 Anthropic Messages 端点 `/v1/messages`：Claude 开扩展思考时必须选它，因为 OpenAI 兼容层会把思考块压成一个字符串并丢掉逐块的 `signature`，而 Messages 端点要求原样回传）；生成参数（`temperature`、`max_tokens` 等）写在同级的 `options` 里，走 Responses 时 Wave 会把这些参数名翻译过去（`reasoning_effort`→`reasoning.effort`、`max_tokens`→`max_output_tokens`、`response_format`→`text.format` 等），其余键原样透传。

改完下一轮对话即生效，无需重启。

只有一处不跟：**桌面端左下角的账户卡片**。它只在窗口重新加载、切换主机、登录/退出登录时重新判断凭据形态，所以改完文件后卡片可能还是旧样子（例如仍显示「登录」按钮，或仍写着「自定义网关」而实际已换成别的网关）。这时**对话本身已经用上新配置**，重开一次窗口卡片就对上——不是文件写错了。

***

## 七、研发知识库：团队知识如何进入 AI {#knowledge-base}

客户常问「你们的知识库是自带还是要接入其他平台」。这一节讲清团队知识进入 AI 工作上下文的四种载体，以及为什么是这个形态。

### 1. 团队知识如何进入 AI 的工作上下文 {#knowledge-carriers}

**不需要把知识搬进某个平台**——AI 直接在你的项目与已有知识平台上按需取用，共四类载体：

| 载体         | 装什么                                   | CodeWave IDE 里的形态                                                |
| ------------ | ---------------------------------------- | -------------------------------------------------------------------- |
| 项目知识     | 构建命令、目录结构、编码约定、团队规范   | `AGENTS.md`：`/init` 分析代码库自动生成，分项目级与用户级            |
| 流程知识     | 部署清单、评审流程、领域工作流           | Agent Skills：插件市场安装，AI 按需自动调用，也可 `/技能名` 显式触发 |
| 外部知识     | 内部 Wiki、Confluence / 语雀 / Notion 等 | MCP 服务器：安装后由 AI 按需调用                                     |
| 企业自有文档 | 员工手册、制度、流程文档                 | 内置检索工具 `kb_search` / `kb_get_doc` / `kb_suggest`，按需检索     |

每类都可以现场演示一句话：

* **项目知识**：在新仓库里执行 `/init`，AI 扫完代码库写出 `AGENTS.md`，下一个会话它就知道构建命令与编码约定。
* **流程知识**：在插件市场装一个技能（如 `commit-skills`），直接说「提交并推送 PR」即触发——技能平时只加载名字与描述，用到时才读全文。
* **外部知识**：接一个语雀 / Confluence 的 MCP server，直接说「按语雀上的《支付模块设计》实现」，AI 会去读那篇文档。
* **企业自有文档**：在企业端「知识库」传一份《员工手册》，直接问「婚假怎么申请」——AI 检索到「员工手册 > 假期制度 > 婚假」，答出「3 个工作日，需提前三个工作日提交申请」，并标出文档名与章节。你也不用帮它纠词：它拿不准公司怎么写时会先看一眼语料里的实际说法（问「带薪假期」能翻出公司写的是「婚假」），换个词再搜。

> 企业知识库默认关闭：在设置页「全局设置」→「基础设置」里打开「企业知识库」即可（也可以手改 `~/.wave/settings.json` 或项目的 `.wave/settings.json` 里的 `"enableKnowledgeBase": true`），保存后下一轮对话生效。开启后 AI 有 `kb_search`（检索）、`kb_get_doc`（读某条命中的全文）、`kb_suggest`（拿语料里出现过的相近词换个写法重搜）三个内置工具。文档由企业管理员在企业端「知识库」页上传 / 删除，成员只能查看列表；AI 只能搜到本企业上传的文档，过滤在服务端做。

![企业端「知识库」页面](/guide/knowledge-base.webp)

### 2. 为什么是这个形态 {#knowledge-rationale}

Claude Code 官方把上下文窗口形容为稀缺资源——「填满得很快，性能随之下降」，所以业界主流做法是**渐进式披露（progressive disclosure）**：启动只加载名字与描述，用到时才读全文（[来源](https://code.claude.com/docs/en/best-practices)）。官方对 Agent Skills 的定位是「**就像给新员工写一份入职指南**」（[来源](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills)）。

### 3. 语料很大时：用 MCP 接知识平台 {#knowledge-large-corpus}

企业内部制度 / 流程文档（几十到几百份）用内置的企业知识库就够，不必为此搭知识平台；跨库检索、语义检索、或语料远超上下文时才轮到 MCP。

如果语料大到塞不进上下文（官方给的经验判据：超过约 200,000 token / 约 500 页），或者需要跨库语义检索，推荐**用 MCP 接客户自己的知识平台**——Confluence / 语雀 / Notion 都有成熟 MCP server，装好即用（配置方式见[桌面版文档 - MCP](/desktop#_5-1-mcp)）。

***

## 八、研发效能度量与治理 {#metrics-governance}

客户在采购前几乎一定会问两件事：**用了之后我怎么知道谁在用、花了多少、交付有没有变好**，以及**会不会把我们的代码和提问拿到别处**。这一节把度量的口径、可用的数据通道与治理边界一次讲清。

### 1. 效能度量分三层看 {#metrics-layers}

度量数据只能回答一部分问题，通常分三层看：**前两层我们直接供数，第三层里 AI 参与的那部分我们也供数，剩下的要和企业自己的研发平台打通**。

| 层次       | 回答的问题         | 数据来源                                                                                                                          |
| ---------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| 采用度     | 谁在用、用得多深   | 企业端「研发效能」页面（按用户 / 按仓库的排行与产出贡献、会话与事件明细）+ 管控台的积分用量趋势与企业用量统计                     |
| 用量与成本 | 消耗了多少         | 企业端「用量统计」页的 API 调用明细 + 管控台的企业用量统计 + SDK 用量回调 / 遥测导出                                              |
| 交付结果   | 交付变快、变稳了吗 | AI 参与的活动量（提交数 / PR-MR 数 / 变更行数）由客户端本地识别后上报；交付周期与稳定性需与企业自己的 Git / CI / 项目管理平台打通 |

* **采用度看的是趋势和阻力，不是考核**：用的人少，先去找原因（缺文档、缺权限、场景不匹配），而不是拿来做排名。
* **交付结果这一层分两半**：AI 参与的活动量我们直接供数——客户端在本地识别「经由工具成功创建的提交」「经由工具发起的 PR / MR」与编辑类工具写入的增删行数，是纯命令行行为检测，不依赖任何托管平台（私有化 GitLab 与公有 GitHub 同等成立）。但**交付变快、变稳最终要看企业自己的数据**：周期时间、吞吐、稳定性这类指标来自企业自己的 Git / CI / 项目管理数据，需要与用量数据打通后一起看——这也是业界一致做法。

业界共识也支持这个口径：SPACE 框架指出**没有单一指标能刻画生产力**，建议至少跨 3 个维度测量；Google DORA 报告显示 AI 采用与交付吞吐可能正相关，但与**交付稳定性仍呈负相关**——所以 AI 使用指标必须和交付指标一起看。

> 免责一句：代码行数是活动量指标而非质量指标——业界（含 Anthropic 自己的研究）都指出用它衡量生产力会高估，重构反而会减少行数。我们把它定位成参考，不作为绩效。

### 2. 企业端「研发效能」页面 {#efficiency-board}

前两层里客户端能供的那部分，在企业端运营平台的「研发效能」页面直接可看。这个页面**只讲研发效能**，指标面就是四族：**活跃会话、提交、PR / MR、代码行变更**。

* **概览卡**：活跃会话、提交、Pull Request、代码行变更（代码行变更同时给新增与删除行数）。
* **时间趋势**：选一个指标看走势（会话 / 提交 / PR / 新增行 / 删除行），按自然日分桶，窗口跨度不超过一天时改用小时；图下方是同一批数值的等值表（列全这五个指标），便于核对与复制。
* **维度排行 / 产出贡献**：两张卡能力相同，都支持「用户 / 仓库」两个维度与上面那五个指标，按所选指标降序并给出**该指标的**占比（超出前 10 名的取值聚合成「其他」，相加仍等于合计）。默认组合分别是「用户 × 提交」（谁在产出）与「仓库 × 新增行」（改动落到哪些仓库）。
* **事件计数与两张明细表**：事件按「会话开始 / 结束、用户输入、工具决策、上下文压缩、错误」分别计数；会话明细逐会话列出提交、PR 与增删行数，事件明细逐条列出事件内容及其用户 / 会话 / 模型 / 仓库归属，两张表都可搜索、排序、分页。
* **导出入口随卡片**：时间趋势、维度排行、产出贡献各自带一个导出入口，导出恒等于该块**当前呈现**的数据（当前窗口、该块的维度与指标，含「其他」聚合项）。

**Token、缓存命中与调用明细不在这个页面**：它们归「用量与成本」，在同一个运营平台的「用量统计」页（见第 3 节）；本页筛选行右侧也有一条「用量与成本见『用量统计』」的入口。请求数、错误数与平均请求耗时同样不在本页——它们不属于研发效能口径，也不参与本页的任何数字（后端取数按四族指标的白名单走）。

![企业端「研发效能」页面](/guide/efficiency.webp)

* **数据来自成员客户端上报**，不是网关侧推断——所以看得见「本机提交了多少次」「改了多少行」这类只在客户端发生的事实。页面顶部标注数据覆盖窗口、分桶粒度（自然日 / 小时）与最后一次上报时间；数据是客户端周期上报后落库的，**最新时段可能还不完整**，别把「还没上报完」读成「用量下降」。
* **「活跃会话」是「窗口内有上报活动的会话数」**，不是「窗口内新开的会话数」：客户端的增量上报没有心跳，窗口内没有活动的会话不出现在明细里——那是正常现象，不是丢数据。
* 该页面由**内置上报通道**供数（见第 4 节），不需要企业自建收集器；入口只对企业端管理员可见。

### 3. 用量与成本 {#usage-cost}

token 明细本身在企业端运营平台的「用量统计」页看：「API 调用明细」按用户与模型展示输入 / 输出 / 显式与隐式缓存命中 / 缓存创建，另有「套餐调用明细」，两种明细都能按调用次数 / 用户 / 模型 / 日期分组并给出计费。**「研发效能」页面不再重复呈现这些**，只在上方给一个跳转入口。需要接进企业自建平台、或要做到逐次可追溯时，用 Agent 侧的两条通道：

* **按交互追溯**：SDK 中每条助手消息带各自的用量元数据，可追溯到具体一次交互。
* **单次会话核对**：CLI 会话退出时按模型打印 token 总量摘要。

### 4. 遥测导出：三条通道 {#telemetry-export}

CodeWave IDE 的遥测走 OpenTelemetry 标准，客户端侧有**三条互不顶替的通道**，按「谁来消费」选：

* **内置上报**：直达**部署方的 CodeWave 服务端**，企业端「研发效能」页面据此供数，不需要企业自建收集器、也不需要逐台配置（默认开启，退出开关见[第 6 节](#telemetry-privacy)）。
* **自建 OTLP**：导出到企业自己的 OTLP 收集器（Grafana Tempo、Jaeger、Datadog 等兼容后端均可），纳入既有的监控与告警体系。
* **Console 打印**：把遥测以可读形式直接打印到终端（对齐 Claude Code 的 `console` 导出器），零配置本地观察；只在交互模式生效，`--stdio` / `--print` 宿主会自动剥除以免污染输出通道。

三条通道的关键区别是**数据的落点**：内置上报到的是部署方自己的服务端（私有化部署时数据不出企业环境），自建 OTLP 到企业指定的收集器，console 只在成员本机终端呈现、不出机器。三者互不顶替——配了自建 OTLP 不会关掉内置上报，反之亦然。自建通道需要显式配置导出器才会产生流量。

可导出的内容：

| 类别    | 内容                                                                                                                                                                                                                                                                                                                |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Metrics | 按类型拆分的 token 用量（`wave.tokens`）、会话数（`wave.sessions`）、编辑类工具的增删行数（`wave.lines.changed`）、经由工具成功创建的提交数与 PR / MR 数（`wave.commits` / `wave.pull_requests`）、按 `user` / `cli` 拆分的活跃时长（`wave.active_time`）、编辑类工具的权限决策数（`wave.code_edit_tool.decision`） |
| Logs    | `session_start` / `session_end` 等会话生命周期事件，以及工具权限决策、压缩等结构化事件                                                                                                                                                                                                                              |

其中提交数与 PR / MR 数**只认「经由工具、且成功」的创建动作**（`git commit`、`gh pr create` / `glab mr create` 等），不看结果是否被合并，也不依赖任何托管平台的 API 或凭据——私有化 GitLab 与公有 GitHub 场景行为一致。

两个较新的口径值得说清：**活跃时长不是在线时长**——`type=cli` 只计 agent 实际在跑的时间（模型调用、工具执行），弹窗等你批准的那几分钟不算，多会话在同一进程里并发时各记各的；`type=user` 只把相邻两次输入间隔小于 5 秒的那段算作在场，长间隔视为挂机。**权限决策数**只覆盖 `Edit` / `Write` 两个编辑类工具的决定（允许与拒绝都计），`source` 区分这次决定来自配置规则、hook、还是你在弹窗里的选择。

指标与事件都带同一组**标准归属属性**：会话 id、账号 id 与（已认证时的）邮箱、终端类型；部署方还可以用 `OTEL_RESOURCE_ATTRIBUTES` 给自己的车队打团队 / 部门标签（例如 `department.name=infra`），该标签既进遥测资源也会投影到指标数据点上，按团队过滤在各类收集器里都成立。**仓库维度（`vcs.repository.*`）默认关闭**，需要按仓库归因时用 `OTEL_METRICS_INCLUDE_REPOSITORY=1` 打开（远端 URL 里的凭据会被剥离，本地路径不出现在遥测里）。**入口标识（`app.entrypoint`）默认也关闭**：需要按「CLI / 桌面端 / VS Code / JetBrains / 远控通道」拆用量时用 `OTEL_METRICS_INCLUDE_ENTRYPOINT=1` 打开（事件面恒带）。

导出器选择与完整配置项见[功能规格说明：OpenTelemetry 集成](/specs/enterprise/opentelemetry)。

### 5. 用量回调（SDK 集成） {#usage-callback}

如果企业自建了度量平台或看板，也可以不走管控台页面，直接通过 SDK 取用量数据：

* **`onUsagesChange` 回调**：每次 AI 调用与消息压缩完成后触发，推送当前会话累计的用量数组，适合实时同步到自建平台。
* **`get usages()` 方法**：随时按需读取同一份数据，适合定时取数、生成报表或与外部监控系统对接。

回调与类型定义见 [Agent SDK](/sdk)（源码开放、JSDoc 完善，直接读 `packages/agent-sdk/src` 即可），数据范围与边界见[功能规格说明：用量追踪](/specs/enterprise/usage-tracking-callback)。

### 6. 隐私与治理 {#telemetry-privacy}

三点先说清楚：

* **默认不采集提示内容**：遥测**默认不记录**用户提示文本与工具调用内容，只有显式开启 `OTEL_LOG_USER_PROMPTS=1` / `OTEL_LOG_TOOL_CONTENT=1` 时才会包含。默认配置下 `user_prompt` 事件不含提示原文。
* **归属属性是身份、不是内容**：每条遥测记录带账号 id 与邮箱（已认证时）、会话 id、终端类型；未登录时用本机持久匿名 id（不含 PII）。仓库归属默认关闭、本地路径不出现；`session.id` 若不需要可从指标侧关掉（`OTEL_METRICS_INCLUDE_SESSION_ID=0`）。
* **按团队聚合呈现，不做个人排行**：用量数据用于容量与成本规划、定位使用阻力，不做个人产出排名。
* **管理员可统一下发配置**：管理员可通过服务端托管配置统一下发遥测参数（托管配置的 `env` 键按同名覆盖成员本机值），无需逐台机器配置。

**自建通道默认关闭**：不配置导出器时，数据不会流向企业自建的收集器；console 输出只在成员本机终端呈现、不出机器。**内置上报的落点是部署方自己的 CodeWave 服务端**——私有化部署时即企业自己的服务器，不流向第三方；它**默认开启**，管理员可以用托管配置为整个车队下发开关（托管配置优先于成员本机配置）。关掉全部遥测出站（内置上报与企业自建导出器一起）用总闸 `DISABLE_TELEMETRY=1`；只想停自建导出器，把 `OTEL_METRICS_EXPORTER` / `OTEL_LOGS_EXPORTER` 设为 `none`。依据见[功能规格说明：OpenTelemetry 集成](/specs/enterprise/opentelemetry)。

***

## 九、代码安全 {#code-security}

客户问得最多的是「你们在代码安全上能做什么」，以及「跟静态扫描、依赖扫描是什么关系」。这一节讲清三层按时机分工的自动能力、一条开箱即用的分支审查，以及我们不承担什么。

### 1. 按触发时机分工的几层能力 {#code-security-layers}

| 时机           | 做什么                                                                  | 由谁提供                |
| -------------- | ----------------------------------------------------------------------- | ----------------------- |
| 每次写入文件后 | 与危险模式清单比对，命中即提示正在写代码的 AI                           | Security Guidance 插件  |
| 每一轮回答结束 | 独立复核本轮全部改动（含 Bash 与子代理的改动）                          | Security Guidance 插件  |
| 提交或推送之前 | 读周边调用方与校验点，判断发现真伪                                      | Security Guidance 插件  |
| 需要时手动发起 | 多 agent 深度扫描全库 / 分支 diff / PR / 单个提交，并把选定发现变成补丁 | Security Audit 插件     |
| 随时手动执行   | 一次过完当前分支相对远端默认分支的全部改动                              | 内置 `/security-review` |

**为什么分层而不是一个开关**：这三类问题的发现成本完全不同。危险调用模式是确定性的字符串匹配，可以便宜到每次编辑都跑，但它抓不到语义类漏洞；语义类漏洞（越权、注入、弱加密）需要读懂上下文，只能靠模型复核，于是它被放到回合结束与提交前；而这两层都只能看见 AI 自己改过的东西——**存量清查**只能靠手动发起的深度扫描。三者互补，不互相替代。

### 2. 怎么用 {#code-security-setup}

* **两个插件**：在插件市场安装 `security-guidance`（自动三层）与 `security-audit`（按需扫描与补丁）。装完即生效，不需要改代码或加 CI 配置。
* **自动三层各自可关闭**：在仓库的 `.wave/security-guidance.json` 里按层开关（如 `{"layers":{"edits":true,"turn":true,"commit":false}}`，可只关某一层），关掉的那层完全不介入。
* **内置命令**：`/security-review` 不需要安装任何东西，直接在对话里执行，它只对本批改动负责——**只报本批新引入的问题**，不动既有历史遗留（那属于深度扫描的职责）。
* **深度扫描的产物**：报告落在仓库下的 `WAVE-SECURITY-<时间戳>/`（自带忽略规则，不会被普通 `git add` 误收），人读报告、机器可读结果与 SARIF 三份；选定发现生成的补丁写在 `patches/` 里，**从不自动应用**——`git apply` 由人执行。
* **修正在同一会话内完成**：审查结束后直接说「按报告改一下」，AI 在当前会话里落实修复，不用换工具、不用重述上下文。

### 3. 用项目自己的规则扩展 {#code-security-custom-rules}

通用清单只能覆盖共性，团队真正关心的是本项目特有的约束（多租户查询必须带租户过滤、某类字段不得进日志）。两层都可以用仓库里的规则文件扩展：

* **安全指引文件**：`<仓库>/.wave/security-guidance.md`（另有用户级 `~/.wave/security-guidance.md` 与项目本地 `.wave/security-guidance.local.md`）——用仓库里的指引描述本项目的威胁模型与约定，模型驱动的复核会把它作为附加上下文加载，与内置清单一起使用；三个作用域**全部加载并拼接**。
* **危险模式规则**：`<仓库>/.wave/security-guidance-patterns.json`（另有用户级 `~/.wave/security-guidance-patterns.json`）——自定义的模式与内置模式一同参与逐次编辑的比对，规则名与提示文案随告警给出。

两点口径要注意：指引是**给复核者的指引，不是屏蔽机制**——写「忽略某类漏洞」不会让该类发现消失；这几层也都**不阻断**写入、提交或合并。需要硬性阻断时应当使用能阻断编辑的 hook 或 CI 检查，代码安全审核不承担这个职责。

### 4. 能力边界 {#code-security-limits}

* **只提示不阻断**：发现以提示的形式回到正在写代码的 AI，由它在同一会话内修正。
* **可能漏报**：模型驱动的复核是纵深防御中的一层，不是完整方案。
* **口径不同**：逐次编辑的比对是确定性的字符串匹配，能被它抓到的模式有限。
* **扫描结果具有随机性**：同一份代码扫两次，发现可以不同；它以「定期执行」来补足，而不是以确定性来保证。
* **只覆盖 AI 自己的改动**：自动三层只看得见 AI 产生或发起的改动；同事在你终端里做的改动手动扫描才看得到。
* **面向自有或已获授权的代码**，不用于扫描第三方代码。

配置细节、每个场景的验收口径与依赖的底层机制见[功能规格说明：代码安全审核](/specs/commands/code-security)。

***

## 十、自定义工作流：多 Agent 编排 {#custom-workflow}

一件事需要很多份互不相同的看法时——几十个文件逐个分析、一个仓库分区域扫、一页页写文档——一个对话轮次撑不住，要把活拆给多个子代理。插件市场里有两个插件正好把这件事的两种做法各演示了一遍：**deep-wiki** 把编排写进提示词（斜杠命令或技能，主 agent 按步骤叫人），**security-audit** 把编排写成脚本（脚本按固定流程扇出）。

### 1. 方式一：提示词里编排，子代理只负责一个角色（deep-wiki） {#custom-workflow-prompt}

适合一次性、交互式的活：用户发起一次，跑完看结果。

```
deep-wiki/
├── .wave-plugin/plugin.json      # 清单：名字、描述、版本
├── agents/wiki-researcher.md     # 三个子代理，各自一个身份
├── agents/wiki-architect.md
├── agents/wiki-writer.md
└── commands/generate.md          # 编排：谁先谁后、传什么
```

`agents/*.md` 是声明式的：frontmatter 只写 `name` 与 `description`，正文是这个人设的职责与硬要求（引用格式、图表数量、验证清单）。子代理按 `<插件名>:<子代理名>` 点名。

`commands/generate.md` 才是编排，它是一份写给主 agent 的步骤表：

1. 先派 `wiki-researcher` 做仓库研究，等它出结论；
2. 把研究结论交给 `wiki-architect`，出目录与入职指南；
3. 目录里的每一页各派一个 `wiki-writer`，多个写手**放在同一批发**，并行推进；
4. 后处理与打包（转义泛型、修 Mermaid、搭 VitePress）不派代理——这些是确定性动作，主 agent 直接做。

两条要点：**每个子代理只拿一个角色**，输入输出写成契约（第一步就把 `(文件路径:行号)` 引用格式定好，逐层传下去）；**确定性动作留在编排器里**，不必为「转义尖括号」再开一个代理。

编排的载体不一定是斜杠命令：同一套步骤搬进 `skills/<名字>/SKILL.md`，用户就不必记住命令名——技能按 `description` 自动匹配，「给这个仓库生成一份带架构图的 Wiki」这类说法直接进流程，还能在自己的正文里按需引 `jobs/xxx.md` 这样的子步骤文件分档。

### 2. 方式二：脚本里编排，子代理只做判断 {#custom-workflow-script}

适合批量、多阶段、要能复现和续跑的活：几十上百个文件查同一类问题，而且每条结论都要被另一个代理独立复核一遍。

骨架就这么长——先要一份清单，再一项两项地过：

```js
export const meta = {
  name: "audit-routes",
  description: "逐个审计 src/routes/ 下的路由是否缺少鉴权，并对抗复核每条发现",
};

const found = await agent("列出 src/routes/ 下所有 .ts 文件。", {
  schema: {
    type: "object",
    required: ["files"],
    properties: { files: { type: "array", items: { type: "string" } } },
  },
});

const audits = await pipeline(
  found.files,
  (file) => agent(`审计 ${file} 是否缺少鉴权，给出文件与行号。`),
  (finding) =>
    agent(`试着推翻这条发现，拿不到 file:line 证据就判它不成立：\n${finding}`),
);

return audits.filter(Boolean);
```

* `agent()` 派一个子代理；`pipeline()` 把两个步骤接到一批条目上，每个条目走完第一步才进第二步，条目之间互不等待。
* `schema` 只加在要机器接着用的那一步：清单变成结构化数组，后面才能逐项派活；正文结论保持散文，复核者读得动。
* 第二步是**唱反调**：谁写的谁审容易放过自己，所以复核交给另一个代理；`filter(Boolean)` 去掉被跳过的条目（`agent()` 只在你跳过它时返回 `null`）。

脚本只是编排：它派活、算数，不读文件也不跑命令，产物由子代理自己写。扇出多少、怎么分组都在脚本里，所以同一份输入跑两次，代理的数量与分组一致；中断后能从 runId 续跑，跑多少 token 也能在脚本里卡。

security-audit 就是这个骨架的完整版：前门是一份技能（认口语说法、先量后问），扇出写在 `workflows/scan.js`——在「审计 → 复核」前面加了威胁建模，把仓库切成区域并行，high 档把复核升级成三视角投票，外加自己的报告格式。插件里的工作流按 `<插件名>:<脚本名>` 调用，即 `security-audit:scan`，`/workflows` 里能看到它跑到哪个阶段。

### 3. 选哪种，以及怎么开始 {#custom-workflow-start}

* 单次、要看过程、步骤之间需要人判断 → 写在提示词里（斜杠命令或技能），子代理各管一段（deep-wiki）。
* 批量、多阶段、要可复现 / 断点续跑 / 卡预算 → 写成脚本（security-audit）。

自己动手的最小路径：项目里放 `.wave/agents/<名字>.md` 就多一个子代理，放 `.wave/skills/<名字>/SKILL.md` 就多一个技能，放 `.wave/workflows/<名字>.js` 就多一个可按名调用的工作流，三者都不需要先做插件。要让团队一起用，把它们装进一个带 `.wave-plugin/plugin.json` 的目录，注册成自有插件市场即可（见 [桌面端文档 - 插件](/desktop#_5-2-插件)）。写脚本时 AI 会自动加载内置技能 `workflow-authoring`（钩子签名、`meta` 形状、`budget` 与恢复规则都在那里），不用你手写一遍。

## 十一、CI 里跑 Wave：PR 自动审查 {#ci-review}

每个 PR 提上来，让 Wave 先过一遍：读改动、给结论、把结论贴回 PR，不合格时这个 check 变红、拦住合并。整条链路不需要有人在旁边点确认。

三步：

1. **本机先跑通**：`wave -p '/code-review' --output-format json --permission-mode dontAsk --tools 'Read,Glob,Grep,Bash' > wave-result.json`，看 `subtype` 是不是 `success`、`echo $?` 是不是 `0`。
2. **搬进 GitHub Actions**：加一个 `.github/workflows/review.yml`（`uses: netease-lcap/wave-agent/.github/workflows/wave-review.yml@main`），配 secret `WAVE_API_KEY` 与变量 `WAVE_MODEL`——CI 里没有本地配置可继承，模型名必须给。
3. **让它拦住合并**：Settings → Branches → Require status checks to pass，勾上这个 job。

三个环境变量、权限预设、两个平台的完整模板、产物字段与 fork PR 等局限，见 [CLI - CI 集成](/cli#ci)；GitLab 侧只是换个 job 段。
