Download OpenAPI specification:
Skill 是一个文件包——一份 SKILL.md 加上配套脚本与资源,描述「怎么做一件
事」。Agent 按需装载它,而不是把全部说明塞进上下文。
与工具的区别:工具是可调用的函数,Skill 是给 Agent 读的
工作手册 + 随手册附带的可执行文件。召回入口在 context-loader 的
search_capabilities,那边只返回最小元数据;真正的内容读取与下载在这里。
三条读取路径,别用错:
| 接口 | 视角 | 读的是 |
|---|---|---|
/skills/{id}/content、/files/read、/download |
消费态 | 已发布的版本 |
/skills/{id}/management/* |
管理态 | 当前草稿,含未发布改动 |
/skills/{id}/history + history/publish / history/republish |
历史 | 已发布过的版本 |
Studio 的编辑页读管理态,Agent 运行时读消费态。拿错会看到不一致的内容。
上传不是 JSON:注册与更新技能包只接受 multipart/form-data 或
application/x-www-form-urlencoded,发 JSON 直接 400
(unsupported content type)。
时间戳一律是纳秒:所有 *_time 字段由 time.Now().UnixNano() 生成。
认证:Authorization: Bearer <token>(OAuth access token 或 bak_ 前缀的
AppKey)。
内部面(internal-v1)的读授权按档位:原有 /content 与 /files/read 在公开面
一律按账户判定(execute / public_access / view 三者有其一),内部面则看
SKILL_INTERNAL_READ_AUTHZ——shadow(默认)查了但不拦、判定不通过只打日志,
enforce 与公开面一致返回 403,off 完全不查。分档是为了不打断其它存量内部调用方。
新增的 /internal-v1/caller/skills/... 专供已有可信账户头的服务间调用:它不受该兼容
档位影响,而是与公开面一样按真实调用者强制授权。context-loader 有 bearer 时走公开面,
只有可信账户头时走该 caller-scoped 内部面;两者都不会切换成服务身份绕过权限判断。
调用方没带账户身份时任何档位都跳过判定——那是「无从判断」,不是「判定为无权」。
/execute 不受该档位影响,一直按账户强制且只认 execute,public_access 不能执行。
内部面另有两个只读元数据接口:GET /skills/{skill_id} 与 POST /skills/names。
它们不做调用者维度的判定,答的是「技能是否存在、什么状态」,供 bkn-backend 校验
知识网络能力绑定与回填元数据。
检索入口是统一能力检索:POST /internal-v1/capabilities/search,请求体
{ query, refs, top_k, types }。refs 是三段式身份的数组
(capability_type / owner_id / capability_id),Skill 的 owner_id 为空。
只要 Skill 就传 types: ["skill"]。
原先的 POST /internal-v1/skills/search 已随 Skill 专属数据集一起退役。Skill、
函数工具、MCP 工具现在是同一个索引里的文档,在同一个排序空间里竞争——三条
链路各自出结果再首尾相接不是排序:BM25 分数无上界、SQL LIKE 根本没有分数,
拼起来的顺序只表示「哪一堆先放」。
refs 是必填白名单,空数组与字段缺失都返回空结果,不是「不过滤」——
后者会把全平台能力交给一个没有任何绑定的调用方。执行工厂只收一组身份,不认识
kn_id,语义由调用方负责。
白名单是前置过滤,不是先取 top_k 再相交:它进 knn 字段对象内部的 filter,
引擎在白名单范围内取最近邻。反过来做的话,平台能力一多,只挂了几个能力的网络在
全局 top_k 里一个都轮不到,挂得越少越搜不到。
两个通道分两次请求、按 rank 做 RRF 融合,不拼成一个 should:knn 分数在
0~1、BM25 无上界,OpenSearch 直接相加会把向量命中挤出候选池。
每项出参带 score 与 matched_by:knn(仅向量命中)、match(仅全文命中)、
hybrid(两个通道都命中)、like(不带 query 的枚举,没有排序可言)。
排序没有 reranker,与概念召回是同一个已知问题。
不收进上面的 paths:内部面不校验令牌,按 docs/api/README.md 的口径不作为
集成合同发布。
上传一个技能包。**Content-Type 只接受 multipart/form-data 或
application/x-www-form-urlencoded**,发 application/json 会被直接拒绝,
报 unsupported content type。
file_type 决定 file 字段怎么解读:
file_type |
file 是什么 |
|---|---|
zip |
技能包压缩文件(multipart 上传) |
content |
直接给的技能内容 |
响应里的 files 列出解包后识别到的文件。
| file_type required | string (SkillFileType) Enum: "zip" "content" 上传形态: |
| file required | string <binary> 技能包。 |
| category | string Default: "other_category" 分类。 |
| source | string Default: "custom" Enum: "custom" "internal" 来源。 |
| extend_info | string 扩展信息(JSON 字符串)。 |
{- "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "files": [
- "string"
]
}分页列出当前主体获授权访问的技能,支持按名称、状态、分类、创建人过滤。
| page | integer >= 1 Default: 1 页码,从 1 开始。 |
| page_size | integer [ 1 .. 100 ] Default: 10 每页数量,1–100。 |
| sort_by | string Default: "update_time" Enum: "create_time" "update_time" "name" 排序字段。 |
| sort_order | string Default: "desc" Enum: "asc" "desc" 排序方向。 |
| name | string 按名称过滤。 |
| status | string (BizStatus) Enum: "unpublish" "published" "offline" "editing" 按状态过滤。 |
| category | string 按分类过滤。 |
| create_user | string 按创建人过滤。 |
| all | boolean 忽略分页返回全部。 |
{- "total": 0,
- "page": 0,
- "page_size": 0,
- "total_pages": 0,
- "has_next": true,
- "has_prev": true,
- "data": [
- {
- "operations": [
- "view"
], - "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "category": "string",
- "category_name": "string",
- "dependencies": { },
- "extend_info": { },
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0,
- "release_user": "string",
- "release_time": 0
}
]
}与 /tool-box/names 同契约:不存在的 ID 静默略过、不占位。
**也注册在 internal-v1**。公开面按调用者的 view 过滤(无权限的 ID 与不存在的
ID 一样被略过),内部面不过滤——服务间调用要的是「这些 ID 还在不在」,用于知识网络
能力绑定的元数据回填与悬空判定。
| ids | Array of strings 待取名的技能 ID 列表。空列表返回空 |
{- "ids": [
- "string"
]
}{- "entries": [
- {
- "id": "string",
- "name": "string"
}
]
}从技能发布版本表分页列出当前调用者拥有 view 权限的技能,供 Agent 能力发现使用。
该接口读取已发布快照,不读取工作区仓库行的当前状态;因此已发布技能在编辑下一版本时
仍可被发现。它与 /skills/market 的区别是权限口径:本接口只认 view,市场接口只认
public_access。
| page | integer >= 1 Default: 1 页码,从 1 开始。 |
| page_size | integer [ 1 .. 100 ] Default: 10 每页数量,1–100。 |
| sort_by | string Default: "update_time" Enum: "create_time" "update_time" "name" 排序字段。 |
| sort_order | string Default: "desc" Enum: "asc" "desc" 排序方向。 |
| name | string 按发布版本名称过滤。 |
| category | string 按分类过滤。 |
| create_user | string 按创建人过滤。 |
| all | boolean 忽略分页返回全部。 |
{- "total": 0,
- "page": 0,
- "page_size": 0,
- "total_pages": 0,
- "has_next": true,
- "has_prev": true,
- "data": [
- {
- "operations": [
- "view"
], - "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "category": "string",
- "category_name": "string",
- "dependencies": { },
- "extend_info": { },
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0,
- "release_user": "string",
- "release_time": 0
}
]
}已发布技能的列表。比工作区列表少一个 status 过滤——市场里的都是已发布的。
| page | integer >= 1 Default: 1 页码,从 1 开始。 |
| page_size | integer [ 1 .. 100 ] Default: 10 每页数量,1–100。 |
| sort_by | string Default: "update_time" Enum: "create_time" "update_time" "name" 排序字段。 |
| sort_order | string Default: "desc" Enum: "asc" "desc" 排序方向。 |
| name | string 按名称过滤。 |
| category | string 按分类过滤。 |
| create_user | string 按创建人过滤。 |
| all | boolean 忽略分页返回全部。 |
{- "total": 0,
- "page": 0,
- "page_size": 0,
- "total_pages": 0,
- "has_next": true,
- "has_prev": true,
- "data": [
- {
- "operations": [
- "view"
], - "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "category": "string",
- "category_name": "string",
- "dependencies": { },
- "extend_info": { },
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0,
- "release_user": "string",
- "release_time": 0
}
]
}市场视角的技能详情,结构与 GET /skills/{skill_id} 一致。
| skill_id required | string 技能 ID。 |
{- "operations": [
- "view"
], - "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "category": "string",
- "category_name": "string",
- "dependencies": { },
- "extend_info": { },
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0,
- "release_user": "string",
- "release_time": 0
}取技能的元数据。文件清单与内容走 /content,包体走 /download。
**也注册在 internal-v1**,供 bkn-backend 校验知识网络能力绑定。内部面不做
调用者维度的 view 判定,同一技能对任何调用者返回相同结果;未发布的技能通过
status 字段体现,不返回 404。别拿 /skills/market/{skill_id} 代替它——那条路
走 public_access 且未发布即 404,会把「存在但未发布」误报成「不存在」。
404 只表示技能不存在或已删除。
| skill_id required | string 技能 ID。 |
{- "operations": [
- "view"
], - "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "category": "string",
- "category_name": "string",
- "dependencies": { },
- "extend_info": { },
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0,
- "release_user": "string",
- "release_time": 0
}删除技能及其全部版本。已被 Agent 挂载的技能删除后装载会失败;
指向它的知识网络能力绑定会变成悬空引用——search_capabilities 列不出来,
execute_skill 也执行不了。
| skill_id required | string 技能 ID。 |
{- "error_code": "string",
- "description": "string",
- "error_details": null,
- "metadata": { }
}只接受 published 与 offline 两个值——不能通过这个接口把技能改回
unpublish 或 editing,那两个状态由注册与编辑动作产生。
本面用的是 PUT(工具箱的同类接口用 POST),注意区别。
| skill_id required | string 技能 ID。 |
| status required | string Enum: "published" "offline" 目标状态。只接受这两个值。 |
{- "status": "published"
}{- "skill_id": "string",
- "status": "unpublish"
}改名称 / 描述 / 分类,不动技能包本身。三个字段都是必填——整体覆盖。
更新会产生新 version。
| skill_id required | string 技能 ID。 |
| name required | string |
| description required | string |
| category required | string |
| source | string Enum: "custom" "internal" |
object |
{- "name": "string",
- "description": "string",
- "category": "string",
- "source": "custom",
- "extend_info": { }
}{- "skill_id": "string",
- "version": "string",
- "status": "unpublish"
}换掉技能的文件内容。与注册一样只接受 form / multipart,不接受 JSON。
更新产生新 version,原版本进历史。
| skill_id required | string 技能 ID。 |
| file_type required | string (SkillFileType) Enum: "zip" "content" 上传形态: |
| file required | string <binary> 新的技能包内容。 |
{- "skill_id": "string",
- "version": "string",
- "status": "unpublish"
}列出该技能发布过的版本,含每次发布的说明与发布人。
| skill_id required | string 技能 ID。 |
[- {
- "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "category": "string",
- "source": "string",
- "release_desc": "string",
- "release_user": "string",
- "release_time": 0,
- "create_user": "string",
- "create_time": 0,
- "update_user": "string",
- "update_time": 0
}
]取某个历史版本的内容,写回当前草稿——不直接发布。用于「拿旧版本当起点 继续改」。改完再走正常发布流程。
与 history/publish 的区别:那个是直接发布旧版本,跳过草稿。
| skill_id required | string 技能 ID。 |
| version required | string 要回灌的历史版本。 |
{- "version": "string"
}{- "skill_id": "string",
- "version": "string",
- "status": "unpublish"
}把某个历史版本直接发布成当前版本,跳过草稿。回滚用。 草稿里未发布的改动不受影响,仍留在草稿态。
| skill_id required | string 技能 ID。 |
| version required | string 要发布的历史版本。 |
{- "version": "string"
}{- "skill_id": "string",
- "version": "string",
- "status": "unpublish"
}返回已发布版本的文件清单与包地址。Agent 运行时读的是这个。
要看草稿里未发布的改动,用 /management/content。
| skill_id required | string 技能 ID。 |
{- "skill_id": "string",
- "url": "string",
- "status": "unpublish",
- "files": [
- {
- "rel_path": "string",
- "file_type": "string",
- "size": 0,
- "mime_type": "string"
}
]
}按包内相对路径读一个文件。返回的是文件的下载 URL 而不是内容本身——
拿到 url 再去取。路径从 /content 返回的 files[].rel_path 里挑。
| skill_id required | string 技能 ID。 |
| rel_path required | string 包内相对路径,取自 |
{- "rel_path": "SKILL.md"
}{- "skill_id": "string",
- "rel_path": "string",
- "url": "string",
- "mime_type": "string",
- "file_type": "string"
}/content 的管理态版本:读的是当前草稿,含尚未发布的改动。
Studio 的编辑页用它。
响应结构与消费态不同,比 /content 多了 name / description /
version / source / file_type,以及 response_mode=content 时的
content 正文——编辑页要一次拿全,不想再跑一趟详情接口。
| skill_id required | string 技能 ID。 |
| response_mode | string Default: "url" Enum: "url" "content"
|
{- "skill_id": "string",
- "name": "string",
- "description": "string",
- "version": "string",
- "status": "unpublish",
- "source": "string",
- "file_type": "zip",
- "url": "string",
- "content": "string",
- "files": [
- {
- "rel_path": "string",
- "file_type": "string",
- "size": 0,
- "mime_type": "string"
}
]
}/files/read 的管理态版本:读草稿里的文件。默认返回下载地址;
response_mode=content 时直接返回文件文本内容。
| skill_id required | string 技能 ID。 |
| response_mode | string Default: "url" Enum: "url" "content"
|
| rel_path required | string 包内相对路径。 |
{- "rel_path": "string"
}{- "skill_id": "string",
- "rel_path": "string",
- "url": "string",
- "mime_type": "string",
- "file_type": "string",
- "size": 0,
- "content": "string"
}在沙箱里跑技能包里的一条命令。技能包被上传到沙箱工作目录,然后执行
entry_shell 指定的命令。
当前主体必须对具体 skill:{skill_id} 持有 execute。请求体不能替换
OAuth/AppKey 或受信任内部上下文产生的执行主体。
mocked 字段要看:为 true 表示这次并没有真的在沙箱里执行
(沙箱不可用等原因下的降级),返回的 stdout/stderr 不是真实结果。
与函数执行一样,命令失败不体现在 HTTP 状态码上——看 exit_code。
| skill_id required | string 技能 ID。 |
| entry_shell required | string 要执行的命令。 |
| timeout | integer 超时(秒)。 |
{- "entry_shell": "python scripts/run.py --mode full",
- "timeout": 0
}{- "skill_id": "string",
- "session_id": "string",
- "work_dir": "string",
- "file_name": "string",
- "uploaded_path": "string",
- "command": "string",
- "exit_code": 0,
- "stdout": "string",
- "stderr": "string",
- "execution_time": 0,
- "mocked": true
}重建技能的检索索引——search_capabilities 的语义召回依赖它。
execute_type 决定范围:full 全量重建,incremental 只处理游标之后
变更的技能。任务异步执行,用返回的 task_id 查进度。
| execute_type required | string (IndexExecuteType) Enum: "full" "incremental" 索引构建范围:全量 / 增量。 |
{- "execute_type": "full"
}{- "task_id": "string",
- "status": "pending",
- "execute_type": "string"
}分页列出索引构建任务。
**status 过滤不接受 canceled**:任务状态本身有 5 个值
(pending / running / completed / failed / canceled),
但这个查询参数的白名单只有前 4 个,传 canceled 会 400。
| page | integer >= 1 Default: 1 页码,从 1 开始。 |
| page_size | integer [ 1 .. 100 ] Default: 10 每页数量,1–100。 |
| sort_by | string Default: "update_time" Enum: "create_time" "update_time" "name" 排序字段。 |
| sort_order | string Default: "desc" Enum: "asc" "desc" 排序方向。 |
| status | string Enum: "pending" "running" "completed" "failed" 按状态过滤。**不接受 |
| execute_type | string (IndexExecuteType) Enum: "full" "incremental" 按执行类型过滤。 |
| create_user | string 按创建人过滤。 |
| all | boolean 忽略分页返回全部。 |
{- "total": 4,
- "page": 1,
- "page_size": 2,
- "total_pages": 2,
- "has_next": true,
- "has_prev": false,
- "data": [
- {
- "task_id": "83039781-8fea-43ba-bc13-11b4fd6f0d39",
- "status": "completed",
- "execute_type": "full",
- "queue_state": "",
- "total_count": 1,
- "success_count": 1,
- "delete_count": 0,
- "failed_count": 0,
- "retry_count": 0,
- "max_retry": 3,
- "cursor_update_time": 1784869482749304600,
- "cursor_skill_id": "bf93eab9-d2f6-4db3-b564-f47e5e35d4c1",
- "error_msg": "",
- "create_user": "266c6a42-6131-4d62-8f39-853e7093701c",
- "create_time": 1785228741173540600,
- "update_time": 1785228742311942400,
- "last_finished_time": 1785228742311942100
}
]
}取单个任务的进度与计数。
| task_id required | string 索引构建任务 ID。 |
{- "task_id": "string",
- "status": "pending",
- "execute_type": "string",
- "queue_state": "string",
- "total_count": 0,
- "success_count": 0,
- "delete_count": 0,
- "failed_count": 0,
- "retry_count": 0,
- "max_retry": 0,
- "cursor_update_time": 0,
- "cursor_skill_id": "string",
- "error_msg": "string",
- "create_user": "string",
- "create_time": 0,
- "update_time": 0,
- "last_finished_time": 0
}以失败任务为模板新建一个任务重跑。响应里 source_task_id 是原任务、
task_id 是新任务——原任务记录保留不变。
| task_id required | string 索引构建任务 ID。 |
{- "source_task_id": "string",
- "task_id": "string",
- "status": "pending",
- "execute_type": "string"
}