Skip to content

模板与示例

本篇是《Ardot Skill 开发指南》的姊妹篇,专注于 Skill 模板和完整示例。原理介绍、客户端运行机制、容易踩的坑等基础内容,请见主篇《Ardot Skill 开发指南(基础篇)》

本文目录:

一、Skill 模板

二、示例 Skill —— Grid Generator

一、Skill 模板

写 Skill 是高度模板化的任务,适合丢给 AI,但合适精确的 AI 指令可以显著提升 Skill 的质量。以下是我们总结出的、生成适合 Ardot 平台运行的 Skill 相关模板,你可以在完成主体内容的填写后,直接喂给 AI 使用。

1.1 SKILL.md 推荐结构

markdown
---
name: <skill-name>
description: |
  [一句话讲做什么] + [一句话讲何时使用]
  Triggers: "中文短语 1", "中文短语 2", "english phrase 1",
  "english phrase 2".
metadata:
  version: "0.1.0"
  author: <team-or-name>
---

# <Skill Title>

## When to use
- 具体场景 1
- 具体场景 2

## When NOT to use
- 邻近但应该排除的场景 1
- 邻近但应该排除的场景 2

## Workflow

1. [第一步具体动作,含 MCP 工具名]
2. [第二步...]
3. [...]

## Reference materials
(如果有 references/ 才写)

- `references/spec.md` — 执行 Step N 前**需要先读**,里面有 X、Y、Z
- `references/edge-cases.md` — 只有遇到 [具体情况] 时才需要读

## Out of scope
- 本 Skill 不做的事 1
- 本 Skill 不做的事 2

## Notes
(可选)
- 性能注意点
- 兼容性说明

1.2 Skill 生成步骤与提示词

第一步:把需求压成一段提示词

不要直接说"帮我写个 ××× 的 skill"。一句话需求难以完成一个质量 OK 的 Skill,可以整理好以下信息,一次性给 AI:

markdown
我要写一个 Skill,承担以下职责:

- 做什么:[一句话]
- 触发场景:[列 3-5 个具体场景]
- 不做什么:[列 2-3 个邻近但应该排除的场景]
- 工作流:[列出 3-7 步具体动作,包含具体命令]
- 依赖:[需要哪些工具/版本]
- 危险操作及限制:[如果涉及修改/提交等]

请按 agentskills.io 官方规范生成 SKILL.md。规范层硬要求:

- name 小写字母/数字/连字符,等于目录名
- description [1-1024 字符,写明做什么 + 何时用]
- metadata.version 用 semver

实战层建议:
- description 视情况补触发关键词、双语短语
- 工作流写具体命令而非模糊描述
- SKILL.md 主体超 5000 tokens 就考虑拆 references/
- 多 Skill 边界混淆 / 工作流可能失败 / 涉及破坏性操作时,
  对应补 Out of scope / Error recovery / Safety 章节

按这个模板给指令,AI 一次过的概率会高不少。

第二步:让 AI 自我审查

写完后再喂一遍清单让它自己挑刺:

markdown
请用以下清单审查上面这个 Skill:

[ ] description 是否同时包含[做什么] + [何时使用] + [按需补充 3 到 5 个触发短语,覆盖团队常用语言和口语化表达]
[ ] description 是否覆盖团队常用语言和口语化触发短语(实战建议)
[ ] name 是否符合命名规范(小写/连字符/无连续--/等于父目录名)
[ ] metadata.version 是否有
[ ] SKILL.md 体量是否过大(建议正文 ≤ 5000 tokens;超出考虑拆 references)
[ ] 工作流是否写了具体命令(而非"运行构建"这种模糊指令)
[ ] 是否需要补 Out of scope(多 Skill 边界容易混淆时)
[ ] 是否需要补 Error recovery(工作流可能失败时)
[ ] 是否需要补 Safety(涉及破坏性操作时)
列出不达标项并修正。

让 AI 对清单做模式匹配比让它自由"反思一下"准确。

第三步:跑 validator

使用斜杠命令:

/my-skill

报错就把报错复制给 AI 让它修。

第四步:实战测试

Skill 装进去后,用各种说法故意触发它:

  • 标准说法:"review this PR"
  • 中文:"审一下这段代码"
  • 口语:"这代码有啥问题没"
  • 边界:"看一下这个 diff"(diff 应该归 commit skill 还是 cr skill?)

某个该触发的说法没触发,回去补 description 关键词。不该触发的反而触发了,先看 description 写得是不是太宽泛、关键词是不是过度发散,必要时再补 Out of scope。

二、示例 Skill —— Grid Generator

我们提供了参考线绘制(Grid Generator) skill 作为示例 skill 供您参考。

本 Skill 的作用:在选中的 Frame 同级生成一个同位置、同尺寸的像素网格图层(grid),用 0.1px 的极细 line 节点拼出来,作为设计时的对齐辅助。

Grid Generator 涉及大量节点创建、分批提交、弱事务容错、AI 行为约束等等内容,恰好覆盖了 Ardot Skill 开发中最常见的"写操作"陷阱。

