用途
create-skill 用于编写 OpenBKN Skill 包,让执行工厂可以注册、智能体可以按步骤执行。编写 Skill 不涉及平台代码:智能体已经具备 get_skill_content、search_capabilities、get_kn_detail、query_metric、execute_tool、execute_action 等能力,Skill 要做的是说明该用哪些能力以及怎么用。
它与相邻技能的分工是:create-skill 写文件;openbkn 技能负责执行 openbkn skill register、openbkn skill set-status、openbkn sandbox run、openbkn function create;create-bkn 负责对知识网络本身建模——Skill 假定网络及其指标、动作已经存在。
包结构
{skill_dir}/
├── SKILL.md # 必需;frontmatter 的 name + description(+ metadata.uses)
└── references/ # 可选:报告格式、业务规则、IO 契约
└── report-spec.md
执行工厂只解析 frontmatter 中的 name、description 与 metadata(metadata 为自由格式,原样存储)。正文是供智能体阅读的文字,其中的“能力依赖”表是约定而非 schema。
编写工作流
- 确定范围——一个知识网络(bkn_scope)。列出会触发该技能的用户问题,以及智能体必须向用户获取的参数。
- 按名称选择能力——通过 get_kn_detail / get_object_types 取得指标与动作类型,通过 search_capabilities 取得函数与 MCP 工具。必须使用注册时的原始名称,因为智能体是按名称检索的。
- 声明两次——在 frontmatter 的 metadata.uses[] 中做机器可读声明(type、name、purpose、confirm),并在正文表格中面向智能体声明(名称 | 类型 | 用途 | 如何调用 | 如何读取结果 | 确认)。
- 编写步骤——编号,每步一次平台调用,并在步骤之间写明参数映射。说明哪一步在结果良好时提前结束、哪一步必须先询问用户。
- 标记确认——任何有副作用的动作都要设 confirm: true,并写上“未经明确同意不得执行”。平台不做这个门禁,由技能负责。
- 添加 references/report-spec.md——输出形态,其中包含一行“依据”,列明所用的能力,便于用户核对链路。
- 注册、发布、挂载——见“交付”。技能只有在被挂载的网络上才对智能体可见。
- 端到端验证——一次受管交互应能在同一个 interaction_id 下看到 get_skill_content → query_metric → execute_tool → execute_action,且 bkn_finish_interaction 返回 evidence_status: complete。
模板:assets/templates/SKILL.md.template、assets/templates/report-spec.md.template。 完整示例(已在 0.1.5 部署上验证):references/examples/demand-deliverability-assessment/。
编写规则
- 名称就是检索键,拼错名称智能体就找不到该能力。
- 只使用已挂载的能力。让智能体报告“未挂载”,而不是退回到其他网络或平台目录中的同名能力。
- 文本字段用 match 定位。带全文索引的字段(condition_operations 包含 match)可能在资源层拒绝 ==,需要在定位行的步骤中说明这一点。
- 查找技能:用 search_capabilities 加查询时函数排序靠前;若要找技能本身,传 types: ["skill"]。
- 不放机密、不放 URL。技能只命名能力,凭据与受管轮次由平台承载。
函数(bkn-osdk)
函数是在平台沙箱中运行的 Python,注册为工具。沙箱自带 bkn_osdk,并注入 BKN_BASE_URL、BKN_TOKEN、BKN_CONVERSATION_ID、BKN_INTERACTION_ID、BKN_PARENT_OPERATION_ID,代码无需自行配置:
from bkn_osdk import kn
def handler(event):
rows = kn.query_object_instance(event["kn_id"], "order", limit=500,
filters=[{"field": "status", "op": "==", "value": "paid"}],
properties=["order_no", "amount"], response_format="json")
return {"count": len(rows.get("datas") or [])}
硬性规则(均已在真实沙箱中验证):
- 入口必须是 handler(event);event 是该工具的输入对象。
- 不要写 from future import ...,沙箱会前置包装代码,该导入会变成 SyntaxError。
- 工具参数类型只能是 string / number / boolean / array / object;integer 会被拒绝并返回 400。
- 函数内部通过 bkn-osdk 发起的读取,会作为 execute_tool 操作的子节点落在调用方的交互上,无需额外接线。
骨架:assets/templates/function.py.template。完整示例(BOM 一级齐套检查):references/examples/functions/l1_kitting_check.py。kn.query_metric / kn.run_sql 及生成的本体层细节见 python/ 下的 bkn-osdk README。
调用另一个函数
函数可以通过平台调用同一网络上挂载的另一个函数:
from bkn_osdk import kn
def handler(event):
answer = kn.execute_tool(event["kn_id"], event["box_id"], event["tool_id"],
{"kn_id": event["kn_id"], "product": event["product"], "qty": 50})
body = answer.get("body", answer) # 被调方的原始响应
if body.get("exit_code") not in (0, None): # HTTP 200 不代表被调方成功
return {"ok": False, "reason": body.get("stderr", "")[-300:]}
return {"ok": True, **(body.get("result") or {})}
kn.execute_tool 会携带沙箱的受管轮次,因此被调方的沙箱拿到相同的调用方凭据,链路中被调方显示为该函数的 execute_tool 操作下,其自身的读取在更下一层。
这需要沙箱 bkn-osdk 具备 kn.execute_tool(bkn-sdk #100 或更高)。在更旧的 SDK 上,唯一路径是 bkn_osdk.call("/api/agent-retrieval/v1/kn/execute_tool", ...),且请求体必须携带由 BKN_CONVERSATION_ID、BKN_INTERACTION_ID、BKN_PARENT_OPERATION_ID 构造的 bkn_context;否则被调方的沙箱完全拿不到凭据。
被调方自身的挂载与权限仍然生效。没有深度或循环保护——不要编写互相调用的函数。
示例:references/examples/functions/call_l1_check.py。
代码 → 工具(openbkn CLI 0.1.5+)
openbkn sandbox run ./fn.py --event '{"kn_id":"<kn>","product":"P1","qty":50}' --pass-token
openbkn toolbox create --name my_functions --type function # name: 字母、数字、_、中文
openbkn function create ./fn.py --toolbox <box-id> --name fn \
--description "..." \
--inputs '[{"name":"kn_id","type":"string","required":true}]' \
--outputs '[{"name":"kitting_ok","type":"boolean"}]'
openbkn function enable <tool-id> --toolbox <box-id> # 工具初始为禁用
openbkn toolbox publish <box-id>
把工具挂载到网络上(重复绑定同一项是无操作):
openbkn bkn capability attach <kn> --box <box-id> --tool <tool-id>
交付
openbkn skill register ./{skill_dir} # -> skill_id, status unpublish
openbkn skill set-status <skill_id> published
openbkn bkn capability attach <kn> --skill <skill_id>
验证清单
- frontmatter 含 name、description、metadata.bkn_scope、metadata.uses[]
- uses[] 中的每个名称都在正文表格中以完全相同的拼写出现
- 每个能力都挂在 bkn_scope 上(用 search_capabilities / get_kn_detail 检查)
- 每个有副作用的动作都有 confirm: true,并有“未经明确同意不得执行”的步骤
- 步骤显式地把一次调用的输出映射到下一次调用的输入
- references/report-spec.md 以所用能力结尾,便于核对链路
- 函数代码:handler(event),无 future 导入,参数类型属于允许集合