作为 Codex、Claude Code 或者 OpenClaw、Hermes 等 Agent 的用户,你应该每天都在跟 Skills、MCP、CLI 这些概念打交道,可能也随时能看到一些媒体文章,讨论谁更好、该怎么选、该怎么配。
过去一年半,这样的讨论经历了好几波,好在今年初开始有一些相对客观的表达,尝试说明 MCP、Skills、CLI 各自的特点和定位。不过,这些讨论大多停留在定性层面:
- 2024.11--2025.5:Anthropic 发布 MCP,Cursor、OpenAI、Google、微软相继接入,国内 BAT 全线跟进,一些媒体称之为"AI 的 HTTP 协议"
- 2025.10--12:Anthropic 推出 Skills,"渐进式披露""按需加载""token 开销远低于 MCP"成为新的关注点
- 2026.1--3:OpenClaw 作者 Peter Steinberger 指出 CLI 天然适配 Agent;3 月 Perplexity CTO 宣布内部从 MCP 转向 CLI,YC 掌门 Garry Tan 公开指出 MCP 的上下文膨胀问题,国内开发者社区随之展开讨论 ------ 也就是这个时候,CLI 这个大家每天都在用的东西,被重新放进了"Agent 扩展能力"的讨论框架里
不知道你会不会好奇:在你使用的真实的 Agent 环境里 ------ CLI、MCP、Skills 这些都算是标准的扩展能力同时存在同时可用 ------ Agent 究竟会怎么协调它们的?谁先谁后?谁管谁?是不是谁会更好、谁会替代谁?我们尝试从 8 个常见的 Agent 的源码入手 ------ Codex、Gemini CLI、Kimi Code、MiMo Code、OpenClaw、Hermes、OpenCode、ClaudeCode(排名不分先后) ------ 把一个问题拆成四个递进的子问题来验证:当 CLI、MCP、Skills 同时在一个 Agent 里,面对同一个需求时,它们到底怎么分工、谁覆盖谁、谁管谁。
调研样本
| 来源 | Agent | 代码仓库 | 代码版本 |
|---|---|---|---|
| GitHub 官方 repo | Codex(OpenAI) | github.com/openai/codex |
4c43465 (2026-07-25) |
| GitHub 官方 repo | Gemini CLI(Google) | github.com/google-gemini/gemini-cli |
3818efb (2026-07-24) |
| GitHub 官方 repo | Kimi Code(月之暗面) | github.com/MoonshotAI/kimi-code |
c497af6 (2026-07-25) |
| GitHub 官方 repo | MiMo Code(基于 OpenCode) | github.com/XiaomiMiMo/MiMo-Code |
29321aa (2026-07-25) |
| GitHub 官方 repo | OpenCode | github.com/anomalyco/opencode |
0a6637e (2026-07-25) |
| GitHub 官方 repo | OpenClaw | github.com/openclaw/openclaw |
6e604438 (2026-07-25) |
| GitHub 官方 repo | Hermes(NousResearch) | github.com/NousResearch/hermes-agent |
760112a (2026-07-25) |
| GitHub | ClaudeCode(Anthropic) | 早期泄露版本 | a99de1b (2026-03-31) |
MiMo Code 基于 OpenCode fork,两个仓库有直接可比性。下文会在分析中标注哪些设计来自 OpenCode 原有代码,哪些是 MiMo Code 独立添加的。
一、问:工具池里,谁覆盖谁?
当一个 CLI 工具和 MCP 工具都能做同一件事,Agent 的实现代码怎么处理冲突?
这是一个纯代码层的问题,不看 prompt,不看模型意图,就看工具注册表。
Codex:核心工具名保留
Codex 把所有工具 ------ ShellCommandHandler、ExecCommandHandler、MCP 工具 ------ 统一存入同一个 ToolRegistry(HashMap<ToolName, CoreToolRuntime>)。核心工具先注册,占据工具名。当扩展/MCP 工具尝试注册同名工具时,直接跳过(codex-rs/core/src/tools/spec_plan.rs:964-1013):
rust
if !reserved_tool_names.insert(tool_name.clone()) {
warn!("Skipping extension tool `{tool_name}`: tool already registered");
continue;
}
ClaudeCode:built-in 优先
ClaudeCode 的 assembleToolPool 里,内置工具在前,MCP 工具在后,uniqBy 按名去重。注释直接写了"built-ins win on name conflict"(src/tools.ts:363-366):
typescript
return uniqBy(
[...builtInTools].sort(byName).concat(allowedMcpTools.sort(byName)),
'name',
)
两个 Agent,两种语言,不同的代码结构。结论出奇一致:CLI 作为内置工具,同名时覆盖 MCP。 没有例外。
全样本对照:
| Agent | CLI 工具注册 | MCP 工具注册 | 同名冲突处理 |
|---|---|---|---|
| Codex | ShellCommandHandler / ExecCommandHandler → ToolRegistry | McpHandler → ToolRegistry | 核心工具先注册,MCP/扩展同名时跳过 |
| Gemini CLI | Shell tool → ToolRegistry | MCP tools → ToolRegistry | 并列注册,无显式优先级规则 |
| Kimi Code | BashTool → builtinTools Map | mcpTools 独立 Map | 三个 Map 分别管理,loopTools 合并 |
| MiMo Code | bash (BashTool) → tool registry | MCP 通过 toolScriptMcp 注入 | 内置工具先注册 |
| OpenCode | shell (ShellTool) → tool registry | MCP 在 SessionTools 外部组装 | 内置先于 MCP |
| OpenClaw | exec 作为一等内置工具 | MCP tools 进入同一策略管道 | 无显式优先级 |
| Hermes | terminal 作为内置工具 | MCP tools 注册进 tool registry | 内置工具同名优先 MCP |
| ClaudeCode | BashTool 进入内置工具池 | MCP 在 assembleToolPool 合并 | uniqBy 保留插入顺序,builtins win |
Codex 和 ClaudeCode 用不同的代码结构表达了同一个规则。Hermes 在它的 Footprint Ladder 里也明确写了内置工具同名优先 MCP ------ 只不过 Hermes 是把它写成显式文档的唯一一家,Codex 和 ClaudeCode 是写在代码里。
需要说明的是,上面这个"覆盖"过程完全发生在模型看到工具之前。模型从头到尾只看到最终结果 ------ 一个去重后的工具列表 ------ 不知道曾经有过同名冲突。这其实是一个容易被忽略的事实:很多时候我们以为是"模型在决定用哪个工具",但实际上,在模型做选择之前,Agent 应用已经做了一系列决定 ------ 哪些工具能进池子、同名时谁赢、哪些工具需要额外步骤才能加载。模型的选择空间,是 Agent 应用划定好的。
二、问:工具什么时候让模型看见?
覆盖是写代码时的事。另一个问题是:工具在什么时间点暴露给模型。
三种可见性策略
Kimi Code 给出了一种最明确的回答:不是所有工具都平等可见。CLI 工具(BashTool)始终在顶层 tools[] 中,模型每一步都能直接调用。MCP 工具则被排除在顶层之外 ------ 当 toolSelectEnabled 为 true 时,模型需要先通过 <tools_added> / <tools_removed> 系统消息发现 MCP 工具的名称,再调用 select_tools 工具加载完整定义,之后才能调用(packages/agent-core/src/agent/tool/index.ts:852-905)。这被 Kimi 称为渐进式披露 ------ MCP 工具不做"插上就能用",而是"发现 → 加载 → 调用"三步走。
这种做法影响的是模型看见工具的时机。更大的主动性被交给了模型 ------ 它根据当前需求决定加载哪些工具,而不是被迫在一堆可能无关的工具定义里做选择。
两个直接效果:一是减少了上下文占用,一定程度缓解了 token 浪费;二是更重要的是,工具不再是大家经常吐槽的那种"一股脑全部暴露"的方式。
Gemini CLI 对 Skills 也做了类似的处理。它的 ActivateSkillTool(packages/core/src/tools/activate-skill.ts)要求模型在看到 available skills 列表后,调用激活工具加载 skill 完整内容,并且需要用户确认。Skills 在 Gemini CLI 里不是自动激活的。
OpenCode 代表的是最简单的情况:Skills 通过 prompt 注入、按名自动匹配,MCP 和 CLI 工具始终可用,不加任何渐进披露层。这个基线是 MiMo Code fork 的起点,下文会看到它在上面加了什么。
ClaudeCode 的做法更复杂。它的 SkillTool prompt 写了:Skill 命中时是 BLOCKING REQUIREMENT ,必须先调用 Skill 再生成其他响应(src/tools/SkillTool/prompt.ts:190)。Skills 的匹配是自动的 ------ 模型看到 skill 的 name 和 description,由 prompt 规则驱动判断,不需要像 Gemini 那样先激活。但在 MCP 这边,ClaudeCode 也有类似 Kimi Code 的机制:它有一个 ToolSearchTool(src/tools/ToolSearchTool/ToolSearchTool.ts),MCP 工具默认是 deferred (延迟加载)状态 ------ 模型只看到工具名,需要调用 ToolSearchTool 加载完整 schema 才能使用(src/tools/ToolSearchTool/prompt.ts:62-68)。MCP server 可以通过 _meta['anthropic/alwaysLoad'] 主动 opt-out。也就是说 ClaudeCode 也有 MCP 的渐进披露机制。Kimi Code 后续在 select_tools 中采用了近似的实现。
MiMo Code 的设计特例
而 MiMo Code 的做法最值得回味。我们知道标准 Skills 的运作方式本身就是渐进式披露:模型只看到 name 和 description,按需决定是否加载完整内容 ------ 这已经是第一层"不全量暴露"。但 MiMo Code fork 后添加了 SkillSearchTool(packages/opencode/src/tool/skill-search.ts),为 Skills 又加了一层门控:连 name + description 也不是直接全部给模型看的,而是先经 BM25 相关性搜索 ------ 高置信度匹配自动加载,低置信度则返回排序结果让模型选择,不匹配的直接不出现。也就是说,MiMo Code 里 Skills 做了两层渐进式披露:第一层是标准的"不暴露正文",第二层是"连目录也要先搜再给"。
但正如那几次集中讨论所展现的那样,MCP 是被吐槽占用上下文最多的能力形式,我们却没有在 MiMo Code 的代码里找到类似 Kimi Code 已经采用的 select_tools 这类实现,没有给 MCP 加任何渐进披露。我们在 MiMo Code 源码样本里可以看到,MCP 工具从连接到注入是全量"盲注" ------ 所有 server 的所有工具定义直接进入模型上下文,没有 select_tools、没有搜索、没有门控。可是已经具备渐进式披露特性的 Skills,MiMo Code 为它再加了一层门控。我们没能在 MiMo Code 官方 repo 的 Issues 或 PRs 里找到有关的信息,对这个设计取舍的原因还不得而知。
一个可能相关的解释来自代码里的一个细节:MiMo Code 的 skill search 在 Claude 和 GPT 模型上是被显式禁用的 (packages/opencode/src/skill/search.ts:24-28)。我尝试将该 Skills 渐进披露理解为一种"弱模型能力补丁" ------ 强模型不需要帮忙做技能选择,但也仅限于猜测。加上 MiMo 自家模型有 100 万 token 的上下文窗口,MCP 工具定义的 token 开销或许算不上是瓶颈。
全样本对照:
| Agent | CLI 可见性 | MCP 可见性 | Skills 可见性 |
|---|---|---|---|
| Codex | 始终立即可用 | 始终可用(支持 tool_search 按需发现) | prompt 注入,"must use" rule 自动匹配 |
| Gemini CLI | 始终立即可用 | 始终可用 | ActivateSkillTool,需手动激活 + 用户确认 |
| Kimi Code | 始终立即可用(顶层 tools\[\]) | 渐进式披露:需 select_tools 显式加载 | Skill 工具可调用 inline skill |
| MiMo Code | 始终立即可用 | 始终可用 | SkillSearchTool:BM25 搜索式渐进披露 |
| OpenCode | 始终立即可用 | 始终可用 | prompt 注入,按名自动匹配 |
| OpenClaw | 始终立即可用 | 始终可用 | prompt 自动匹配 |
| Hermes | 始终立即可用 | 始终可用 | prompt 自动匹配 |
| ClaudeCode | 始终立即可用 | 渐进式披露:MCP 工具默认 deferred,需 ToolSearchTool 加载 | BLOCKING REQUIREMENT,自动匹配 |
有意思的是,这张表里没有任何一个 Agent 在 CLI 上做渐进披露------CLI 永远是"立即可用"。是 CLI 工具本身就不需要,还是还没人想到要给 CLI 也加一层门控?
CLI 在所有 Agent 里都是"立即可用"状态 ------ 它是内置工具,不需要加载步骤。MCP 有时需要显式加载(Kimi Code),有时不需要(Codex、MiMo Code);ClaudeCode 则处于中间状态 ------ MCP 工具默认 deferred,但可通过 alwaysLoad 配置绕过。Skills 有时自动匹配(ClaudeCode、Codex),有时需要手动激活(Gemini CLI),有时通过搜索渐进披露(MiMo Code)。
三、问:Skill 能不能管工具?
前两个问题讲的是工具层内部的关系。再往上一层:Skill ------ 作为工作流描述 ------ 有没有能力约束 CLI 和 MCP 的使用。
这个问题在各 Agent 之间产生了最大的分歧。
ClaudeCode:硬授权
ClaudeCode 是目前唯一在代码层实现了"Skill 硬授权 CLI"的。它的 Skill frontmatter 支持 allowed-tools 字段(src/skills/loadSkillsDir.ts:242),Skill 作者可以声明"这个流程允许执行哪些命令"。当 Skill 被激活时,allowedTools 被注入为 alwaysAllowRules.command,预授权特定的 bash 命令模式(src/tools/SkillTool/SkillTool.ts:779-806)。这不是 prompt 建议,是权限层的硬操作。Skill 的 shell frontmatter 还可以指定用 bash 还是 powershell(src/utils/frontmatterParser.ts:339-370),虽然 skill 作者的选择不能覆盖用户的运行时开关。
Codex:声明式依赖
Codex 的 Skill 可以声明工具依赖,但不算硬约束。它的 SkillToolDependency 结构体支持 type: "cli" 和 type: "mcp" 两种依赖类型(codex-rs/skills/src/model.rs:80-92),告诉系统"这个 Skill 需要 gh CLI"或"这个 Skill 需要 GitHub MCP server"。但这更像声明关系,不强制权限。
其他 Agent:纯 prompt
Kimi Code、MiMo Code、OpenClaw、Hermes 的 Skills 是纯 prompt 机制。Skill 被注入为一段 markdown 文本(Kimi Code 的 <kimi-skill-loaded> 块、MiMo Code/OpenCode 的 skill content 渲染),能建议 模型做什么,不能阻止模型做什么。在这些 Agent 里,"Skill 管不了工具"不是设计缺陷,是当前架构的共识设定。
OpenClaw 的 AGENTS.md 把这个边界写成了显式的哲学立场:"Skills own workflows; root owns hard policy and routing"------Skill 负责工作流,但硬性策略和路由归 root(也就是 Agent 应用本身)。Skill 可以告诉模型"该怎么做",但不能替模型决定"能做哪些"。这是一种清醒的分工:流程归你,权限归我。
全样本对照:
| Agent | Skill 能否管 CLI | Skill 能否管 MCP | 机制 |
|---|---|---|---|
| Codex | 可声明依赖(type: "cli") | 可声明依赖(type: "mcp") | SkillToolDependency 声明式,非硬约束 |
| Gemini CLI | 不能 | 不能 | 纯 prompt |
| Kimi Code | 不能 | 不能 | 纯 prompt 注入(<kimi-skill-loaded>) |
| MiMo Code | 不能 | 不能 | 纯 prompt 注入 |
| OpenCode | 不能 | 不能 | 纯 prompt 注入 |
| OpenClaw | 不能 | 不能 | 纯 prompt 注入 |
| Hermes | 不能 | 不能 | 纯 prompt 注入 |
| ClaudeCode | 硬授权(allowed-tools) | 不能 | allowed-tools → alwaysAllowRules.command,权限层硬操作 |
这个分歧说明,Skill 和工具之间的关系在各 Agent 中还没有统一:有人让 Skill 拥有权限层的硬约束力,有人只让它做 prompt 层面的建议。这条线往哪里走,可能是接下来最值得关注的分化点。
四、问:有没有显式的设计框架?
前三个问题看的是代码行为。最后一个问题看的是设计自觉 ------ 有没有 Agent 把 CLI、MCP、Skills 之间的取舍逻辑写成显式的规则,而不是让它从代码里"自然长出来"。
大部分 Agent 没有。但有两个做了,而且方式不同。
Hermes:Footprint Ladder
Hermes 的 AGENTS.md 里有一个"Footprint Ladder"(足迹阶梯,第 182-206 行),按"新增永久表面积"从小到大排列所有能力扩展方式。这里的"表面积"是软件维护的概念 ------ 每新增一个工具、一个 API、一条代码路径,就多了一块需要持续维护测试安全审计的面积。阶梯越往上,引入的"表面积"越小:
- 扩展现有代码 ------ 零新增表面积
- CLI command + skill ------ Agent 执行
hermes <subcommand>,由 skill 提供流程指导。零模型工具表面积。这是订阅任务、定时任务、服务设置的默认选择 - Service-gated tool ------ 需要结构化参数但仅在前提条件满足时出现
- Plugin ------ 第三方能力,不进 core
- MCP server ------ 如果能力确实需要成为工具(结构化 I/O),但不核心,优先做成 MCP server 而非新增 core tool
- New core tool ------ 最后手段
CLI+skill 在第二级,MCP server 在第五级。这个排序不是基于"谁更好" ------ Footprint Ladder 的唯一标准是新增表面积。Hermes 明确说:"选择最高(表面积最小)的可行阶梯。"
通俗地讲:能用 CLI 和 skill 解决的事,不用 MCP;能用别人写的 MCP server 解决的事,不自己写 core tool。
OpenClaw:结构性职责划分
OpenClaw 没有 Hermes 那么细的阶梯,但给了一个简洁的结构性描述:AGENTS.md 开头第一句就是"Skills own workflows; root owns hard policy and routing"(Skills 拥有工作流,root 拥有硬策略和路由)。三层关系一目了然 ------ Skills 管怎么做,Agent 管怎么排,工具(不管是 CLI 还是 MCP)是被编排的。
这两个通用型 Agent 的框架,跟前面 Coding Agent 的代码实现指向同一个方向:三者不是平级竞争关系。CLI 直接干活,MCP 接外部系统,Skills 管理流程。 区别在于,Hermes 和 OpenClaw 把这件事写成了可以指导后续开发的显式规则,而其他 Agent 是让代码行为自然形成分层 ------ 有效果,但少了一份"我们想清楚了"的自觉。
全样本对照:
| Agent | 是否有显式设计规则 | 说明 |
|---|---|---|
| Codex | 无 | 代码行为上有 skill instructions 先于工具调用的顺序,但未写成设计文档 |
| Gemini CLI | 无 | ActivateSkillTool 需手动激活,但无关于"为什么"的规则说明 |
| Kimi Code | 无 | 渐进式披露由代码实现,changelog 有动机记录但未形成持久的设计框架 |
| MiMo Code | 无 | SkillSearchTool 的 BM25 选择有官方博客说明,但未形成通用规则 |
| OpenCode | 无 | --- |
| OpenClaw | 有 | "Skills own workflows; root owns hard policy and routing",定义了架构层职责划分 |
| Hermes | 有 | Footprint Ladder 六级阶梯,定义了所有能力扩展方式的取舍标准和优先级 |
| ClaudeCode | 隐式完整 | BLOCKING + allowed-tools + builtin 优先形成完整行为链,但未写成设计文档 |
五、ClaudeCode:把事情串起来的样本
看完各 Agent 在一两个子问题上的处理,可以发现 ClaudeCode 的特别之处在于它在四个子问题上都有独特的设计:
工具冲突 :assembleToolPool 里 built-in 优先于 MCP,CLI 显然权重高于 MCP 的。
可见性 :Skill 命中是 BLOCKING REQUIREMENT,必须先加载 Skill,再决定用什么工具。同时 MCP 工具默认 deferred,需通过 ToolSearchTool 加载 schema 后才能调用 ------ Kimi Code 后续也在 select_tools 中采用了近似实现。MCP server 还可以通过 _meta['anthropic/alwaysLoad'] 让特定工具跳过 deferred,直接暴露完整 schema(src/services/mcp/client.ts:1785)------ 这相当于一个配置层面的门控开关。
Skill 管工具 :allowed-tools 字段让 Skill 可以硬授权 CLI 命令 ------ 全样本唯一的硬约束。
完整设计 :MCP server 可以提供 Skill(通过 skill:// resources),但 MCP Skill 被标记为不可信 ------ 不执行 inline shell command(src/skills/loadSkillsDir.ts:371-374),本地 Skill 优先于同名 MCP Skill(SkillTool.ts:82-93 的 uniqBy([...localCommands, ...mcpSkills], 'name'))。也就是说,MCP 可以是 Skill 的分发渠道,但 Agent 保留最终控制权。
ClaudeCode 不是每一项都做得最激进,但它是把 CLI、MCP、Skills 三层之间的硬交互做得最全面的。这可能跟它作为早期版本有关 ------ 实验更多,规矩少一些。但不管原因是什么,它提供了一个很完整的参考样板。
需要说明的是,本文分析的 ClaudeCode 代码来自 2026 年 3 月的泄露版本(a99de1b)。ClaudeCode 不开源,后续版本可能已经调整了上述设计 ------ 比如 ToolSearchTool 的触发条件、MCP deferred 的默认行为等,都有可能发生变化。以上分析仅反映该版本的状态。
六、从源码看到的
四个子问题看完,呈现的图景不复杂。
没有任何一个 Agent 实现了一个硬编码的 cli > mcp > skill 优先级数值。各 Agent 的分层机制 ------ 工具注册顺序、渐进式披露、权限规则、prompt 约束 ------ 加在一起形成的是一个结构性分层:
| 层 | 职责 | 各 Agent 的实现方式 |
|---|---|---|
| Skills | 工作流路由:匹配任务、决定流程、授权工具 | ClaudeCode 的 BLOCKING REQUIREMENT;Codex 的 "must use" rule;OpenClaw 的 "Skills own workflows";MiMo Code 的 BM25 搜索式渐进披露 |
| CLI | 系统执行:直接跑命令、操作本地环境 | 所有 Agent 的内置工具,同名时优先于 MCP,始终立即可用 |
| MCP | 外部连接:调 API、查数据库、访问 SaaS | 有序加载(Kimi Code select_tools、ClaudeCode ToolSearchTool),统一注册(Codex),独立治理(Hermes MCP catalog) |
| Agent 应用 | 治理:信任、权限、优先级、审计 | Hermes Footprint Ladder、OpenClaw 的策略路由、ClaudeCode 的 allowed-tools + skill:// 安全边界 |
更简洁地说:CLI 负责跑命令,MCP 负责接系统,Skills 负责编排两者,Agent 应用决定边界。
七、日常使用的参考
从源码分析回到日常使用,下面这张表可以作为参考:
| 你想让 Agent 做什么 | 参考方向 | 例子 |
|---|---|---|
| 执行本地命令、管理文件、操作 git | CLI | git commit、npm install、ls |
| 访问外部系统或 SaaS | MCP | 连接 GitHub API、Notion、Linear、数据库 |
| 按固定流程重复做事 | Skills | 代码审查流程、周报格式、发布 checklist |
| 用外部系统完成稳定流程 | MCP + Skill | GitHub MCP 读 PR,Code Review Skill 定义审查流程 |
| 用本地命令完成稳定流程 | CLI + Skill | gh CLI 操作 GitHub,Skill 定义审查步骤和授权命令 |
MCP server 装得多并不等于 Agent 能力强 ------ Hermes 的 Footprint Ladder 从维护表面积的角度解释了这一点,每增加一个工具都是模型决策负担的增加。但从另一个角度看,确实需要 MCP 的场景(权限治理、结构化 I/O、跨平台复用),CLI 也代替不了。
一个具体案例:Playwright 的三种形态
Playwright 算是典型的同一个产品同时提供 CLI、MCP、Skills 三种扩展形态的案例(截至 2026 年 7 月,@playwright/mcp v0.0.75 / Playwright 1.60)。三种形态是独立安装的,不是打包在一起:
- MCP (
npx @playwright/mcp@latest):50+ 工具,通过结构化无障碍树操作浏览器,单次会话约消耗 114K tokens - CLI (
npm install -g @playwright/cli):命令行工具,单次会话约消耗 27K tokens ------ 比 MCP 少约 4 倍 - Skills (
playwright-cli install --skills):安装 markdown 技能文件,教 Agent 怎么用 CLI 命令 ------ 专门跟 CLI 配对,不跟 MCP 配对
面对"打开网页并截图"这样一个任务,如果只装了 MCP,Agent 走 MCP 工具(browser_navigate + browser_screenshot);如果装了 CLI + Skills,Agent 读取技能后走 CLI 命令(playwright-cli open + playwright-cli screenshot);如果两种都装了,Agent 自己判断 ------ Playwright 官方的建议是"CLI 适合需要 token 效率的编码 Agent,MCP 适合需要持续状态和迭代推理的自动化流程"。甚至从 Playwright 1.59 起,MCP 和 CLI 可以通过 browser.bind() 共享同一个浏览器实例。
这个案例说明的不是"哪种更好",而是同一个产品可以同时提供三种形态,由 Agent 和用户根据场景选择。三层不是非此即彼。
八、对开发者
对开发者来说,选择 CLI、MCP 还是 Skills,涉及的维度更多 ------ 能力粒度、维护成本、权限模型、信任链路、命名空间、跨 Agent 可移植性。一个相关的问题是 Plugin:ClaudeCode、Kimi Code、Codex 的 Plugin 系统可以把 Skills、MCP servers、Hooks 打包在一个 manifest 里安装,但安装之后每种能力各自走 Agent 原有的加载通道,Plugin 本身不运行代码 ------ 它是包装盒,不是执行器。OpenClaw 是个例外,它的原生 Plugin 会执行自己的 register(api) 代码来动态注册能力。文章已经很长了,这些留到之后另开一篇。
九、写在最后
AI 把一切都加速了,包括这些能力形式本身的演进。我们没有展开的地方也还很多 ------ 开发者视角下 CLI/MCP/Skills 的技术选型、MCP 协议即将到来的重构对 Agent 设计的影响、插件(Plugin)体系如何在三种扩展能力之上再加一层编排。我们在 ClaudeCode 里已经看到 MCP server 可以提供 Skills ------ 三层之间的边界本身就在变化。
不知道你在具体使用哪些 Agent,是否发现跟上文分析一致或不一致的地方,我们可以一起聊聊。