核心三角-Command Agent Skill - claude_0x02

目录概要

  1. 接着上一篇的疑问
  2. 历史背景:为什么会演化出三个相似的东西
  3. 一张表看清三者本质
  4. 三个维度深入对比
  5. 经典场景:"现在几点了?"------谁响应?
  6. 决策树:遇到需求到底选哪个?
  7. Frontmatter 对比速查
  8. 混编:三者如何组合使用

1. 接着上一篇的疑问

上一篇扫完 6 个核心概念之后,我留了一个尾巴------Command、Agent、Skill 这三个东西看起来都是一段提示词,都能封装工作流,到底有啥区别?这篇就把这个尾巴接上。

这三者不仅名字容易混,frontmatter 字段还有大量重叠------都有 namedescriptionallowed-toolsmodel------光看一个文件内容,你甚至分不出这是 command 还是 skill。更要命的是,它们的触发时机、上下文隔离、状态持久化等行为差异,在官方文档里是分散描述的,你很难在一个地方拿到清晰对比。

这篇的三个部分:

  • 历史------为什么会演化出三个,不是一个
  • 对比学习------三者在各维度上的差异
  • 选择决策------遇到需求怎么判断用哪个

2. 历史背景:为什么会演化出三个相似的东西

不感兴趣历史的可以直接跳到第 3 节。但我个人觉得,理解演化路径之后,三者的定位会清晰很多------它们不是拍脑袋造的,是一步一步解决真实问题迭代出来的。

2.1 最早只有 Commands

Claude Code 最早的扩展机制只有 slash commands

那时候很朴素:想复用工作流就写个 .md,里面放提示词,然后用 /name 触发。跟 textexpander、shell alias 都没啥区别。

graph LR U[用户输入 /commit-and-push] --> C[读取 commit-and-push.md] C --> P[作为提示词塞给 Claude] P --> Cla[Claude 执行]

Commands 解决的问题很直白:避免重复打字。但很快就暴露出短板:

  • Claude 不会主动用 :你不输入 /xxx,Claude 永远想不到去用
  • 污染上下文:一个复杂 command 几百行提示词塞进主对话,越用越慢
  • 没有记忆:每次白板开始,学不到东西

2.2 Subagents 诞生------解决复杂任务

Boris Cherny 在一些公开访谈里反复提到一个观点:不要让一个复杂任务污染主对话

为了这件事,Subagents 诞生了。Subagent 的设计哲学是:

一个 subagent 就是一个有独立人格、独立上下文、独立工具权限的"员工"。

graph TB Main[主对话上下文] -.派遣任务.-> Agent[Subagent
独立上下文] Agent -.只返回结果.-> Main Agent --> T[自己的工具集] Agent --> M[自己的 memory] Agent --> S[自己的 skills]

它解决了:

  • 隔离:子任务不污染主对话
  • 自主:Claude 自己判断什么时候派遣 subagent(靠 description 匹配)
  • 专业化:每个 subagent 有专属工具、模型、权限

但 Subagents 太重了。对于"现在几点了?"这种问题,启动一个独立上下文的 agent,就像叫一个专职员工去接一杯水------成本完全不匹配。

2.3 Skills 诞生------轻量级可复用知识

Anthropic 内部用 Claude Code 时发现,大量的场景是:

"我想让 Claude 做某件事时按某个方法做,但不值得起一个 agent。"

比如:

  • 生成 SVG 时按公司设计规范
  • 调用内部 API 时按错误处理约定
  • 写 commit message 时按项目风格

这些都是可复用的知识片段,不是独立任务。于是 Skills 出现了。

Skills 的关键创新是"渐进式揭露 "------一个 skill 是一个目录,不是单个文件。SKILL.md 只放"何时用、怎么用"的摘要,具体参考资料、脚本、示例分散在子目录里,用的时候再读。

graph TD A[SKILL.md
简述 + 何时触发
默认加载] B[references/api.md
用时才加载] C[scripts/validate.py
用时才执行] D[examples/case1.md
参考示例] A -.用到时读.-> B A -.用到时跑.-> C A -.用到时看.-> D

2.4 为什么不把三者合并?

我其实也想过这个问题------为什么不设计一个统一的 "Extension" 类型,用几个布尔字段开关?

答案是:三者的心智模型完全不同,强行合并反而更难学

  • Command 是"用户主动触发的工作流入口 "------心智模型是按钮
  • Skill 是"可复用的知识/流程 "------心智模型是工具箱里的工具
  • Agent 是"有独立人格的员工 "------心智模型是员工

按钮、工具、员工,这三个词你一听就知道用法不同。但如果把它们合成一个叫 "Extension" 的东西然后用布尔字段区分,反而让人每次都要脑补"这东西现在是按钮还是员工"。

这跟编程语言设计里"正交性 vs 简单性"是一个老问题------Anthropic 选择保留三个清晰的心智模型,承担额外的概念负担换取更低的使用负担。


3. 一张表看清三者本质