您可以 下载 Grid Generator,然后在 Ardot 上上传运行。

使用方法:

  1. 打开 Ardot — AI 小助手 — 技能 — 上传。
  2. 上传后选中 Skill 运行,或不选中 Skill,直接选中想要生成网格的 Frame,然后输入"帮我生成网格"即可。

Grid Generator 使用示意

2.1 目录结构

text
grid-generator/
├── SKILL.md
└── references/
    └── advanced-grids.md

2.2 SKILL.md

markdown
---
name: grid-generator
description: |
  为选中的 Frame 生成 0.1px 极细像素网格,用于对齐辅助。
  当用户想画网格、加参考线、检查像素对齐时使用。
  Triggers: "加网格", "生成网格", "对齐网格", "画个 grid",
  "show grid", "add grid", "像素对齐", "pixel grid".
metadata:
  version: "0.3.1"
  author: ardot-team
---

# Grid Generator

在选中的 Frame **同级**生成一个同位置、同尺寸的像素网格图层。网格
使用 0.1px 的极细 line 节点,不影响设计稿视觉密度。

## ⚠️ 硬约束(违反会导致功能完全错误,必须遵守)

本 skill 的核心价值在于"极细的 line 网格"。下面这些约束是**强制
的**,无论你之前训练时见过什么"画网格"的常规写法,本 skill 都必须
按以下规则执行:

| 维度 | ✅ 必须 | ❌ 禁止 |
|---|---|---|
| 节点类型 | `type: "line"` | `type: "rectangle"``type: "frame"` 当线用 |
| 线宽 | `strokeWeight: 0.1`(小数 0.1,不是 1) | `strokeWeight: 1`、或用矩形的 `width/height: 1` 模拟 |
| 颜色机制 | `strokes` + `strokeWeight` | `fills`(line 不接受 fills,会变成不可见) |
| 方向 | `rotation: 0` 横线 / `rotation: 90` 竖线 | 用 width vs height 比例模拟方向 |

**为什么不能用 rectangle**:rectangle 在很小的线宽(如 0.1px)下,
Ardot 渲染时会消除子像素,导致显示不出来;line 节点的 strokeWeight
是矢量描边,0.1 能正确显示为发丝级参考线。

**为什么不能用 fills**:line 节点的视觉表现完全由 strokes 控制,
fills 在 line 上无效。如果你在 line 上写 fills,结果是一根透明
不可见的线。

如果你"觉得用 rectangle 更直接 / 更熟悉",请停止这个念头,按本
skill 的规则执行。完整写法见 Step 5。

## When to use

- 设计稿需要对齐到 4 / 8 / 16 像素的栅格
- 想快速校验布局间距是否符合规范
- 想给自己加个临时的视觉参考

## When NOT to use

- 想要列网格(columns)—— 本 skill 只做均匀像素网格
- 想要修改目标 Frame 本身 —— 本 skill 不会动目标 Frame
- 想要可导出的网格 —— 生成的 grid 是普通图层,导出时会显示

## Workflow

### Step 1 — 拿到目标 Frame

调用 `fetch_editor_state`(设置 `includeSchema: false`
`includeGeneralEditInstructions: false`)。

判断当前选区:

- **有选区且全部都是 Frame****所有**选中的 Frame 都作为目标,逐个生成 grid(不要只处理第一个!)
- **有选区但混合了非 Frame 节点**:只处理其中是 Frame 的那些,并在最终报告里说明"忽略了 N 个非 Frame 节点"
- **有选区但全部不是 Frame**(比如选中了矩形、文字):告诉用户
  "请选中至少一个 Frame,本 skill 只能为 Frame 生成网格" 然后停下
- **没有选区**:告诉用户 "请先选中一个或多个 Frame" 然后停下

⚠️ **重要**:如果选了 N 个 Frame,本 skill 要为每一个 Frame 都
生成一个独立的 grid 图层,**一个都不能漏**。Step 2 ~ Step 7 整个
流程要对每个 Frame 重复一遍(或者一次性收集完所有 gridSize 再批量
执行)。

对每个目标 Frame 记录:

- `id`(用于后续 batch_edit 的 parent 引用 / 同级插入定位)
- `name`(用于报告)
- `x` / `y` / `width` / `height`(用于网格尺寸计算)
- `parent.id`(用于把 grid 插到同一个父节点下)

### Step 2 — 让用户选网格密度

对每个目标 Frame,调用 `AskUserQuestion`,问网格大小:

- 选项:`4px``8px`(默认推荐)、`16px``24px``自定义`
- 单选
- 如果用户选了"自定义":再问一次让用户输入数字。**必须在提问时
  显式告知用户合法范围**:
  - 计算 `maxGridSize = floor(min(frameWidth, frameHeight) / 2)`
  - 提示文案示例:
    "请输入网格大小(合法范围 1 ~ {maxGridSize}px,超出范围则
    无法画出任何网格线)。"
- 如果用户输入超出范围(小于 1 或大于 maxGridSize):
  - **不要默默拒绝再问**,要明确告知 "{用户输入} 超出合法范围
    1 ~ {maxGridSize}px,请重新输入"
  - 然后再次询问

