本文中的"主会话"指
SDK 启动 CLI 时始终追加
不传
传字符串列表时,只有列表中匹配的 skill 会出现在主会话模型的 skill 列表中,并可通过
插件内 skill 使用插件限定名
上面的配置最终允许列出的读取 / 搜索工具和
字符串列表形式的
初始化结果会包含 CLI 在本次会话中发现到的完整 skill 清单,不受字符串列表形式的
如果你用
这类
这里只展示 skill 相关字段;完整类型见 SDK References。Python 中流式
query()(或 Python 的 QoderSDKClient)直接驱动的会话,与通过 Agent 工具委派的子 Agent 相对。两类会话的关系见 子 Agent。
options.skills 控制主会话的 skill 上下文与 Skill 工具调用策略。传字符串列表时,SDK 会同时下发主会话 skill allowlist,并把每一项编译成 Skill(name) 后与工具白名单(allowedTools / allowed_tools)合并;传 'all' 时允许调用所有已发现 skill,不额外过滤主会话上下文。
SDK 不加载内置 skills
SDK 启动 CLI 时始终追加 --disable-builtin-skills,会话不会拿到 CLI 出厂内置的那批 skill(simplify、debug、security-review、quest、batch、agent-creator、hook-config、mcp-config、skill-creator 等)。发现清单(TypeScript 的 initializationResult().skills、Python 的 get_server_info()['skills'])里也不会出现 source: 'built-in' 的条目,模型系统提示同样看不到它们。
这是 SDK 的固定行为,没有开关可以打开;如果你想要 CLI 内置 skill 的能力,要么自己在 plugin / 用户目录 / 项目目录里复刻一份 SKILL.md,要么直接复用 CLI 默认场景。
你的会话仍然能用以下来源贡献的 skills:
- plugin skills:通过
options.plugins加载,使用插件限定名(plugin:skill)。 - 用户 / 项目 skills:通过 setting sources 选项显式打开
user/project/local后被发现。 - Agent 预加载 skills:在
options.agents[name].skills里声明,只对该子 Agent 生效。
使用 CLI 默认策略
不传 skills 时,SDK 不额外注入 Skill allowlist,完全交给 CLI 自身策略。由于内置 skill 已经被禁用,没有 setting sources / plugins 的会话,发现清单会是空列表。
启用所有已发现 skills
skills 取 'all' 会允许 Skill 工具调用所有当前 CLI 发现到的 skill(来源由 setting sources / plugins 决定,不再包含内置)。
只启用指定 skills
Skill 工具调用。列表项支持普通名称和插件限定名;传空列表 [] 会让主会话看不到、也无法通过 Skill 工具调用任何 skill。
这个列表不会改变 CLI 的发现结果;未列出的 skill 仍可能出现在发现清单中。
启用插件内 skill
插件内 skill 使用插件限定名 plugin:skill。关于 plugin 加载方式见 Plugins 文档。
与显式工具白名单合并
Skill(review)。SDK 会合并去重,不会重复写入同名条目。
隐藏已发现的 skills
字符串列表形式的 options.skills 会过滤主会话模型上下文并限制 Skill 工具调用,但不会改变发现清单中的发现结果。想让某个 plugin / 用户 / 项目 skill 连发现清单也不再出现,需要使用 settings.skillOverrides。
'off':完全隐藏,不进发现清单、不进模型系统提示、Skill工具调用也会被拒。- 其它取值:
'on'(默认)、'name-only'(只露名字、不露描述)、'user-invocable-only'(模型看不到,用户仍可通过/name触发)。 - 影响范围:plugin、user、project 等所有 SDK 可见来源都尊重该 override;CLI 内置 skill 已经被
--disable-builtin-skills拦在外面,写不写 override 都不会出现。 - key 命名规则:插件 skill 用插件限定名
plugin:skill;非插件 skill 用裸名。两种形态可以同时写,匹配时先按完整名命中、缺命中则退回裸名。
options.skills可以隐藏主会话的模型上下文,但不会过滤发现清单;需要同时从发现清单中隐藏时,使用skillOverrides: { name: 'off' }。
读取当前会话发现到的 skills
初始化结果会包含 CLI 在本次会话中发现到的完整 skill 清单,不受字符串列表形式的 options.skills 过滤。它适合宿主 UI 展示「已发现的 skills」,不能直接当作主会话当前可调用列表。Python 中 query() 是一次性流,没有便捷查询接口,用 QoderSDKClient 才能在握手后读取。
字符串列表形式的skills是主会话上下文与工具可见性控制,不是安全边界。未列出的 skill 不会出现在模型的 skill 列表中,也不能通过Skill工具调用,但 skill 文件仍在磁盘上,仍可能被普通文件读取工具访问。
自定义 Agent 预加载 Skills
如果你用 options.agents 定义自定义子 Agent,可以在 Agent 定义里声明 skills。这样当主会话调用 Agent 工具时,子 Agent 会带着指定 skill 运行。
skills 只影响该 Agent 的上下文,不等价于给主会话启用同名 skill——主会话的工具白名单不会被这条改动影响。
Options 速查
| 字段(TypeScript / Python) | 说明 |
|---|---|
skills / skills | 列表限制主会话的 skill 上下文与调用;[] 禁用全部;'all' 启用全部已发现 skills |
agents / agents | 自定义 Agent;Agent 定义内可声明独立的 skills 预加载列表 |
allowedTools / allowed_tools | 工具白名单;会与 skills 编译出的 Skill(...) 条目合并去重 |
settingSources / setting_sources | 决定 CLI 是否扫描用户 / 项目目录里的 skills(默认空 = 沙箱) |
plugins / plugins | 加载插件,插件里的 skills 会进入发现集合 |
settings 还有几个 skill 相关字段,SDK 都是透传,实际效果取决于 CLI 版本是否实现:
| 字段 | 作用 |
|---|---|
skillOverrides | 按 skill 名设置 'on' | 'name-only' | 'user-invocable-only' | 'off';plugin、user、project 等来源都尊重该 override |
skillListingMaxDescChars | skill listing 里每条描述的字符上限;SDK 原样透传,默认值由 CLI 版本决定 |
skillListingBudgetFraction | 给 skill listing 预留的上下文窗口比例;SDK 原样透传,默认值由 CLI 版本决定 |
返回值参考
SystemMessage(subtype="init").data["skills"] 是 skill 名称列表,与这里带元数据的发现清单不是同一个结构。
最佳实践
- 按需启用
skills:'all'适合开发和调试;面向最终用户的产品通常应该传明确列表。 - 想要 CLI 内置 skill 的行为,自己复刻:SDK 不会把
simplify/security-review这些塞进会话,需要的话在 plugin 或 setting sources 范围里自己提供 SKILL.md。 - 不要把
skills当沙箱:安全边界应由工具白名单 / 黑名单、权限回调、权限模式和沙箱共同控制。 - 给 UI 用发现清单:
initializationResult().skills/get_server_info()['skills']是 CLI 发现链路的稳定入口,用来展示「已发现的 skill」,不代表主会话当前全部可调用。 - 子 Agent 的
skills单独管理:它与主会话options.skills是两套独立的列表,互不覆盖。
当前限制
--disable-slash-commands是 CLI 一次性禁用所有 slash-command skill 的能力,SDK 当前没有暴露一等 option,不建议依赖非公开的透传路径。settings.skillListingMaxDescChars、settings.skillListingBudgetFraction是 SDK 已透传的 listing 预算控制字段;当前 qoderclicn 还没有实现 listing 预算控制,传入不会报错但也不会改变行为。- Python SDK 暂未提供
client.supported_skills()便捷方法,需要从get_server_info()['skills']读取(已列入 backlog)。