一、业务背景
- 需要把数据发送给指定平台,对方平台会提供接口文档,根据接口文档做数据对接
- 下游平台有多个,因此把这个过程提炼成skill,提升对接代码生成的准确性
二、Skill基本概念
1. Claude官方定义
- Skill 是一组打包好的指令,教给 AI 一次,永久受用。与其在每次对话中重复解释偏好和流程,不如通过 Skill 只教一次
2. 文件结构
- 这是skill的常规定义,一些简单的skill只需要SKILL.md即可
- 本次我手写的skill就只用到了SKILL.md
skill-name/
├── SKILL.md
├── scripts/
│ └── validate.py
├── references/
│ └── api-guide.md
└── assets/
└── template.md
3.渐进式披露(核心设计原则)
- 第一级(YAML frontmatter):提供足够的信息让AI知道应该何时使用Skill
- 第二级(SKILL.md正文):包含完整的指令和指导
- 第三级(链接文件):Skill目录中捆绑的附加文件
三、Skill实战——基础信息文件
1.概念
- 这个基础信息文件并非必须,是接口对接需要一些基础信息
- 名为generate.md,里面会填充一些定制化数据
- skill中定义通用能力,基础信息文件中定义定制化属性
2.generate.md
## 1.基础信息
- 接口文档:xxx对外开放接口文档V1.1.pdf
- ReceiverId:1xxxx(业务中每个对接平台唯一)
- 类名:xxxService
- 车辆类型:单车(业务相关)
- config命名:xxx_config(配置中心配置项命名)
## 2.鉴权相关(接口文档中鉴权相关定义)
- 签名算法:接口文档中第二部分
- 鉴权接口:
## 3.接口对接(来源Kafka实时数据消息)
- 3.3 推送订单数据 —— handleOrder
## 4.接口对接(来源定时任务)
- 3.4 定时推送定位数据 —— uploadLocation
## 6.参考Service(参考类很重要,如果有相似的对接平台,可以大大提升AI生成代码的准确性)
- xxxService
四、Skill实战——SKILL.md
1.front matter
- 这个一定要定义! 否则AI不知道什么时候触发skill
---
name: interface-documentation
description: 当用户要求在新增、生成、修改平台对接Service类,或根据接口文档和 generate.md 落地平台对接,使用此 skill
---
2.名称
3.适用场景
当用户的需求符合以下任一情况时,应使用本 skill:
- 提到“平台对接”“接口文档对接”“生成对接类”
- 提到“根据接口文档生成接入代码”
- 提到 `generate.md`
- 提到 `xxx(工程项目名)` 仓库中的平台对接实现
如果只是普通 Java 代码修改、测试修复、文档整理,而不是接口文档对接流程,不要强行使用本 skill
4.核心目标
根据模版文件和接口文档,在仓库中生成或修改一套符合现有工程规范的平台对接实现。重点是:
- 找到正确的接入入口和参考实现
- 按仓库现有模式新增 Service、Task、Plugin、Constant 等代码
- 严格按接口文档中的必填字段组织上报报文
- 尽量沿用仓库现有的上传、鉴权、日志、坐标转换方式
5.输入
- 这里我的输入就是基础信息文件,接口文档,以及基础信息文件中定义的一些信息
执行本 skill 前,优先确认以下输入:
1. 模版文件
- 默认使用 `generate.md`
- 如果仓库中存在更具体的路径,以实际文件为准
2. 接口文档
- 根据 `generate.md` 中“1.基础信息”里的接口文档名称获取
- 若是 PDF、Word 或图片形式,先提取出必要字段和接口说明
- 如果pdf skill不可用,用mac自带的PDFKit,必须解析接口文档才能开始生成代码
3. 接入基础信息
- ReceiverId
- Service 类名
- 车辆类型:单车或电单
- Apollo 配置命名
- 是否有签名算法
- 是否有独立鉴权接口
- 需要对接的接口列表
- 参考 Service
6.输出
- 这里我们想要的输出结果就是一个Service类,可以把上游数据转化为发送给下游平台的数据
完成后,通常应产出以下内容中的一部分或全部:
- `ReceiverEnum` 中新增接收方枚举
- 新的 Service 类
- 新的 `constant` 常量类
- 新的 `task` 定时任务类
- 新的 `plugin` 鉴权类(如需要)
- 新的 `enum` / `param` / `model` 类(如接口确实需要)
- 必要的 Spring / Dubbo / 任务注册代码
- 必要的日志、车辆类型校验和坐标转换逻辑
7.行为
- 定义skill具体行为,防止AI读过多上下文,或者参考错误的Service类
### 1. 先读模版,再读接口文档
优先从 `generate.md` 中读取:
- Service 类名
- ReceiverId
- 车辆类型
- Apollo 配置名
- 需要实现的接口清单
- 参考 Gov
如果模版和接口文档冲突,以接口文档的字段和协议为准,但要在结果里明确说明冲突点。
### 2. 先找参考实现,再开始写代码
优先在仓库中搜索同类型、同风格、同地区的已有实现,尤其是:
- 同为单车或同为电单的 Service
- 同类平台协议的 Service
- 模版中指定的参考 Service
默认参考规则:
- 单车优先参考:`xxxService`
- 电单优先参考:`xxxService`
如果模版中已经指定了参考 Service,则优先使用模版指定项。
### 3. 先补基础注册项
通常应先完成这些基础项:
1. 在 `ReceiverEnum` 中新增 receiver
2. 创建 Service 类
3. 创建 Apollo 配置变量
4. 创建常量类
这样可以先搭起完整结构,再补协议细节。
### 4. 再做鉴权
#### 签名算法鉴权
如果模版“2.鉴权相关”说明了签名算法:
- 按接口文档实现签名
- 不要自行发明协议字段
- 复用仓库现有的加签工具优先,确实没有再新增
#### 鉴权接口鉴权
如果模版“2.鉴权相关”说明需要通过接口换取 token:
- 实现 `ServiceTokenPlugin`
- token 获取、刷新、缓存方式尽量复用现有模式
- redis key、过期时间、日志命名沿用仓库风格
如果模版未说明,则跳过,不要擅自补一个 token 机制。
### 5. 实现实时数据对接
根据模版“3.接口对接(来源Kafka实时数据消息)”逐项实现。
要求:
- 实时数据对接方法通常为 `handle...` 开头
- 所有实时上报可以复用一个统一上传方法
- 方法体必须严格按以下顺序组织
固定顺序:
1. 先判断车辆类型是否匹配
- 单车使用 `isHtw`
- 电单使用 `isBh`
2. 进行数据转换和接口调用
- 把内部对象转换成接口文档要求的字段
- 调用政府接口上传
不要打乱这个顺序。
### 6. 实现定时任务对接
根据模版“4.接口对接(来源定时任务)”实现。
推荐方式:
1. 先创建一个 Task 类
2. 从数据表按城市查询数据
3. 批量调用 Gov 中定义的上传方法
8.评测标准
- 一些必须要实现的准则,比如坐标系转换,是否做了鉴权
实现完成后,至少检查以下内容:
1. Receiver 是否已注册
2. Service 是否能被 Spring 扫描到
3. 定时任务是否已注册到对应 XML 或调度配置
4. 单车 / 电单判断是否正确
5. 上传字段是否只包含文档要求的必填项
6. 坐标是否按要求转换
7. 鉴权逻辑是否匹配文档
8. 日志、缓存 key、常量是否符合仓库风格
9.失败处理
如果信息不足,不要硬猜。
优先按以下方式处理:
1. 先完成结构骨架
2. 明确标注缺失信息
3. 仅实现仓库和模版中可以确认的部分
尤其不要在以下情况强行实现完整协议:
- 接口文档读不到
- 签名规则缺失
- 字段定义不完整
- 参考 Service 与目标协议差异很大
10.一句话原则
先按 `generate.md` 定边界,再按接口文档定字段,最后严格沿用 `project` 现有 Service 风格落地实现。
五、总结
- 这个skill可以提升对接效率,让代码生成准确度达到80%以上
- 如果直接丢接口文档给AI,只有50-60%代码可用,剩下需要多次对话或者自己手动修改代码
- 后续也会继续做优化,比如skill拆分,把接口文档解析和Service生成拆开
- 还有一个最佳实践,就是把自己的想法写出来,然后让AI生成一个skill,会更符合AI自身的规范