Skills API
列出 Dinox 技能,获取短期下载链接,将当前笔记导出为 Agent Skills tar.gz;包含认证、响应字段、Python 示例、版本与错误处理。
通过两个只读接口,把 Dinox 中保存的技能下载到自己的工具或 Agent:先列出技能,再按笔记 ID 获取下载链接。导出包包含当前技能说明及附属文件,并保留相对目录。
还没有技能笔记?先按 移动端技能库指南 从 GitHub 或 ZIP 导入,等待正文同步、附件上传完成。
基础信息与认证
| 项目 | 值 |
|---|---|
| 服务地址 | https://aisdk.chatgo.pro |
| 列表 | GET /api/openapi/skills |
| 获取下载信息 | GET /api/openapi/skills/{noteId} |
| 请求认证 | Authorization: Bearer <token> |
| OAuth 权限 | dinox.notes.read |
| 成功响应 | HTTP 200,code: "000000" |
| 导出格式 | 单技能 tar.gz |
可以使用现有 App API Token,或具备上述 scope 的 OAuth token。App Token 在 设置 → 同步设置 → API Token 获取。接口只返回当前账号有权访问的技能;即使笔记公开,也不能匿名导出。
Token 是账号凭证。不要写进网页前端、公开仓库、截图或日志。下面的 Python 示例在终端隐藏输入 token;下载对象存储链接时不会携带这个 token。
这两个 Skills 路由使用自己的限流:每个账号在每个服务实例每分钟最多 60 次请求。同一账号在单实例最多同时打包 1 个技能,单实例最多同时打包 2 个技能。多实例不代表可以依赖额度倍增,客户端应顺序下载并处理 429。JSON 响应使用 Cache-Control: no-store。
1. 列出技能
GET /api/openapi/skills?page_size=20
Authorization: Bearer <token>查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
page_size | 整数 | 否 | 默认 20,范围 1–50 |
start_cursor | 字符串 | 否 | 上一页的 next_cursor;首屏省略 |
按笔记 UUID 升序分页。游标绑定当前账号,应原样传回并正确 URL 编码,不要自行解析或跨账号复用。
成功响应
以下 ID 和版本均为示意值,请使用实际返回结果。
{
"code": "000000",
"msg": "success",
"data": {
"results": [
{
"id": "00000000-0000-4000-8000-000000000001",
"name": "pdf",
"description": "Read, create and transform PDF files.",
"version_id": "opaque-version-id",
"exportable": true,
"error": null
}
],
"has_more": false,
"next_cursor": null
}
}| 字段 | 含义 |
|---|---|
results[].id | 技能笔记 ID;下载接口使用它,不使用技能名称 |
name / description | 技能标识和用途描述 |
version_id | 当前可导出内容的版本,不透明字符串;不可导出时为 null |
exportable | 当前元数据与资源状态是否通过导出前置校验 |
error | 正常为 null;异常时为 {code, message} |
has_more / next_cursor | 是否还有下一页,以及下一页游标 |
技能正文未同步、附件未上传或属性无效时,条目仍可能出现在列表中:
{
"id": "00000000-0000-4000-8000-000000000001",
"name": "pdf",
"description": "Read, create and transform PDF files.",
"version_id": null,
"exportable": false,
"error": {
"code": "SKILL_NOT_READY",
"message": "技能附件尚未上传完成"
}
}列表不会下载附件或访问对象存储,因此 exportable: true 不保证随后的真实存储读取一定成功。一个技能不可导出也不会使整页查询失败。
2. 获取技能下载信息
GET /api/openapi/skills/00000000-0000-4000-8000-000000000001
Authorization: Bearer <token>此请求会按当前内容生成归档,返回 JSON,不会直接返回压缩包字节。
{
"code": "000000",
"msg": "success",
"data": {
"id": "00000000-0000-4000-8000-000000000001",
"name": "pdf",
"version_id": "opaque-version-id",
"url": "https://storage.example.com/skill.tar.gz?signature=example",
"expires_at": "2026-09-18T12:10:00.000Z",
"format": "tar.gz",
"sha256": "<64 位十六进制 SHA-256>",
"size_bytes": 17804
}
}| 字段 | 含义 |
|---|---|
id / name | 本次归档所属笔记与技能标识 |
version_id | 本次归档的版本;可能与更早列表中的版本不同 |
url | 私有归档的签名下载地址,约 10 分钟有效 |
expires_at | 下载地址过期时间,UTC ISO 8601 |
format | 当前固定为 tar.gz |
sha256 | 压缩包字节的 SHA-256,64 位十六进制 |
size_bytes | 压缩包大小,单位字节 |
拿到 url 后发起普通 HTTPS GET 即可下载,不要向对象存储转发 Dinox Authorization 请求头。持有签名链接即可下载,请勿公开或写入日志;链接过期时重新调用此接口获取新地址。
停止技能分发不会立即撤销此前签发且尚未过期的链接。
3. 可运行的下载示例
下载 Python 示例脚本,保存后在自己的终端运行。仅使用 Python 3.10+ 标准库,无需安装第三方依赖。
# 列出所有分页中的技能;运行后按提示输入 API Token
python3 download-dinox-skill.py
# 用列表返回的实际 ID 下载;目标文件必须不存在
python3 download-dinox-skill.py \
--note-id 00000000-0000-4000-8000-000000000001 \
--output pdf.tar.gz脚本隐藏输入 token,列出全部分页;下载时校验 size_bytes 和 sha256,校验失败会删除本次不完整文件。已有文件不会被覆盖,签名链接不会被打印,也不会自动解压或执行技能。
核心请求逻辑如下(完整脚本还包含分页、错误处理和流式校验):
import getpass
import json
from urllib.request import Request, urlopen
origin = "https://aisdk.chatgo.pro"
token = getpass.getpass("Dinox API Token: ").strip()
request = Request(
origin + "/api/openapi/skills?page_size=20",
headers={"Authorization": "Bearer " + token},
)
with urlopen(request, timeout=30) as response:
page = json.load(response)
for skill in page["data"]["results"]:
print(skill["id"], skill["name"], skill["exportable"])示例适合个人终端验证。长期同步程序还应实现重试、版本记录和目标 Agent 的安装步骤,见下文。
下载包的目录与兼容范围
pdf/
├── SKILL.md
├── LICENSE.txt
├── forms.md
├── reference.md
└── scripts/
└── convert_pdf_to_images.py这里只有一个以 skill_name 命名的顶层目录,没有额外的 skills/ 包装层,也没有 plugin.json。下载格式采用 Agent Skills 的目录与 SKILL.md 结构。
SKILL.md 由当前笔记重新生成:
---
name: pdf
description: Read, create and transform PDF files.
---
# PDF 工作指南
在这里保存你在 Dinox 中维护的技能指令。name、description取当前属性,不从导入时的历史快照回填。- 指令取当前已同步的 Markdown 正文。
- 导入时的
license、compatibility、allowed-tools、metadata会在合法时保留;其他自定义 frontmatter 字段不保证导出。 - 附属文件保留字节内容和相对路径。普通文件权限固定为
0644,不恢复可执行位或符号链接,时间戳固定以减少无意义差异。 - Markdown 经过保存与生成,不保证原始排版或字节完全相同。
解压前应校验路径,拒绝绝对路径、越界路径和不安全链接。先解压到独立目录、检查内容,再安装到目标 Agent 支持的技能目录;避免覆盖本地修改。脚本按解释器运行,例如 python scripts/example.py,并自行安装它声明的依赖。API 不执行任何包内代码。
哪些笔记会被识别为技能
手机的技能导入流程会自动留下识别信息,普通用户无需额外添加开关。
开发者需要了解下面的优先级:
properties.skill === false:停止后续分发,优先于导入标记。properties.skill === true:明确标记为技能;账号中须存在 key 为skill、类型为checkbox的属性定义。- 否则兼容移动端导入标记:
extra_data.skill.version === 1。
仅有 skill_name,或标题中出现「Skill」,不会把普通笔记自动识别成技能。extra_data.skill.version 是内部数据格式标记,与 API 内容版本不同,不应拿它做更新判断。
导出还要求账号的属性定义类型正确:
| key | 要求 |
|---|---|
skill_name | text;有效技能标识 |
skill_description | text;非空描述 |
skill_files | files;附件包含资源 ID 和相对路径,无附件可为空 |
skill_source_url | 来源追溯字段,不参与技能识别 |
skill_source_revision | 上游提交记录,不作为 API 内容版本 |
文件属性的结构示例:
{
"skill_files": [
{
"resourceId": "00000000-0000-4000-8000-000000000002",
"path": "scripts/convert_pdf_to_images.py"
}
]
}resourceId 指向文件内容,path 表示它在技能根目录中的位置。只有资源 ID、没有路径的附件无法可靠重建技能目录,导出会拒绝猜测路径。资源必须属于当前账号、未删除并已上传。
以上是数据模型说明,本页两个接口均为只读,不提供技能创建、属性修改或 GitHub 同步接口。
版本比较与同步策略
把 version_id 当作不透明字符串,只比较相等与否,不要依赖其长度或内部编码。它覆盖生成的 SKILL.md、排序后的文件路径以及资源上传版本等信息。
| 变化 | 是否影响 API 内容版本 |
|---|---|
| 修改技能正文、标识或描述 | 是 |
| 增删附件、修改相对路径、替换上传资源 | 是 |
| 仅修改来源链接或来源 commit | 否 |
| 仅改变资源 OCR、摘要或缩略图 | 否 |
sha256 则只用于校验本次压缩包。不要把 GitHub commit、version_id 和压缩包 SHA-256 当作同一个值。
建议按以下顺序同步:
- 拉完所有分页,记录本轮完整列表。
exportable: false单独报错,不视为删除。 - 以笔记 ID 作为稳定身份,比较本地记录的
version_id。名称可能更改,也可能重复。 - 对新增或变化的条目顺序请求下载信息,下载并校验归档。
- 安全解压和安装成功后,保存下载信息返回的版本,再更新本地状态。
- 只有完整列举成功后才考虑处理缺失项;权限错误、网络失败不能作为删除依据。需要覆盖本地修改时,应先保留旧内容或进行人工确认。
打包期间如果正文或附件发生变化,服务会返回 409,避免混合不同版本。重新查询后再试。跨页查询不是同一数据库快照,持续同步客户端应在后续轮次再次扫描,让并发新增或修改最终收敛。
同一上传资源应保持内容不变。替换文件请经过 Dinox 的上传流程更新资源记录;直接在对象存储中覆盖同一个 key 而不更新 Dinox 元数据,不属于受支持的版本更新方式。
错误与重试
业务错误一般返回以下形状;鉴权错误由公共认证层返回,客户端首先判断 HTTP 状态码:
{
"code": "SKILL_NOT_READY",
"msg": "技能附件尚未上传完成",
"data": null
}列表条目内部的错误使用 error.message,顶层失败响应使用 msg,不要混用。
| HTTP | 常见 code / 情况 | 建议处理 |
|---|---|---|
| 400 | INVALID_ID、INVALID_PAGE、INVALID_CURSOR | 修正 ID、页大小或重新开始分页 |
| 400 | INVALID_SKILL、INVALID_PROPERTY_TYPE、INVALID_PATH、PATH_CONFLICT | 检查元数据、属性类型和文件路径,修复后重试 |
| 401 | token 无效或未登录 | 重新获取有效凭证 |
| 403 | 缺少 OAuth scope | 授予 dinox.notes.read |
| 404 | SKILL_NOT_FOUND | 笔记不存在、未标记为技能、停止分发或无访问权限 |
| 409 | SKILL_NOT_READY | 等待正文同步及附件上传 |
| 409 | RESOURCE_CHANGED、SKILL_CHANGED | 内容在打包时变化,重新查询后重试 |
| 409 | RESOURCE_UNAVAILABLE、STORAGE_UNAVAILABLE | 检查附件和对应存储配置 |
| 413 | SKILL_TOO_LARGE | 缩减文件、正文或附件数量 |
| 429 | EXPORT_BUSY、RATE_LIMITED | 顺序下载,遵循返回的 Retry-After(如有),退避重试 |
| 502 | EXPORT_FAILED、STORAGE_UNAVAILABLE | 稍后重试,持续失败时检查存储可用性 |
| 500 | SKILLS_UNAVAILABLE | 暂时性服务异常,退避重试 |
对 429/5xx 使用带随机抖动的指数退避,并限制次数;不要对 400/401/403 无限重试。文件下载地址过期时,重新申请地址,不必反复请求旧链接。
导出边界
单个文件最多 5 MiB,每技能最多 50 个附件,正文最多 512 KiB,总未压缩内容最多 64 MiB。非法路径、大小写冲突、文件与目录冲突及嵌套 SKILL.md 会被拒绝。打包处理期限为 120 秒,客户端应留出适当超时余量。
官方存储与账号配置的自定义 S3 都通过资源归属校验读取。自定义存储需要可从服务端访问的公共 HTTPS 443 端点;私网地址或重定向端点不受支持。
接入验收清单
- 在 App 导入一个带脚本的技能,等待同步后能在列表中找到。
- 下载后
size_bytes与 SHA-256 校验通过,顶层目录名与name一致。 scripts/等相对目录还在,SKILL.md包含当前描述和正文。- 修改正文并同步后,
version_id变化,下载得到新内容。 - 正确处理未就绪、过期链接和限流;失败时不覆盖已安装版本。
- 日志和仓库中不保存 token 或签名下载地址。
继续阅读:手机端导入和管理 · 其他 OpenAPI 接口 · Dinox CLI Skills