跳到主要内容

配置与密钥

什么时候读:技能需要 API key、token、endpoint 等按角色隔离的配置时。

注入结构​

平台按角色隔离存储技能参数,执行前注入四处,同一份值:

ctx["skill_configs"] = {"<skill_name>": {"api_token": "..."}, "api_token": "..."}
ctx["skill_args"] = {"api_token": "..."}
ctx["api_token"] = "..." # 顶层扁平副本

CLI 风格的 --api-token 归一为 api_token,并补大写别名 ctx["API_TOKEN"]。 另外 compat.effective_input 会把配置 setdefault 进 input_data(只回填 handler 代码里真会读的键), 所以从 input_data 读也拿得到——但按 ctx 读更明确。按下列顺序取,取到即止:

import os

def _cfg(ctx, key, skill_name):
for src in (ctx.get("skill_configs", {}).get(skill_name) or {},
ctx.get("skill_configs") or {},
ctx.get("skill_args") or {},
ctx):
v = src.get(key)
if v is not None and str(v).strip():
return str(v)
return os.getenv(key, "")

call_skill 调子技能时,子技能的 skill_configs 由平台按 role_id + 子技能名 重新查库注入,不继承调用方的。 页面面板 / 试运行线同样由 skill_param_store.inject(role_id, skill_name, …) 注入;异步后台在派发时预取好带走。

参数的三个存放范围(控制台 GET /skills/params/{skill}、POST /skills/params/set 的 scope): role(某角色专属,需 role_id)/ personal(当前用户)/ shared(团队共享)。三者如何合并由 skill_param_store 决定(不在本次核对范围);技能侧照上面的顺序取值即可,不关心来自哪个范围。

凭证规则​

  1. 名字含 key / token / secret / password / credential / auth 的参数自动加密存储,且从暴露给模型的 schema 中摘除——模型不填,平台执行时注入。技能不得要求模型传密钥。
  2. 匹配是子串不是后缀:技能内的常量名(PARAM_KEYS、AUTH_HEADERS、author)也会被命中并摘除/加密。非凭证名避开这些子串;自测脚本同样按子串扫。
  3. 凭证的合法来源只有两条:① 管理员在控制台「技能参数」表单填写(/skills/params/set,只写非空值,留空 = 保持原值); ② 用户在对话里直接给出,模型用 save_skill_param 保存(平台校验该值必须出现在用户本轮原文中)或随 install_skill 的 env 一起传。 技能不得自行生成或从历史拼凑凭证。
  4. 子进程/容器型技能的凭证走环境变量,文档用 $VAR 引用,不展开、不打印。没有「打印出来确认一下」这种步骤。
  5. 技能目录里不放任何含密钥的文件:/api/v1/skills/<name>/ui/asset 免鉴权,能按技能名匿名下载技能目录里 .json .js .html .css 及图片字体等后缀的文件(有没有面板都一样)。密钥只走参数表单 / save_skill_param / 环境变量。

frontmatter 声明(两处,各管一段)​

① 顶层 env——控制台参数表单、安装表单、市场「需要密钥」标记读这里(skills._env_schema_from_dir / _build_market_row)。认的键:environment_variables / env / requires-env / required-env / secrets / inputs (SKILL.md frontmatter、skill.toml、skill_meta.json 三处都扫,skill.toml 的 [requires].env 也算)。

env:
- name: XXX_API_KEY # 或 key
label: XXX 的 API Key # 或 title / display_name
description: 在 xxx.com 控制台「API 密钥」页申请
required: true # 缺省 true(也认 is_required / isRequired)
secret: true # 缺省 false(也认 is_secret / isSecret);true 时表单打码
# 可选:default / example / enum(options) / format / model_type / model_hints
  • 写成纯名字列表(env: [XXX_API_KEY])= 全部必填 + 密文。
  • 零配置技能写 env: []。三处都没声明时,平台会扫 SKILL.md 与 handler.py 正文「嗅探」疑似密钥名 (os.getenv("X")、param_name="x"、全大写 XXX_YYY 常量,名字含 key/secret/token/api/password/access/appid…), 在表单里冒出「(自动检测,请确认是否需要)」的假配置项。
  • 任一必填项 → 市场标 needs_secret,install_skill 缺值时返回 missing_env 要求先补。
  • 名字以 xkeyai_ 开头的技能,平台会用自身的 xkeyai 密钥 / 模型自动回填对应项。

② metadata.openclaw——执行器运行前校验、文档型子代理鉴权提示读这里:

metadata:
openclaw:
primaryEnv: XXX_API_KEY
requires:
env: [XXX_API_KEY] # 或 [{name: X, required: true}]
bins: [curl]

requires 在执行前校验,缺 env 返回 needs_config 提示,不进入执行。 声明 exec_mode: shell 或 runtime 的技能不校验 bins。

需要配置的技能两处都写:只写 ② 的话,控制台表单靠嗅探才看得到这个配置项(且标为非必填)。

缺配置时的返回​

if not token:
return {"success": False, "error_type": "config", "non_retriable": True,
"error": "未配置 XXX_API_KEY",
"user_message": "请在对话中提供 XXX 的 API Key(直接粘贴即可,平台会加密保存)。"}

config 类错误标 non_retriable,因为同参数重试必然失败。