本页目录21
- 原文 URL 已重定向到「Extend agents with skills」页面,该页同时覆盖 Skills 与 Agent SDK 会话中的命令(原 slash-commands 内容)
- skills 是文件系统产物(.claude/skills/<name>/SKILL.md),通过 settingSources/setting_sources 中的 user、project 加载,SDK 不提供编程注册 API
- query() 的 skills 选项接受 "all"、技能名数组或 [],用于控制 Claude 可调用哪些技能;按名称派发(/<name>)不受此列表限制
- system/init 消息的 skills 字段列出已加载的可用户调用技能,slash_commands 字段列出会话中可用的全部命令(内置命令、bundled skills、自定义技能、命令文件)
- /compact 需要已有对话历史才能生效,压缩结果通过 subtype 为 compact_boundary 的 system 消息返回;/clear 重置上下文但不删除磁盘上的历史,可通过 resume 选项恢复
- skills 列表中的名称必须精确匹配,不支持通配符,非法名称会在会话启动前被 query() 拒绝(TypeScript 抛 Error,Python 抛 ValueError)
本文是对官方 Agent SDK 某页的中文整理,完整与最新内容以原文为准:https://code.claude.com/docs/en/agent-sdk/slash-commands
说明:该原文链接目前会重定向/合并到官方文档「Extend agents with skills」页面,该页明确注明「本页同时覆盖 Agent SDK 会话中的命令(Commands in Agent SDK sessions)」,即原 slash-commands 页的内容。以下整理基于该合并后的页面全文。
Skills 与 Agent SDK 的关系
Agent Skills 用于扩展 Claude 的专项能力,Claude 会在相关场景下自动调用。Skills 打包为 SKILL.md 文件,包含说明、描述以及可选的配套资源。
在 Claude Agent SDK 中,skills 具有以下特点:
- 以文件系统产物定义:每个 skill 是独立目录下的一个
SKILL.md文件,例如.claude/skills/<name>/SKILL.md - 从文件系统加载:SDK 根据
settingSources(TypeScript)或setting_sources(Python)所指定的位置加载 skills - 自动发现:文件系统设置加载后,SDK 会在启动时从用户和项目目录发现 skill 元数据,并在 Claude 调用该 skill 时加载完整内容
- 由模型调用:Claude 根据上下文自主决定何时使用
- 由用户调用:可以在 prompt 中发送
/<name>直接派发某个 skill(见下文「Agent SDK 会话中的命令」) - 通过
skills选项限定范围:默认情况下,已发现的 skills 都会启用;可以传入技能名称列表、"all"或[]来控制 Claude 可调用哪些 skills
与可以通过 agents 选项 编程定义的子代理(subagents)不同,skills 只能创建为磁盘上的文件,SDK 不提供编程方式注册它们的 API。
说明:Skills 通过文件系统 setting sources 被发现。在
query()的默认选项下,SDK 会加载 user 与 project 源,因此~/.claude/skills/、<cwd>/.claude/skills/,以及从<cwd>到仓库根目录之间任意父目录下的.claude/skills/都可用。如果显式设置了settingSources,需要包含'user'或'project'才能保留 skill 发现能力;也可以使用plugins选项 从特定路径加载 skills。
在 Agent SDK 中使用 Skills
在 query() 上设置 skills 选项,控制 Claude 在会话中可调用哪些 skill。省略该选项时,已发现的 skills 会全部启用,且 Skill 工具可用,行为与 CLI 一致。传入 "all" 可让 Claude 调用所有已发现的 skill;传入名称列表则只允许列表中的;传入 [] 则不允许调用任何 skill。
例如,只允许 Claude 调用两个指定名称的 skill:
options = ClaudeAgentOptions(skills=["pdf", "docx"])
const options = { skills: ["pdf", "docx"] };
在会话中配置 Skills
设置 skills 后,SDK 会自动将 Skill 工具加入 allowedTools。如果同时传入了显式的 tools 列表,需要在其中包含 "Skill",Claude 才能调用 skills。
配置完成后,Claude 会自动从文件系统发现 skills,并在与用户请求相关时调用它们。
以下示例在一个会话中启用所有已发现的 skill,并预先批准 skills 常用的工具。示例将 cwd 设为进程当前工作目录,因此需要在包含 .claude/skills/(位于当前目录或其任一父目录)的项目内运行:
import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
cwd=os.getcwd(), # .claude/skills/ here or in a parent directory
setting_sources=["user", "project"], # Load skills from filesystem
skills="all", # Let Claude invoke every discovered skill
allowed_tools=["Read", "Write", "Bash"],
)
async for message in query(
prompt="Help me process this PDF document", options=options
):
print(message)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Help me process this PDF document",
options: {
cwd: process.cwd(), // .claude/skills/ here or in a parent directory
settingSources: ["user", "project"], // Load skills from filesystem
skills: "all", // Let Claude invoke every discovered skill
allowedTools: ["Read", "Write", "Bash"]
}
})) {
console.log(message);
}
确认 Skills 已加载
在消息流的开始阶段,SDK 会产出一条 subtype 为 init 的 system 消息。检查其 skills 数组即可确认 skills 在 Claude 开始工作前已成功加载。该数组包含已定义的可供用户调用的 skills,以及 Claude Code 内置(bundled)的 skills。
该数组只列出可供用户调用的 skills。在 frontmatter 中设置了 user-invocable: false 的 skill 仍会加载并可供 Claude 使用,但不会出现在该数组中。无论该 skill 是否在你的 skills 列表中,该数组都反映会话实际发现到的 skills。
只允许特定 Skills
若只想让 Claude 调用指定的 skills,在 skills 列表中传入其名称。名称需匹配 SKILL.md 中的 name 字段,或该 skill 所在目录名;对插件提供的 skill 使用 plugin:skill 形式。
该列表只接受精确的技能名称。如果某一项无法作为精确名称使用,query() 会在会话启动前就拒绝整个列表(见下文「无效 skill 名称错误」)。
未列入列表的 skill,模型看不到,Skill 工具也会拒绝调用,但其文件仍留在磁盘上,可通过 Read 和 Bash 访问。限制列表并不会限制按名称派发。
若要让 Claude 调用所有已发现的 skill,应传入 skills: "all",而不是通配符写法。
Agent SDK 会话中的命令
本节即 SDK 的命令(command)文档。命令是指在 prompt 中发送 /<name> 所运行的任何东西。命令面板上的条目背后的实现各不相同:
- 内置命令(Built-in commands):执行编码在 Claude Code 进程内部的逻辑,例如
/compact - 内置技能(Bundled skills):随 Claude Code 附带的 prompt 产物,例如
/code-review - 你自己的 skills:你编写的 prompt 产物,每个都是包含
SKILL.md文件的目录。一个可供用户调用的 skill 名称会自动加入命令面板,因此派发你自己的/security-check与运行内置命令的方式相同 - 自定义命令文件(Custom command files):一种较旧的产物形式,行为相同,是
.claude/commands/下的扁平 Markdown 文件,文件名即为命令名。Skills 是它推荐的继任者
默认情况下,你和 Claude 都可以调用任意 skill。可以通过 skill 的 frontmatter 分别限制这两条调用路径。两个术语的定义参见词汇表中的 Command 和 Skill 条目。完整的内置命令列表见 Commands in Claude Code,两种产物形式的完整指南见 Extend Claude with skills。
发现可用命令
可以通过 SDK 派发那些无需交互式终端即可运行的命令。system/init 消息的 slash_commands 字段列出了当前会话中可用的命令。需要交互式终端的命令(如 /theme 和 /terminal-setup)不会出现在列表中。可在会话启动时读取该字段:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Hello Claude",
options: { maxTurns: 1 }
})) {
if (message.type === "system" && message.subtype === "init") {
console.log("Available commands:", message.slash_commands);
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage
async def main():
async for message in query(prompt="Hello Claude", options=ClaudeAgentOptions(max_turns=1)):
if isinstance(message, SystemMessage) and message.subtype == "init":
print("Available commands:", message.data["slash_commands"])
asyncio.run(main())
打印出的列表混合了内置命令、内置 skills、你可供用户调用的 skills,以及 .claude/commands/ 文件:
Available commands: ["clear", "compact", "context", "usage", "code-review", "verify", "security-check", ...]
你可供用户调用的 skills 会同时出现在这个列表和「确认 Skills 已加载」一节所述的 skills 数组中。slash_commands 列表还包含会话中其余的可用命令。设置了 user-invocable: false 的 skill 不会出现在任何一个列表中。配置了 MCP servers 的会话,还可以将 MCP prompts 作为命令暴露。
按名称派发命令
在 prompt 字符串中包含 /<name> 即可发送命令,方式与发送普通文本相同。派发不依赖 skills 选项——即便某个可供用户调用的 skill 不在你的 skills 列表中,发送 /<name> 依然会运行它。像 /compact 这样作用于对话历史的命令,需要先有历史消息才能生效。
说明:命令与其它 prompt 一样,可能触发
maxTurns/max_turns限制,这会导致查询以 error 类型的 result 结束,而不是success。关于 error result 的约定,参见 Handle the result。如果命令可能触及该限制,请像 Single Message Input 中所示那样,用 TypeScript 的try/catch或 Python 的try/except包裹消息循环,或者将maxTurns设得足够大以完成任务。
用 /compact 压缩历史
/compact 命令通过总结较早的消息来缩减对话历史的大小,同时保留重要上下文。压缩需要已有对话且历史消息足够多才能进行总结。下面的示例先进行一轮对话,然后压缩它,并读取报告压缩结果的 compact_boundary system 消息:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Compaction needs existing history, so have a conversation first
try {
for await (const message of query({
prompt: "Explain what this project does",
options: { maxTurns: 2 }
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result,
// so the follow-up query below still runs.
console.error(`Session ended with an error: ${error}`);
}
// Compact the same conversation
for await (const message of query({
prompt: "/compact",
options: { continue: true, maxTurns: 1 }
})) {
if (message.type === "system" && message.subtype === "compact_boundary") {
console.log("Compaction completed");
console.log("Pre-compaction tokens:", message.compact_metadata.pre_tokens);
console.log("Trigger:", message.compact_metadata.trigger);
// Example output:
// Compaction completed
// Pre-compaction tokens: 1842
// Trigger: manual
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage, SystemMessage
async def main():
# Compaction needs existing history, so have a conversation first
try:
async for message in query(
prompt="Explain what this project does",
options=ClaudeAgentOptions(max_turns=2),
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
except Exception as error:
# A single-shot query() raises after yielding an error result,
# so the follow-up query below still runs.
print(f"Session ended with an error: {error}")
# Compact the same conversation
async for message in query(
prompt="/compact",
options=ClaudeAgentOptions(continue_conversation=True, max_turns=1),
):
if isinstance(message, SystemMessage) and message.subtype == "compact_boundary":
print("Compaction completed")
print("Pre-compaction tokens:", message.data["compact_metadata"]["pre_tokens"])
print("Trigger:", message.data["compact_metadata"]["trigger"])
# Example output:
# Compaction completed
# Pre-compaction tokens: 1842
# Trigger: manual
asyncio.run(main())
说明:只有真正执行了压缩,才会产出
compact_boundary消息。如果没有内容可总结,/compact会报告原因而不是抛出异常。此时运行仍会以successresult 结束,且不会有compact_boundary消息,result 文本会携带原因,例如单轮简短对话后可能出现Not enough messages to compact.。全新的一次性query()调用总是以空上下文开始,因此该模式应用在已有历史轮次的会话中,例如 流式输入模式,或恢复会话时。
用 /clear 重置上下文
/clear 命令将对话重置为空上下文,此后的 prompt 不再带有先前的对话历史。之前的对话仍保留在磁盘上。可以通过将其会话 ID 传给 resume 选项 返回该对话。
/clear 在流式输入模式中很有用(该模式下你在单一连接上发送多条 prompt)。对于一次性 query() 调用,每次调用本就以空上下文开始,因此发送 /clear 没有实际效果;此时应直接发起新的 query()。
创建 Skills
将每个 skill 创建为一个目录,其中包含带 YAML frontmatter 和 Markdown 内容的 SKILL.md 文件。description 字段决定 Claude 何时调用该 skill。
示例目录结构:
.claude/skills/security-check/
└── SKILL.md
选择发现级别
将 skills 保存在以下两个最常见的发现级别之一:
| 级别 | 路径 | 说明 |
|---|---|---|
| 项目级 skills | .claude/skills/ | 仅在当前项目中可用 |
| 个人级 skills | ~/.claude/skills/ | 在你的所有项目中可用 |
如果已有 .claude/commands/ 下的自定义命令文件,它们会继续正常工作。位于 .claude/commands/deploy.md 的命令文件会创建 /deploy,其行为与位于 .claude/skills/deploy/SKILL.md 的 skill 相同。若命令文件与 skill 同名,具体以哪个生效见 Where skills live。SDK 会从与 skills 相同的两个作用域加载 .claude/commands/ 和 ~/.claude/commands/ 文件。两种产物形式的完整指南见 Extend Claude with skills。
创建并派发你的第一个 Skill
创建 .claude/skills/security-check/SKILL.md:
---
name: security-check
description: Run a security vulnerability scan
---
Analyze the codebase for security vulnerabilities including:
- SQL injection risks
- XSS vulnerabilities
- Exposed credentials
- Insecure configurations
文件一旦存在,该 skill 就可以通过 SDK 使用了。当请求与其描述匹配时 Claude 会调用它,你也可以直接派发:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "/security-check",
options: { maxTurns: 10 }
})) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def main():
async for message in query(
prompt="/security-check", options=ClaudeAgentOptions(max_turns=10)
):
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())
成功运行会以 success result 结束,其文本携带扫描结果。针对一个植入了漏洞的小型 Express 应用,result 文本开头类似:
**Security scan of `app.js` — 4 findings (most severe first):**
1. **SQL Injection** (line 8) — `req.query.name` is concatenated directly into the SQL string. Trivially exploitable (`' OR '1'='1`, `'; DROP TABLE users;--`). **Fix:** use parameterized queries, e.g. `db.query("SELECT * FROM users WHERE name = ?", [req.query.name], cb)`.
...
该 skill 的名称也会出现在 init 消息的 slash_commands 数组中。
说明:Claude Code 内置了
code-review和verify两个 skill。如果你将某个.claude/commands/文件命名为其中之一,例如.claude/commands/code-review.md,该文件对应的命令会遮蔽内置的 skill,slash_commands中该名称只会出现一次。
为 Skills 预授权工具
说明:对于项目级和个人级 skills,
allowed-toolsfrontmatter 字段仅在直接使用 Claude Code CLI 时生效。在 SDK 会话中,应通过 query 配置里的allowedTools选项(Python 中为allowed_tools)来管理这些 skills 的工具批准。从 claude.ai 同步而来的 skills 遵循它们自己的 frontmatter 规则。
Skills 使用会话的工具运行。下例通过 allowedTools(Python 中为 allowed_tools)预先批准 Read、Grep、Glob,使 Claude 在运行 security-check skill 时能够检查文件而无需为审批而中断:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
setting_sources=["user", "project"], # Load skills from filesystem
skills="all",
allowed_tools=["Read", "Grep", "Glob"],
)
async def main():
async for message in query(prompt="Check this project for security issues", options=options):
print(message)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Check this project for security issues",
options: {
settingSources: ["user", "project"], // Load skills from filesystem
skills: "all",
allowedTools: ["Read", "Grep", "Glob"]
}
})) {
console.log(message);
}
在消息流中,skill 调用会表现为一次 Skill 工具调用,随后是针对项目文件的 Read 调用。运行以携带扫描结果的 success result 结束。
该列表是预先批准所列工具,而不是限制其它工具。关于完整的权限流程,包括权限模式和 canUseTool 回调,参见 Permissions。
故障排查
找不到 Skills
检查 settingSources 配置:SDK 通过 user 和 project setting sources 发现 skills。如果显式设置了 settingSources/setting_sources 却省略了这两个源,SDK 就不会加载 skills:
# Skills not loaded: setting_sources excludes user and project
options = ClaudeAgentOptions(setting_sources=[], skills="all")
# Skills loaded: user and project sources included
options = ClaudeAgentOptions(
setting_sources=["user", "project"],
skills="all",
)
// Skills not loaded: settingSources excludes user and project
const optionsWithoutSkills = {
settingSources: [],
skills: "all"
};
// Skills loaded: user and project sources included
const optionsWithSkills = {
settingSources: ["user", "project"],
skills: "all"
};
各个源分别加载哪些 skill 目录,参见文件系统源对照表。关于 settingSources/setting_sources 的更多细节,参见 TypeScript SDK reference 或 Python SDK reference。
检查工作目录:SDK 会从 cwd 选项所指目录及其直到仓库根目录之间的每一层父目录中的 .claude/skills/ 加载 skills。确保 cwd 指向包含 .claude/skills/ 的目录、或其在同一仓库内的下级目录:
# Ensure your cwd points to the directory containing .claude/skills/
options = ClaudeAgentOptions(
cwd="/path/to/project", # .claude/skills/ here or in a parent directory
setting_sources=["user", "project"], # Loads skills from these sources
skills="all",
)
// Ensure your cwd points to the directory containing .claude/skills/
const options = {
cwd: "/path/to/project", // .claude/skills/ here or in a parent directory
settingSources: ["user", "project"], // Loads skills from these sources
skills: "all"
};
完整模式参见在 Agent SDK 中使用 Skills。
核实文件系统位置:
# Check project skills
ls .claude/skills/*/SKILL.md
# Check personal skills
ls ~/.claude/skills/*/SKILL.md
Skill 未被使用
检查 skills 选项:如果传入了 skills 列表,确认该 skill 的名称在其中。当 Claude 尝试调用一个未列入列表的 skill 时,Skill 工具会返回 Skill <name> is not in this session's skills allowlist。可将该名称加入列表,或直接在 prompt 中发送 /<name> 派发该 skill(此方式无需列入列表即可生效)。
检查 description:确保描述具体且包含相关关键词。写好 description 的指南参见 Agent Skills best practices。
无效 Skill 名称错误
当 skills 列表中的某个名称无法作为精确的 skill 名称使用时,query() 会在启动 Claude Code 进程之前就拒绝该列表。会触发拒绝的名称包括:
- 空名称
- 名称中包含括号、逗号或控制字符
- 名称前后带有空白填充
- 通配符形式,例如裸的
*或以:*结尾的后缀
各 SDK 的报错方式不同:
TypeScript:TypeScript SDK 会抛出一个 Error,说明该条目违反的规则。例如 skills: ["docs:*"] 会抛出:
Invalid skill name "docs:*": wildcard-suffix names are not allowed; list each skill by its exact name.
空名称会报告 Skill names must be non-empty strings.
Python:Python SDK 会抛出 ValueError,说明该条目违反的规则。例如 skills=["docs:*"] 会抛出:
ValueError: Invalid skill name 'docs:*': wildcard-suffix names are not allowed; list each skill by its exact name.
空名称会报告 Skill names must be non-empty strings。
其它故障排查
关于一般性的 skills 故障排查(例如 YAML 语法错误和调试),参见 Claude Code skills troubleshooting section。
后续步骤
Claude Code skills guide 深入讲解了如何编写 skill。其指导内容同样适用于 SDK 会话,但有一处例外:对于项目级和个人级 skills,为 Skills 预授权工具一节所述的 allowedTools 选项取代了 allowed-tools frontmatter 字段。可以从以下几节开始:
- Frontmatter reference:所有支持的字段
- Pass arguments to skills:
$ARGUMENTS、$0、$1,以及 skill 叠加使用。完整替换表还包含具名参数和${CLAUDE_*}变量 - Inject dynamic context:在 Claude 看到 skill 内容之前运行的
!`command`行 - Where skills live:所有发现级别、插件命名空间,以及 skill 与命令文件同名时的处理方式
相关资源
- Commands in Claude Code:完整的命令面板,包括所有内置命令
- Agent Skills overview:概念性概览、优势与架构
- Agent Skills best practices:编写高效 skills 的指南
- Agent Skills cookbook:示例 skills 与模板
- Subagents in the SDK:类似的基于文件系统的 agent,附带编程选项
- SDK overview:SDK 总体概念
- TypeScript SDK reference:完整 API 文档
- Python SDK reference:完整 API 文档