理解 Agent 中的 Slash Command:从概念到自定义命令实践 📅 2026/6/29 20:17:39 看起来像一句聊天消息但本质上更接近“命令”。普通消息通常会进入大模型推理流程由模型理解意图再决定是否使用工具Slash Command 则会先被 Agent 的命令系统拦截和解析然后按命令名触发固定逻辑。这也是我觉得它值得单独讲清楚的原因Slash Command 不是 Prompt 的另一种写法而是 Agent 系统里的一个控制入口。理解这个入口后很多问题就容易解释了为什么/help不需要模型推理也能直接显示帮助信息为什么/new可以直接开启新会话为什么有些开源项目安装后会在 Claude Code、Gemini CLI、Hermes 这类 Agent 里多出自己的命令为什么 Hermes 可以通过配置新增/greet、/wechat-gzh这样的自定义命令这篇文章围绕这些问题展开重点放在 Slash Command 本身而不是 Skill 的基础概念。二、Slash Command 到底是什么Slash Command 是 Agent 会话中的一种“命令式输入”。它通常以/开头后面跟命令名和可选参数。例如/help /model gpt-5.1 /skill markdown-to-wechat-richtext /wechat-gzh abc/def.md一条 Slash Command 通常可以拆成两部分/wechat-gzh abc/def.md └─────────┘ └────────┘ 命令名 参数也就是命令名/wechat-gzh 参数abc/def.mdAgent 收到这类输入后一般不会马上把整句话当作自然语言丢给模型而是先执行类似下面的流程用户输入一条以 / 开头的消息 ↓ Agent 判断这是 Slash Command ↓ 解析命令名和参数 ↓ 查找命令注册表、Quick Command、插件命令或 Skill 命令 ↓ 执行对应逻辑 ↓ 返回结果或者改变当前会话状态所以 Slash Command 的关键点不是“让模型理解得更好”而是“让系统更确定地触发一个动作”。举个简单例子帮我开一个新会话这是自然语言Agent 需要理解你的意图。而/new这是命令系统可以直接把它识别为“开启新会话”。三、Slash Command 解决了什么问题Slash Command 的价值是把常用操作变成短小、稳定、可重复的入口。在 Agent 使用过程中有些事情不适合每次都用自然语言描述。比如查看帮助新建会话清理上下文切换模型加载 Skill执行固定脚本给已有能力起一个短别名在聊天平台里触发运维检查如果每次都用自然语言表达容易出现两个问题。第一个问题是啰嗦。比如“帮我重新开启一个新的上下文并且不要继承当前对话历史”不如/new直接。第二个问题是歧义。自然语言要经过模型理解模型可能会解释、追问、或者做出和预期不一致的判断Slash Command 的命令名和参数结构更固定适合控制类动作。我通常把 Slash Command 分成四类来看。会话控制命令这类命令改变当前会话状态例如/new /clear /retry /undo /compress /quit它们不是用来完成业务任务的而是用来管理会话本身。配置和状态命令这类命令用于查看或修改 Agent 运行状态例如/model /config /tools /status /usage它们的特点是用户希望得到一个确定的系统行为而不是一段开放式回答。能力加载命令这类命令用于加载某种能力或工作流例如 Hermes 中的/skill markdown-to-wechat-richtext也可以是某个 Skill 被注册成动态命令后直接调用/markdown-to-wechat-richtext abc/def.md这里的重点是Slash Command 只是入口真正执行任务的可能是 Skill、工具、插件或 Agent 工作流。用户自定义命令用户自定义命令是本文后面重点讨论的部分。比如希望输入/greet直接输出Hello, nice to meet you!或者希望输入/wechat-gzh abc/def.md实际调用本地已有的/markdown-to-wechat-richtext abc/def.md这就是 Slash Command 作为“快捷入口”的典型用法。四、开源项目为什么安装后能提供自己的命令很多开源项目安装后可以在某个 Agent 里使用自己的 Slash Command。这里容易产生一个误解好像所有 Agent 都有一套统一的 Slash Command 插件标准。实际情况不是这样。不同 Agent 的实现方式差别很大。一个项目能提供命令通常是因为它适配了某个 Agent 的扩展机制。常见方式有几种。文件型命令有些 Agent 会约定一个命令目录。项目只要把 Markdown 文件放进去Agent 就会把这些文件识别成命令。典型形式类似.claude/commands/xxx.md ~/.claude/commands/xxx.md这种模式下Markdown 文件往往不是普通文档而是一个 Prompt 模板。用户输入/xxx后Agent 加载对应模板再把参数拼进去执行。这种方式很适合开源项目分发自己的工作流例如/spec-create /spec-implement /spec-review但要注意这是某些 Agent 的约定不代表所有 Agent 都支持同样的目录结构。注册表型命令有些 Agent 在源码里维护一张命令注册表。每个命令都有名字、说明、参数、handler。用户输入/help、/model、/new时系统会查注册表然后调用对应处理函数。Hermes 的内置 Slash Command 就属于这种思路。命令注册表是核心入口之一CLI、自动补全、帮助信息、部分平台映射都可以基于这张表生成。这种方式更适合系统级命令因为它需要修改 Agent 本身的代码。插件型命令插件型命令介于“用户配置”和“修改源码”之间。项目提供一个插件插件安装后向 Agent 注册新的 Slash Command。用户不需要改 Agent 源码但命令仍然可以拥有比较完整的逻辑。这类方式适合可分发、可复用、功能较完整的扩展。MCP 或工具型入口还有一些项目并不直接提供 Slash Command而是提供 CLI、MCP Server 或工具集。Agent 通过工具发现机制拿到这些能力后再用某种命令或自然语言触发。这种情况下用户看到的可能像 Slash Command但底层并不一定是命令文件或命令注册表而是工具调用。所以判断一个项目为什么能提供命令不能只看“有没有/xxx”还要看它适配的是哪一种扩展机制。五、Hermes 里自定义 Slash Command 的几种方式在 Hermes 中自定义 Slash Command 可以从简单到复杂分成几层。Quick Command最简单的是 Quick Command。它写在 Hermes 配置文件里~/.hermes/config.yamlQuick Command 支持两种类型exec aliasexec用来执行本地 shell 命令适合固定输出、系统检查、脚本执行。alias用来把一个短命令改写到另一个 Slash Command适合给已有命令、Skill 命令或复杂命令起别名。官方文档里的表达也很直接Quick Commands 可以把一个短 Slash Command 映射到 shell 命令或者映射到另一个 Slash Command。内置 Slash Command如果要做系统级命令就需要改 Hermes 源码。大体思路是在命令注册表里增加命令定义。在 CLI 或 Gateway 的命令处理逻辑里增加 handler。如有必要补充帮助信息、自动补全、平台映射和测试。这种方式适合真正属于 Hermes 核心能力的命令例如会话控制、配置管理、工具管理等。普通用户只是想加一个快捷命令时不建议直接走这条路。插件命令插件命令适合可分发扩展。如果一个能力不应该进入 Hermes 核心但又希望安装后自动多出命令就可以做成插件。插件方式比 Quick Command 更重但比直接改核心源码更适合分发。Skill 动态命令Hermes 还支持把已安装 Skill 当作动态命令来调用。例如本地有一个 Skillmarkdown-to-wechat-richtext它可以用于把 Markdown 文章转换成微信公众号编辑器友好的富文本 HTML 片段。如果这个 Skill 可以作为动态命令调用那么原始调用可能是/markdown-to-wechat-richtext abc/def.md这里/markdown-to-wechat-richtext是入口abc/def.md是传给这个 Skill 的文件路径参数。后面要做的/wechat-gzh本质上就是给这条较长的 Skill 命令起一个短别名。六、实践一用 Quick Command 实现/greet先从最简单的例子开始实现一个/greet命令。目标效果是/greet输出Hello, nice to meet you!这个命令不需要读取文件不需要调用 Skill也不需要让大模型参与推理。它只是返回一句固定文本所以最适合用 Quick Command 的exec类型。配置写法打开 Hermes 配置文件~/.hermes/config.yaml加入下面配置quick_commands: greet: type: exec command: printf Hello, nice to meet you!\n这里有几个细节需要注意。greet是命令名不需要写成/greet。用户输入时带/配置里只写命令名。type: exec表示这是一个执行 shell 命令的 Quick Command。command里的内容是实际执行的 shell 命令。这里用printf输出固定文本。保存配置后在 Hermes 会话里输入/greet预期看到Hello, nice to meet you!如果当前会话没有立即生效可以重启 Hermes CLI或者开启一个新会话再测试。为什么这里不用 Skill/greet这种命令没有复杂流程也没有可复用的任务经验。为了输出一句固定文本去写 Skill会把问题复杂化。这里用exec的好处是不调用 LLM不消耗 token配置简单行为稳定很适合做系统检查、固定脚本、状态查询比如下面这些命令也适合execquick_commands: disk: type: exec command: df -h / uptime: type: exec command: uptimeexec的边界也很清楚它适合执行明确的 shell 命令不适合承载复杂的 Agent 工作流。七、实践二用/wechat-gzh abc/def.md调用本地 Skill第二个例子更接近真实工作流。本地已经有一个 Skillmarkdown-to-wechat-richtext它的用途是把 Markdown 文章转换成微信公众号编辑器友好的富文本 HTML 片段。原始调用可以写得比较完整/markdown-to-wechat-richtext abc/def.md但这个命令名偏长。日常写文章时更希望输入一个短命令/wechat-gzh abc/def.md达到同样效果。目标映射关系是/wechat-gzh abc/def.md ↓ /markdown-to-wechat-richtext abc/def.md这里推荐使用全小写字母和连字符的命令名wechat-gzh这种命名方式更符合 Slash Command 的使用习惯也更不容易遇到大小写匹配带来的困扰。配置写法在~/.hermes/config.yaml中配置quick_commands: wechat-gzh: type: alias target: /markdown-to-wechat-richtext如果已经有前面的/greet可以放在同一个quick_commands下quick_commands: greet: type: exec command: printf Hello, nice to meet you!\n wechat-gzh: type: alias target: /markdown-to-wechat-richtext注意这里用的是alias不是exec。原因很简单/wechat-gzh不是要执行一条本地 shell 命令而是要转发到另一个 Slash Command让 Hermes 继续按 Skill 命令处理。参数到底是怎么传过去的这一段最容易困惑。用户输入的是/wechat-gzh abc/def.mdHermes 先把它拆成两部分/wechat-gzh abc/def.md └─────────┘ └────────┘ 命令名 参数文本也就是命令名/wechat-gzh 参数文本abc/def.md然后 Hermes 查quick_commands发现配置里有wechat-gzh: type: alias target: /markdown-to-wechat-richtext接下来alias 会把原命令后面的参数文本追加到target后面/markdown-to-wechat-richtext 空格 abc/def.md最终得到/markdown-to-wechat-richtext abc/def.md也就是说abc/def.md不是写死在配置里的也不需要在配置里写${1}、$ARGUMENTS这类占位符。它来自用户实际输入中跟在命令名后面的剩余文本。Hermes CLI 的处理逻辑也能印证这一点。alias 分支里会取出原始命令中base_cmd后面的内容user_args cmd_original[len(base_cmd):].strip() aliased_command f{target} {user_args}.strip() return self.process_command(aliased_command)这段逻辑表达的意思就是目标命令 原命令参数 改写后的新命令所以不同输入会得到不同的改写结果用户输入Hermes 改写后/wechat-gzh abc/def.md/markdown-to-wechat-richtext abc/def.md/wechat-gzh posts/a.md/markdown-to-wechat-richtext posts/a.md/wechat-gzh /home/sharpcj/blog/a.md/markdown-to-wechat-richtext /home/sharpcj/blog/a.mdtarget是固定的/markdown-to-wechat-richtext参数是动态的abc/def.md posts/a.md /home/sharpcj/blog/a.md这就是带参数 alias 的核心。Skill 接收到的是什么alias 只负责改写命令不负责解释参数含义。当/wechat-gzh abc/def.md被改写成/markdown-to-wechat-richtext abc/def.md后面的处理就交给markdown-to-wechat-richtext这个 Skill 命令。这个 Skill 需要理解abc/def.md是一个 Markdown 文件路径然后按自己的工作流去读取文件、转换内容并生成微信公众号可复制使用的 HTML fragment。所以职责边界是角色负责什么/wechat-gzh提供短命令入口Quick Command alias把短命令改写成长命令并保留参数/markdown-to-wechat-richtext加载并执行本地 Skill 工作流Skill理解文件路径完成 Markdown 到微信富文本 HTML 的转换这个边界很重要。不要期待 alias 自己去读文件、转换 HTML、处理 Mermaid 或输出结果文件。alias 只做“转发”。真正的任务执行在 Skill 里。没有传参数会怎样如果只输入/wechat-gzhalias 改写后会变成/markdown-to-wechat-richtext这时 Skill 没有拿到文件路径就无法知道要转换哪篇文章。比较合理的结果是提示用户补充 Markdown 文件路径。所以这个命令的推荐用法应该始终带上文件路径/wechat-gzh path/to/article.md如果路径里包含空格最好避免这种路径命名如果确实需要使用建议先按当前 Hermes 命令解析行为测试引号是否符合预期。技术文章和工程文件里我更建议直接使用不含空格的路径。八、exec和alias怎么选理解/greet和/wechat-gzh后Quick Command 的两种类型就比较清楚了。类型做什么是否调用 Agent 工作流适合场景exec执行本地 shell 命令通常不调用固定输出、系统检查、脚本执行alias改写到另一个 Slash Command取决于目标命令缩短命令名、包装 Skill、复用已有命令判断时可以问一个问题这个命令最终要做的事情是一条 shell 命令能完成还是应该交给 Agent/Skill 继续处理如果是一条 shell 命令能完成用exec。例如quick_commands: disk: type: exec command: df -h /如果是调用另一个 Slash Command用alias。例如quick_commands: wechat-gzh: type: alias target: /markdown-to-wechat-richtext我不建议把复杂 Prompt 直接塞进 Quick Command。Hermes 文档也明确提到string-only prompt shortcut 不是有效的 Quick Command。可复用 Prompt 工作流应该放进 Skill再用 alias 指向这个 Skill 命令。这也是/wechat-gzh这个例子的设计思路复杂工作流放 Skill 短入口用 alias九、排查命令不生效的问题配置完 Slash Command 后如果输入命令没有得到预期结果可以从下面几个方向排查。配置文件位置是否正确Quick Command 写在~/.hermes/config.yaml不要写到项目目录里的普通 YAML 文件也不要写到其他 profile 的配置里。如果使用 Hermes profile需要确认当前会话使用的是哪个 profile。不同 profile 有不同的配置、Skill 和记忆目录。YAML 缩进是否正确YAML 对缩进敏感。下面是正确写法quick_commands: greet: type: exec command: printf Hello, nice to meet you!\n wechat-gzh: type: alias target: /markdown-to-wechat-richtext常见错误是缩进错位例如把type写到和greet同一层或者把第二个命令写到greet里面。命令名不要带斜杠配置 key 不写/wechat-gzh: type: alias target: /markdown-to-wechat-richtext用户输入时才写//wechat-gzh abc/def.md这是很多人第一次配置时容易写错的地方。修改配置后是否需要重启有些配置在当前会话里不会立刻重新加载。稳妥做法是保存配置后重启 Hermes CLI或者开启新会话再测试。如果是在 Gateway 场景比如 Telegram、Discord、Slack 里使用也可能需要重启 Gateway。Skill 是否真的存在如果/wechat-gzh最终指向/markdown-to-wechat-richtext那本地就必须真的有这个 Skill并且 Hermes 能识别到它。可以用 Hermes 的 Skill 管理命令检查或者在会话里直接测试原始命令/markdown-to-wechat-richtext abc/def.md如果原始命令都不工作/wechat-gzh这个 alias 也不会工作。alias 只是改写命令不会修复目标命令本身的问题。十、什么时候需要更正式的 Slash CommandQuick Command 很方便但它不是万能的。如果只是给常用命令起别名、执行脚本、包装已有 SkillQuick Command 足够好。但如果需要下面这些能力就应该考虑更正式的实现方式命令需要复杂参数解析命令需要交互式确认命令要出现在完整帮助和自动补全体系里命令要跨平台稳定分发给很多用户命令需要访问 Hermes 内部状态命令需要完整测试和权限控制这时更适合做内置命令或插件命令。可以这样选择需求推荐方式自己用的短命令Quick Command执行一条固定脚本Quick Commandexec给已有 Slash Command 起别名Quick Commandalias包装已有 SkillSkill Quick Commandalias给团队分发完整扩展插件命令进入 Hermes 核心能力内置 Slash Command对大多数个人工作流来说最实用的组合是Skill 承载复杂流程 Quick Command 提供短入口/wechat-gzh就是这个组合的例子。十一、总结Slash Command 是 Agent 里的命令入口不是普通 Prompt。它的作用是把常用动作变成明确、短小、可重复的输入。命令系统会先解析命令名和参数再决定调用内置逻辑、Quick Command、插件命令、Skill 命令或其他扩展能力。在 Hermes 中普通用户自定义命令最适合从 Quick Command 开始。固定输出或脚本执行用execquick_commands: greet: type: exec command: printf Hello, nice to meet you!\n给已有 Skill 命令起短别名用aliasquick_commands: wechat-gzh: type: alias target: /markdown-to-wechat-richtext输入