把用户为每个 Frame 选择的网格大小记为 `gridSize`

### Step 3 — 算出网格线的坐标

**原则**:第一根线从 `gridSize` 开始(不是从 0 开始),之后每隔
`gridSize` 一根,只要坐标还在 Frame 范围内就继续画。

不要"留白"、不要"考虑边距"、不要"觉得太靠边就跳过"。

**横线(y 坐标列表)**

```
y = gridSize, 2*gridSize, 3*gridSize, ...
所有满足 0 < y <= frameHeight 的位置都要画
```

**竖线(x 坐标列表)**

```
x = gridSize, 2*gridSize, 3*gridSize, ...
所有满足 0 < x <= frameWidth 的位置都要画
```

#### 自验证公式(必做)

```
预期横线数 = floor(frameHeight / gridSize)
预期竖线数 = floor(frameWidth / gridSize)
```

如果你算出的 y/x 列表长度跟公式不一致,说明算错了。

#### 软上限检查

```
totalLines = horizontalLineCount + verticalLineCount
```

如果 `totalLines > 200`,用 `AskUserQuestion` 提示用户继续 / 取消。

### Step 4 — 创建 grid Frame 容器

`batch_edit` 创建一个新 Frame,参数:

- `parent`:目标 Frame 的 `parent.id`(同级插入)
- `name``grid`
- `x` / `y`:跟目标 Frame 完全一致
- `width` / `height`:跟目标 Frame 完全一致
- `fills``[]`(不填充)
- `clipsContent`:true(网格超出边界时被裁掉)

### Step 5 — 在 grid Frame 里用 line 节点画网格线

**⚠️ 再次提醒**:网格线**只能**`type: "line"` + `strokeWeight: 0.1`

**注意:本步可能涉及大量节点,必须分批提交。每次 batch_edit 提交
≤ 25 个 op(Ardot 上限),保守起见建议 ≤ 20 个,提交后用
`batch_read` 验证。**

每根线的样式(线宽 0.1px、半透明红):

```javascript
strokes: [{
  type: "SOLID",
  color: { r: 1, g: 0, b: 0 },
  opacity: 0.5,
  visible: true,
  blendMode: "NORMAL"
}],
strokeWeight: 0.1
```

### Step 6 — 锁定 grid Frame

所有线提交完毕,验证通过后,用 `batch_edit` 锁定 grid Frame:

```
U(gridFrameId, { locked: true })
```

锁定的目的:避免用户操作目标 Frame 时误选到网格。

### Step 7 — 报告

最终告诉用户:

```
已为 N 个 Frame 生成 grid 图层:
1. [目标 Frame 1 名]
   - 网格大小:[gridSize]px
   - 共 [horizontalLineCount] 根横线 + [verticalLineCount] 根竖线
   - 已锁定 ✓
...

线宽统一为 0.1px(半透明红)。
删除时请在图层面板取消锁定后 Delete 对应的 grid 层。
```

## Out of scope

- 不做列网格(columns) / 行网格(rows)—— 想要的话见
  `references/advanced-grids.md`
- 不做"删除网格"功能 —— grid 是普通同级图层,用 Ardot 原生
  Delete 即可
- 不修改目标 Frame 本身
- 不做跨多个 Frame 批量加网格
- 不做颜色 / 线宽定制(如果需要,生成后手动改 grid 层属性)

## Reference materials

- `references/advanced-grids.md` — 介绍列网格、行网格的实现思路,
  本 skill 不实现,但用户想自己扩展时可以参考。

2.3 references/advanced-grids.md

markdown
# 进阶:列网格 / 行网格的实现思路

本 skill v0.1 只做单位网格(uniform grid)。如果你想扩展成列
网格或行网格,可以参考下面的思路自己改造。

## 列网格(Columns)

常用于 Web / 移动端布局,按列数 + 间距 + 边距划分。

### 参数

- `columnCount`:列数(4 / 8 / 12 / 16 常见)
- `margin`:左右边距
- `gutter`:列之间的间距

### 列宽计算

`columnWidth = (frameWidth - margin * 2 - gutter * (columnCount - 1)) / columnCount`

如果算出来 columnWidth < 0,说明 Frame 太窄,参数不合理。

### 矩形位置

`第 i 列的 x 坐标 = margin + (columnWidth + gutter) * i`

### 颜色

跟单位网格不同,列网格通常用半透明蓝或半透明粉来跟单位网格区分。
建议 `rgba(0, 100, 255, 0.1)`

## 行网格(Rows)

跟列网格对称,用于垂直节奏对齐。把上面公式里的 width 换成 height、
margin 换成上下边距即可。

## 同时生成多种网格

如果用户想要列网格 + 行网格叠加,可以在 grid Frame 里建两个子
Frame,分别叫 `columns``rows`,分别画。这样用户可以单独显示
/ 隐藏某一层。

## 关于性能

矩形数量没有上限规定,但 Ardot 画布在节点数 > 500 时可能开始卡。
设计时要做好节点数估算和软上限。