技能开发概述
开发技能前先确认以下条件:流程已经重复出现、输入输出稳定、失败时能说明原因。任一条件不满足时,先在普通对话中验证流程,再决定是否开发为技能。
技能包结构
my-skill/
├── SKILL.md 必需:技能标识、用途、触发条件和操作方法
├── scripts/ 可选:Python 等确定性脚本
├── references/ 可选:运行时按需读取的资料
└── assets/ 可选:模板与静态文件
包内资源一律使用相对技能根目录的路径;技能不得引用其他技能的文件、代码或配置。
一个可执行的最小 SKILL.md 如下。id 是发布后保持稳定的技能标识,name 和 description 用于列表与触发判断,正文说明具体操作。
---
id: erp-order-query
name: erp-order-query
description: 当用户查询采购订单时,从 ERP API 获取当前记录
nexus:
outbound:
allowedHosts: [erp.example.com]
runtimeConfig:
- key: ERP_REGION
label: ERP 区域
secret: false
uses:
- id: erp-region
mode: sdk_value
---
# ERP 订单查询
运行 `python3 scripts/query.py`,根据脚本返回的数据回答。
出站与运行配置声明
nexus.outbound.allowedHosts 列出由平台网络访问的目标主机,只填写主机名,不包含协议、路径或凭据。nexus.outbound.clientAudiences 列出由桌面客户端访问的精确目标,可限制协议、主机、端口、路径前缀和方法。脚本通过 nexus_sdk.http 发起 HTTP 请求;默认走平台,用户本机、VPN 或企业内网目标显式传 route="client"。未声明的目标、私网绕过和上游重定向会被拒绝。
网络出口与密钥注入是两件事。无鉴权本地接口使用 route="client",不声明或伪造运行配置;需要注入 Token 等配置值时,才使用 platform_proxy_inject 或 client_proxy_inject 对应的 config_use。route 与 config_use 不能同时传,客户端离线也不会自动改走平台。
nexus.runtimeConfig 声明执行时需要的配置项。每项至少包含稳定的 key、界面名称 label、是否敏感的 secret 和一个 uses 用途。需要在脚本中读取原值时使用 sdk_value;只需要向受控 HTTP 请求注入单个值时使用平台代理注入,并声明准确的目标范围。助手默认配置值和成员覆盖策略由助手维护者配置,不写入 SKILL.md。
脚本读取上例配置项时使用:
from nexus_sdk import config, http
region = config.get("ERP_REGION", reason="筛选本次订单查询区域")
response = http.get(
"https://erp.example.com/api/orders",
params={"region": region},
)
response.raise_for_status()
缺少配置值时,读取动作触发配置卡;用户提交后原调用继续。密钥不得写入技能源码、参考资料、测试消息或普通日志。
开发流程
- 准备一份真实输入和认可的结果,先写清触发条件。
- 用技能构建器生成最小文件,只加入完成样例必需的脚本和资料。
- 在测试对话中运行成功样例,再提供一个缺字段或越权输入。
- 保存草稿,修正触发条件和失败说明。
- 安全检查通过并确认影响预览后,再明确发布。
开发完成的标准是:真实输入在测试对话中稳定产出预期结果,失败原因可以说明。
开发限制
| 边界 | 设计含义 |
|---|---|
| 最终技能包不超过 20 MiB | 排除运行产物和依赖目录 |
| 密钥走运行配置 | 不得写进源码、参考资料或示例 |
| 外部网络先声明主机 | 脚本不能临时访问任意地址 |
| 说明必须符合真实行为 | 不得声称拥有平台没有提供的能力 |
安全检查与发布
测试回答“这份输入能否完成”;安全检查和影响预览回答“这份代码能否交给更多助手运行”。编辑文件后,安全检查结果需要重新运行;发布前确认文件变化和受影响助手。
后续操作
准备好输入样例和预期结果后,进入《技能工坊》完成开发与测试;满足测试条件后,再按《发布与安全检查》处理发布。