这张表是全篇精华,建议截图保存。

维度 Command Agent Skill
心智模型 按钮 员工 工具
文件位置 .claude/commands/<name>.md .claude/agents/<name>.md .claude/skills/<name>/SKILL.md
运行上下文 内联(共享主对话) 独立子上下文 内联(默认)
用户主动触发 /command-name ❌ 不出现在 / 菜单 /skill-name(除非 user-invocable: false
Claude 自动触发 ❌ 永远不会 ✅ 通过 description 匹配 ✅ 通过 description 匹配
独立上下文窗口 ✅ 完全隔离 ❌(除非 context: fork
预加载其他 skills skills: 字段
持久化 memory memory: user/project/local
可限制工具权限 allowed-tools: tools: / disallowedTools: allowed-tools:
可指定模型
典型场景 团队共享工作流入口 复杂自主任务 可复用的知识片段

4. 三个维度深入对比

4.1 上下文维度

这是三者最本质的区别。

graph TB subgraph Main[主对话 - 用户与 Claude] direction LR M1[用户消息] M2[Claude 响应] CMD[Command 执行
内联在主上下文] SKILL[Skill 执行
内联在主上下文] end AGT[Agent 执行
独立上下文] Main -. 派遣任务 .-> AGT AGT -. 只返回结果 .-> Main style AGT fill:#faa,stroke:#f00 style CMD fill:#afa,stroke:#0a0 style SKILL fill:#aaf,stroke:#00f

一个权衡:

  • 内联(Command/Skill):快、轻,但会占用主上下文 token
  • 隔离(Agent):慢、重,但不污染主上下文

一条实用经验------如果一个任务的中间推理过程很长(比如读十几个文件才能下判断),用 Agent;如果只是"应用一下模板"或"按某个方法做一件事",用 Skill。

4.2 触发维度

flowchart TD User[用户说 '现在几点了?'] User --> Check{Claude 决策} Check --> C1[检查 Commands
用户有输入 /xxx 吗?] Check --> C2[检查 Skills
有 description 匹配?] Check --> C3[检查 Agents
有 description 匹配?] C1 -->|没| X1[Commands 不触发] C2 -->|time-skill 匹配| Y1[✅ Skill 候选] C3 -->|time-agent 匹配| Y2[Agent 候选] Y1 --> Pick[Claude 选最轻的] Y2 --> Pick Pick --> Use[用 time-skill] style X1 fill:#fcc style Y1 fill:#cfc style Use fill:#ff9

Claude 的默认优先级

  1. Skill(内联,最便宜)← 优先
  2. Agent(独立上下文,贵)← Skill 不够用时
  3. Command(永不自动触发)← 只等用户主动输入

4.3 状态维度

Command Agent Skill
单次执行内的状态
跨会话记忆 memory 字段
预加载其他知识 skills 字段

唯一有持久化人格的是 Agent。这也是为什么 "code reviewer" 这种长期积累风格偏好的角色,最适合做成 Agent。


5. 经典场景:"现在几点了?"------谁响应?

这个仓库里恰好有三个同主题的 extension(有的是演示用的),完美的对照实验:

  • time-command(Command)
  • time-agent(Agent)
  • time-skill(Skill)

当用户说"现在几点了?"时:

机制 会触发吗? 为什么?
time-command Command 不会自动触发,必须输入 /time-command
time-agent 候补 description 也匹配,但 Skill 更轻------主对话直接内联算出来就够了,没必要开独立上下文。Skill 存在时,Agent 优先级更低
time-skill 首选 description 匹配 + 内联执行 + 零上下文开销

如果你把 "time" 这个需求实现成 agent 而不是 skill,那就是高射炮打蚊子。


6. 决策树:遇到需求到底选哪个?

flowchart TD Start[新需求来了] --> Q1{用户主动输入 /slash
才触发吗?} Q1 -->|是| CMD[选 Command
工作流入口] Q1 -->|否| Q2{任务复杂度?} Q2 -->|轻量 单一能力| Q3{需要隔离上下文?} Q2 -->|复杂 多步自主| Q4{需要持久化记忆
或预加载知识?} Q3 -->|否| SKILL[选 Skill] Q3 -->|是| SKILL_F[选 Skill
设置 context: fork] Q4 -->|否| AGT[选 Agent 基础版] Q4 -->|是| AGT_P[选 Agent
+ memory + skills] style CMD fill:#afa style SKILL fill:#aaf style SKILL_F fill:#aaf style AGT fill:#faa style AGT_P fill:#faa

6.1 实战四问

遇到新需求时,顺次问四个问题:

谁触发?

  • 用户主动 → Command
  • Claude 判断 → Skill / Agent

任务多重?

  • 几十 token 的轻操作 → Skill
  • 多步推理、读大量文件、调 API → Agent

要不要记住东西?

  • 每次白板 → Skill / Command
  • 跨会话记忆 → Agent(memory 字段)

会不会被 agent 调用?

  • 是 → 做成 Skill(可通过 skills: 预加载到 agent)
  • 否 → 根据其他条件决定

7. Frontmatter 对比速查

三个 frontmatter 有很多字段重名,但语义不同。这里只给最小常用集------完整的 13 个 Command 字段会在 04 篇逐一拆解,Agent/Skill 的完整字段表也会在对应的深入篇补齐。这里够用就行。

Command

yaml 复制代码
---
description: Do something useful
argument-hint: [issue-number]
allowed-tools: Read, Edit, Bash(gh *)
model: sonnet
---

(还有 disable-model-invocationuser-invocablename 等另外 9 个字段------04 篇细讲。)

Agent

yaml 复制代码
---
name: my-agent
description: Use this agent PROACTIVELY when...
tools: Read, Write, Edit, Bash
disallowedTools: Bash(rm *)
model: sonnet            # haiku / sonnet / opus / inherit
maxTurns: 10
permissionMode: acceptEdits
memory: user             # user / project / local
skills:
  - my-skill
mcpServers:
  - playwright
background: false
isolation: worktree
color: cyan
---

Skill

yaml 复制代码
---
name: my-skill
description: Do X when user asks for Y
argument-hint: [file-path]
disable-model-invocation: false
user-invocable: true
allowed-tools: Read, Grep, Glob
model: sonnet
context: fork
agent: general-purpose
---

字段含义对照(同名不同义)

字段 Command Agent Skill
name 文件名 必须显式声明 显式或文件夹名
description 描述(可选) 触发匹配用,必写 触发匹配用,必写
allowed-tools 允许的工具 tools 字段 允许的工具
model 模型别名 模型别名或 inherit 模型别名

8. 混编:三者如何组合使用

最经典的组合是 Command → Agent → Skill 三层编排。

sequenceDiagram actor User as 用户 participant CMD as /weather-orchestrator
(Command) participant AGT as weather-agent
(Agent) participant PS as weather-fetcher
(预加载 Skill) participant API as Open-Meteo API participant SK as weather-svg-creator
(Skill) User->>CMD: /weather-orchestrator CMD->>User: 摄氏还是华氏? User->>CMD: 摄氏 rect rgb(250, 200, 200) Note over CMD,AGT: Agent 阶段 独立上下文 CMD->>AGT: Agent 工具调用 AGT->>PS: 读取预加载指令 PS-->>AGT: API 调用方法 AGT->>API: GET current temperature API-->>AGT: 26°C AGT-->>CMD: temperature=26, unit=C end rect rgb(170, 170, 255) Note over CMD,SK: Skill 阶段 内联执行 CMD->>SK: Skill 工具调用 SK->>SK: 生成 SVG + output.md SK-->>User: 文件已生成 end

这里用了两种 skill 调用模式:

  1. Agent Skill 模式weather-fetcher 通过 agent frontmatter 的 skills: 字段预加载到 agent 上下文
  2. 直接 Skill 模式weather-svg-creator 由 command 通过 Skill 工具直接调用

这两种模式同样是 skill,使用方式完全不同------这在下一篇拆 weather system 源码时会看得很清楚。


三者的分工

到这里,Command/Agent/Skill 三者的差异和选型逻辑就讲完了。

简单复盘一下------三者不是三个并列的功能,而是演化路径上的三个阶段 :Commands 解决"少打字",Subagents 解决"任务隔离",Skills 解决"轻量知识复用"。三个心智模型各司其职------按钮、员工、工具,你记住这三个词,基本不会选错。

选型四问也很直白:谁触发?多重?要记忆吗?被谁调用? 顺次答完就有答案。

抽象讲完了,该看具体执行了。


Footnotes

参考资料

外部链接

相关推荐
竹林8182 小时前
在NFT项目中集成IPFS:从Pinata上传到前端展示的完整踩坑指南
前端·javascript
吴声子夜歌2 小时前
Vue3——渲染函数
前端·vue.js·vue·es6
Hello--_--World2 小时前
ES15:Object.groupBy() 和 Map.groupBy()、Promise.withResolvers() 相关知识点
开发语言·前端·javascript
Cache技术分享2 小时前
386. Java IO API - 监控目录变化
前端·后端
Hooray2 小时前
管理后台框架 AI 时代的版本答案,Fantastic-admin 6.0 它来了!
前端·前端框架·ai编程
2501_913680003 小时前
Vue3项目快速接入AI助手的终极方案 - 让你的应用智能升级
前端·vue.js·人工智能·ai·vue·开源软件
开开心心_Every3 小时前
动图制作工具,拆分转视频动态照离线免费
运维·前端·人工智能·edge·pdf·散列表·启发式算法
饭后一颗花生米3 小时前
2026 前端实战:AI 驱动下的性能优化与工程化升级
前端·人工智能·性能优化
YJlio3 小时前
4月14日热点新闻解读:从金融数据到平台治理,一文看懂今天最值得关注的6个信号
java·前端·人工智能·金融·eclipse·电脑·eixv3