1. 从“skills”这个标题说起:它到底指什么
第一次看到“skills”这个标题,很多人会以为是某个泛泛而谈的能力清单,或者一份简历上的技能罗列。但结合热搜词里的 Agent Skills、Google Cloud、npx、GKE、claude agent skills、codex skills 这些词来看,这里的 skills 显然不是指人类的能力,而是指AI Agent 生态里的一种可插拔能力单元。简单说,它是一套让 AI 助手从“只会聊天”变成“能干活”的机制。
我最早接触这个概念是在折腾 Claude 的 Agent 能力时。当时我一直在想一个问题:大模型本身很聪明,但它不知道我公司的代码规范,不知道我常用的部署流程,也不知道我那个内部系统的接口长什么样。每次对话都要重新解释一遍,效率极低。skills 就是来解决这个问题的——它把特定领域的知识、操作流程、工具调用方式打包成一个可复用的模块,Agent 在需要的时候自动加载,用完即走。
这套东西能做什么?举几个我实际用过的场景。第一,让 Agent 按照我团队的代码风格写代码,包括命名习惯、注释格式、错误处理方式。第二,让 Agent 自动执行一套部署检查清单,从构建到测试到发布,每一步都有明确的判断标准。第三,让 Agent 在写论文时自动调用文献检索、格式校对、引用管理这些能力。这些都不是靠一句 prompt 能稳定实现的,而是需要结构化的 skill 定义。
适合谁来参考?如果你是前端开发者,想让自己用的 AI 编程助手更懂你的项目;如果你是 DevOps 工程师,想让 Agent 帮你处理 GKE 集群的日常运维;如果你是研究者,想让 AI 辅助论文写作;甚至如果你只是想让 AI 帮你做分镜脚本、自动挖洞测试,skills 这套机制都值得花时间研究。它不是什么高深的技术,核心思想就是“把重复性的专业操作封装成 Agent 能理解的标准模块”。
我踩过的第一个坑就是把它想复杂了。一开始我以为要写很多代码,要理解复杂的协议。实际上,一个最基础的 skill 就是一个文件夹,里面放一个说明文件,告诉 Agent 这个 skill 是干什么的、什么时候用、怎么用。就这么简单。当然,要做到生产可用,还需要考虑版本管理、依赖处理、错误恢复这些工程问题,但入门门槛比想象中低很多。
2. Agent Skills 的核心设计思路拆解
2.1 为什么需要 Skills 而不是纯 Prompt
纯 Prompt 的问题在于“一次性”。你这次对话里告诉 Agent 要遵守某些规则,下次开新对话它就忘了。而且 Prompt 越长,模型的注意力越分散,关键信息容易被淹没。我做过一个测试,把一份 2000 字的代码规范直接塞进系统提示词,Agent 在前几轮还能遵守,到后面就开始自由发挥了。这不是模型不听话,而是长上下文里的信息衰减是客观存在的。
Skills 的思路完全不同。它把知识分成“常驻”和“按需加载”两部分。常驻部分只保留最核心的索引信息,比如“有一个叫 code-review 的 skill,用于代码审查”。当 Agent 判断当前任务需要代码审查时,才去加载完整的 skill 内容。这样既保证了知识的完整性,又避免了上下文污染。这个设计思路借鉴了操作系统的虚拟内存机制——不是所有东西都塞进内存,而是按需换页。
另一个关键考量是可组合性。一个复杂的任务往往需要多个 skill 协同。比如“部署一个新服务”这个任务,可能涉及代码检查 skill、容器构建 skill、Kubernetes 配置 skill、监控告警 skill。如果每个 skill 都是独立定义的,Agent 就能像搭积木一样把它们串起来。这种组合能力是纯 Prompt 很难做到的,因为 Prompt 里的指令是扁平的,没有明确的边界和接口。
2.2 Skills 的目录结构与元数据设计
一个标准的 skill 目录通常长这样:
my-skill/ ├── SKILL.md # 核心说明文件 ├── scripts/ # 可执行脚本 │ ├── setup.sh │ └── validate.py ├── references/ # 参考文档 │ └── api-spec.md └── assets/ # 静态资源 └── template.yamlSKILL.md是整个 skill 的入口,它需要回答三个问题:这个 skill 解决什么问题、什么时候触发、具体怎么执行。我见过很多人把 SKILL.md 写成技术文档,堆满了实现细节,结果 Agent 反而不知道什么时候该用它。正确的做法是面向触发场景写说明,而不是面向实现写文档。
元数据部分通常包括 name、description、version、author 这些基础字段。但真正影响 Agent 行为的是 description 的写法。我试过两种写法:一种是“这个 skill 用于处理 Kubernetes 部署”,另一种是“当用户需要将容器化应用发布到 GKE 集群,或者需要排查 Pod 启动失败问题时,使用这个 skill”。实测下来,第二种写法的触发准确率高出一大截。原因很简单,Agent 是根据语义匹配来决定是否加载 skill 的,描述里包含的场景越具体,匹配越精准。
2.3 触发机制与加载策略
Skills 的触发有两种模式:自动触发和显式调用。自动触发依赖 Agent 对当前任务的理解,它会扫描所有已注册 skill 的 description,找到最匹配的那个。显式调用则是用户在对话里直接说“用 xxx skill 来做这件事”。
自动触发的难点在于误触发和漏触发。我遇到过 Agent 在一个简单的文件重命名任务里,莫名其妙加载了一个复杂的部署 skill,原因就是那个 skill 的 description 里写了“文件操作”这个宽泛的词。后来我把 description 改得更具体,误触发就消失了。漏触发通常是因为 skill 的描述和用户的实际表述之间存在语义鸿沟。比如用户说“帮我把这个服务上线”,而 skill 描述里写的是“Kubernetes 部署”,Agent 可能匹配不上。解决办法是在 description 里补充同义词和常见表述。
加载策略上,我建议把 skill 分成三层:核心层是每次对话都加载的轻量索引,只包含 skill 名称和一句话描述;领域层是按项目或任务类型加载的,比如前端项目加载前端相关的 skill 集合;任务层是具体执行时才加载的完整 skill 内容。这种分层策略能有效控制上下文长度,同时保证 Agent 在需要时能拿到足够的信息。
3. 从零搭建一个可用的 Skill:实操全流程
3.1 环境准备与工具链选择
搭建 skill 不需要复杂的开发环境,但有几个工具能大幅提升效率。首先是npx,它是 Node.js 生态里的包执行器,很多 skill 相关的工具都通过 npx 分发。比如npx playwright install就是安装浏览器自动化依赖的常用命令。不过这个命令在国内网络环境下经常失败,我后面会专门讲排查方法。
其次是Google Cloud CLI,如果你的 skill 涉及 GKE 操作,gcloud 命令是绕不开的。安装完成后需要执行gcloud init做初始化配置,包括选择项目、设置默认区域、配置认证。这一步的坑在于认证方式的选择,我建议用服务账号密钥而不是个人账号授权,因为服务账号的权限更可控,也方便在 CI/CD 环境里复用。
代码编辑器方面,VS Code 加上 Markdown 预览插件就够用了。SKILL.md 本质上是 Markdown 文件,但它的结构比普通文档更严格,需要遵循特定的 frontmatter 格式。我习惯在 VS Code 里配置一个 snippet,输入skill就自动生成模板,省去每次手写 frontmatter 的麻烦。
提示:如果你在安装 npx 相关工具时遇到网络超时,可以先检查 npm 的 registry 配置。国内用户通常需要切换到镜像源,但具体用哪个源要根据你所在网络环境实测,没有万能方案。
3.2 编写第一个 SKILL.md:从模板到落地
我拿一个实际用过的例子来说明。假设我要做一个“GKE 部署检查”的 skill,用于在部署前自动检查 Kubernetes 配置文件的常见问题。SKILL.md 的内容大致如下:
--- name: gke-deploy-check description: 当用户需要将应用部署到 GKE 集群,或者需要检查 Kubernetes YAML 配置的合规性时使用。适用于 Deployment、Service、Ingress 等资源的部署前检查。 version: 1.0.0 author: your-name --- # GKE 部署检查 ## 何时使用 - 用户提到“部署到 GKE”“发布到 Kubernetes”“检查 YAML” - 用户提供了 Kubernetes 资源文件需要审查 - 部署失败后需要排查配置问题 ## 检查清单 1. 资源限制:每个容器是否设置了 requests 和 limits 2. 健康检查:是否配置了 livenessProbe 和 readinessProbe 3. 镜像标签:是否使用了 latest 标签(禁止) 4. 命名空间:是否明确指定了 namespace 5. 标签规范:是否包含 app、env、version 三个标准标签 ## 执行步骤 1. 读取用户提供的 YAML 文件 2. 逐项对照检查清单 3. 输出问题列表,按严重程度排序 4. 对每个问题给出修复建议和示例代码 ## 参考 - 内部规范文档:references/k8s-standard.md - 检查脚本:scripts/validate.py这个模板的关键在于检查清单要具体可执行。我见过很多 skill 写的是“检查配置是否合理”,这种描述 Agent 没法执行,因为“合理”没有标准。必须拆解成“是否设置了 requests 和 limits”这种二元判断,Agent 才能给出确定的结果。
3.3 脚本与工具的集成方式
Skill 里的脚本不是必须的,但涉及复杂操作时,脚本能大幅提升可靠性。比如上面例子里的validate.py,它做的事情就是解析 YAML 文件,按照检查清单逐项验证,输出结构化的结果。Agent 只需要调用这个脚本,然后解读输出即可。
脚本集成的关键是输入输出格式要固定。我习惯让脚本接受文件路径作为参数,输出 JSON 格式的结果。这样 Agent 不需要理解脚本内部逻辑,只需要知道怎么传参、怎么解析返回。这种设计也方便单独测试脚本,不用每次都通过 Agent 来验证。
# scripts/validate.py 的核心逻辑 import sys import json import yaml def check_resources(doc): issues = [] for container in doc.get('spec', {}).get('template', {}).get('spec', {}).get('containers', []): if 'resources' not in container: issues.append({ 'severity': 'high', 'message': f"容器 {container['name']} 未设置资源限制", 'fix': "添加 resources.requests 和 resources.limits" }) return issues if __name__ == '__main__': with open(sys.argv[1]) as f: docs = yaml.safe_load_all(f) all_issues = [] for doc in docs: if doc and doc.get('kind') == 'Deployment': all_issues.extend(check_resources(doc)) print(json.dumps(all_issues, ensure_ascii=False))这个脚本的写法很朴素,但实用。它不依赖任何外部服务,输入输出都是标准格式,Agent 调用起来没有歧义。我建议每个 skill 的脚本都遵循这个模式:单一职责、标准输入输出、无副作用。
3.4 本地测试与调试方法
写完 skill 后,不要急着注册到 Agent 里。先在本地做单元测试。我的做法是准备一组测试用例,包括正常配置、各种异常配置、边界情况。然后直接运行脚本,检查输出是否符合预期。这一步能发现大部分逻辑错误。
Agent 层面的测试更复杂一些。我通常会在对话里模拟真实场景,观察 Agent 是否在正确的时机加载了 skill,加载后是否按照 SKILL.md 的步骤执行。这里有个技巧:在 SKILL.md 里加入调试输出,比如“执行到第 3 步时输出当前检查结果”。这样你能清楚地看到 Agent 的执行路径,判断它是在哪一步偏离了预期。
调试过程中最常见的问题是Agent 跳步。比如检查清单有 5 项,它只执行了 3 项就给出结论。原因通常是 SKILL.md 的步骤描述不够强制。后来我在每一步前面加了“必须”“禁止跳过”这样的词,跳步问题明显减少。另一个技巧是把检查清单做成表格,Agent 对表格结构的遵循度比纯文本列表更高。
4. 常见问题与排查技巧实录
4.1 npx playwright install 失败的排查思路
这个问题在热搜里出现频率很高,我自己也遇到过多次。npx playwright install失败通常有三个原因:网络超时、权限不足、版本冲突。排查顺序建议从网络开始。
先执行npx playwright install --dry-run,看看它实际要下载什么。如果卡在下载阶段,基本就是网络问题。Playwright 的浏览器二进制文件体积很大,国内直连经常超时。解决办法是设置PLAYWRIGHT_DOWNLOAD_HOST环境变量指向可用的镜像源,或者手动下载后放到缓存目录。缓存目录的位置可以用npx playwright install --help查看,通常在用户目录下的.cache/ms-playwright。
权限问题多出现在 Linux 环境,特别是用 root 安装后切换普通用户运行时。表现是“无法写入缓存目录”或“浏览器启动失败”。解决办法是确保缓存目录的属主和运行用户一致,或者用--with-deps参数让安装程序自动处理系统依赖。
版本冲突的典型表现是“找不到匹配的浏览器版本”。这通常是因为 package.json 里的 playwright 版本和已安装的浏览器版本不一致。执行npx playwright install时会自动安装匹配版本,但如果之前手动装过其他版本,可能会冲突。清理缓存后重新安装通常能解决。
| 故障现象 | 可能原因 | 排查命令 | 解决方向 |
|---|---|---|---|
| 下载卡住不动 | 网络超时 | npx playwright install --dry-run | 配置镜像源或手动下载 |
| 权限拒绝 | 缓存目录属主错误 | ls -la ~/.cache/ms-playwright | 修正目录权限 |
| 版本不匹配 | 多版本共存 | npx playwright --version | 清理缓存后重装 |
| 依赖缺失 | 系统库不全 | npx playwright install-deps | 安装系统依赖 |
4.2 Skill 不触发或误触发的调整方法
Skill 不触发是最让人头疼的问题。你明明写了 skill,Agent 就是不用。排查的第一步是检查 description 的语义匹配度。把用户可能说的各种表述列出来,看看和 description 里的关键词有没有重叠。如果没有,就需要补充同义词。
我遇到过一个典型案例:一个用于“数据库迁移”的 skill,用户说“帮我改表结构”时从来不触发。后来在 description 里加了“修改表结构、添加字段、调整索引”这些表述,触发率立刻上来了。这说明 Agent 的语义匹配是基于词汇重叠的,描述里覆盖的场景词越多,匹配概率越高。
误触发则相反,通常是 description 太宽泛。比如一个“代码审查”skill,如果 description 里写了“检查代码”,那用户说“帮我看看这段代码什么意思”时也会触发,但这明显不是审查场景。解决办法是加入排除条件,比如“仅在用户要求检查代码质量、发现潜在 bug、审查合并请求时使用,不适用于代码解释和教学场景”。
还有一个隐藏问题是skill 之间的优先级冲突。当多个 skill 的 description 都匹配当前任务时,Agent 需要决定加载哪个。我建议在 skill 的元数据里加一个 priority 字段,数值越高优先级越高。或者在 description 里明确写出“当同时满足 A 和 B 条件时,优先使用本 skill”。
4.3 跨平台兼容性与依赖管理
Skills 在不同 Agent 平台上的行为可能有差异。我测试过 Claude 的 Agent Skills 和 Codex 的 skills 机制,核心思路一致,但细节上有区别。比如 Claude 对 SKILL.md 的 frontmatter 格式要求更严格,Codex 则更灵活。如果你要写一个跨平台通用的 skill,建议把平台相关的配置抽离出来,放在单独的配置文件里。
依赖管理是另一个坑。Skill 里用到的脚本可能依赖特定的 Python 包或系统工具。如果目标环境没有这些依赖,skill 就会执行失败。我的做法是在 SKILL.md 里明确列出依赖项,并在脚本开头做依赖检查。如果依赖缺失,脚本输出明确的错误信息,Agent 就能告诉用户需要安装什么。
# 依赖检查示例 import shutil import sys required = ['kubectl', 'gcloud'] missing = [cmd for cmd in required if not shutil.which(cmd)] if missing: print(f"缺少依赖: {', '.join(missing)}", file=sys.stderr) sys.exit(1)这种防御性编程看起来多余,但在实际使用中能省去大量排查时间。Agent 拿到明确的错误信息后,可以自动尝试安装依赖,或者至少能给用户一个清晰的提示,而不是抛出一堆看不懂的堆栈信息。
4.4 版本更新与回滚策略
Skill 不是写完就一劳永逸的。业务规则会变,工具接口会变,Agent 平台本身也在迭代。我建议给每个 skill 建立版本管理机制,用语义化版本号(major.minor.patch)。当 skill 的行为发生不兼容变化时,递增 major 版本;新增功能时递增 minor;修复 bug 时递增 patch。
回滚策略同样重要。我遇到过新版本 skill 上线后导致 Agent 行为异常的情况,这时候需要快速回退到上一个稳定版本。做法很简单:保留最近三个版本的 skill 目录,在注册时通过配置指定使用哪个版本。如果新版本出问题,改一行配置就能回滚,不用重新部署。
注意:skill 的版本更新不要频繁。每次更新都会改变 Agent 的行为,频繁变更会让使用者难以建立稳定的预期。我通常攒一批改进后统一发版,而不是发现一个小问题就立刻更新。
5. 进阶玩法:让 Skills 组合出更强能力
5.1 多 Skill 协同的工作流设计
单个 skill 能解决的问题有限,真正强大的是多个 skill 的组合。我设计过一个“前端项目发布”工作流,涉及四个 skill:代码检查、构建打包、部署到 GKE、发布后验证。每个 skill 独立定义,但通过一个工作流描述文件串联起来。
工作流描述文件的核心是定义执行顺序和条件分支。比如“代码检查通过后才执行构建”“构建产物存在才执行部署”“部署成功后自动触发验证”。这些条件判断不需要写在每个 skill 里,而是由工作流层统一管理。这样每个 skill 保持单一职责,组合逻辑集中在一处,维护起来清晰很多。
实际运行时,Agent 会先加载工作流描述,然后按顺序加载和执行各个 skill。如果某个环节失败,Agent 会根据工作流定义决定是重试、跳过还是终止。这种设计让复杂任务的自动化成为可能,而且每个环节都可以单独测试和替换。
5.2 从个人使用到团队共享
个人用的 skill 和团队共享的 skill 是两回事。个人用时,你可以容忍一些模糊的描述和不完整的文档。但团队共享时,每个 skill 都需要有明确的负责人、使用说明、变更记录。我建议在团队内部建立一个 skill 仓库,用 Git 管理,每个 skill 一个目录,通过 Pull Request 来变更。
团队共享的另一个问题是权限控制。不是所有 skill 都适合所有人使用。比如涉及生产环境操作的 skill,应该限制只有特定角色才能触发。实现方式可以在 skill 的元数据里加一个required_role字段,Agent 在加载前检查当前用户的角色是否匹配。这个机制需要 Agent 平台的支持,如果平台不支持,可以在 skill 脚本里做二次校验。
文档也很关键。我见过太多团队把 skill 写完后就不管了,新人来了完全不知道有哪些 skill 可用、怎么用。我的做法是维护一个自动生成的 skill 索引,从每个 SKILL.md 的 frontmatter 里提取 name、description、version,生成一个总览页面。每次 skill 更新时自动刷新,保证索引和实际内容一致。
5.3 性能优化:减少加载延迟与 Token 消耗
Skill 加载是有成本的,主要体现在 Token 消耗上。一个完整的 SKILL.md 可能有两三千字,加载多个 skill 后上下文会迅速膨胀。优化方向有两个:压缩 skill 内容和按需加载。
压缩方面,我习惯把详细的参考文档放在references/目录,SKILL.md 里只保留核心流程和触发条件。Agent 在执行过程中如果需要更详细的信息,再去读取参考文档。这样常驻上下文里的内容很少,只有真正执行时才加载完整信息。
按需加载方面,可以利用 Agent 平台的懒加载机制。有些平台支持在 skill 里定义“依赖 skill”,只有当主 skill 被触发时,才去加载依赖 skill。这种链式加载能有效控制初始上下文长度。我实测下来,一个包含五个 skill 的工作流,用懒加载后初始 Token 消耗降低了约 60%。
另一个技巧是缓存执行结果。如果某个 skill 的输出是确定性的,比如代码格式检查,可以在本地缓存结果,避免重复执行。Agent 在调用前先检查缓存,命中则直接返回。这个机制需要 skill 脚本自己实现,但实现起来不复杂,对性能提升很明显。
6. 我踩过的坑与实操心得
6.1 描述写得太“技术”反而不好用
刚开始写 skill 时,我习惯用技术术语描述,比如“本 skill 实现基于 AST 的代码静态分析”。结果 Agent 根本不知道什么时候该用它。后来我改成“当用户需要检查代码中的潜在错误、不规范写法、安全隐患时使用”,触发率立刻上来了。Agent 不是编译器,它不理解 AST 是什么,但它理解“检查代码错误”这个场景。
这个教训让我意识到,skill 的描述是写给 Agent 看的,不是写给人类开发者看的。要用 Agent 能理解的语义,而不是技术实现的术语。现在我写 description 时,会先想“用户在什么场景下会说哪些话”,然后把这些话的关键词提炼出来放进描述里。
6.2 脚本不要写得太“聪明”
我写过一个自动修复 Kubernetes 配置的脚本,它会根据检查结果自动修改 YAML 文件。想法很好,但实际用起来问题很多。有时候修复建议是错的,有时候修改后引入了新问题。最麻烦的是,Agent 看到脚本返回“修复成功”就认为任务完成了,但实际上修复结果需要人工确认。
后来我把脚本改成只做检查、不做修改。检查结果输出给 Agent,由 Agent 决定是否修改、怎么修改。这样虽然多了一步交互,但可靠性高了很多。脚本的职责是提供确定性的信息,而不是替 Agent 做决策。这个边界划清楚后,skill 的稳定性明显提升。
6.3 不要试图用一个 skill 解决所有问题
我见过一个“万能 skill”,试图覆盖代码审查、部署、监控、告警所有场景。结果就是每个场景都做不好,description 写得含糊不清,Agent 经常误触发。后来我把它拆成四个独立 skill,每个只做一件事,反而都好用了。
Skill 的设计哲学应该是单一职责。一个 skill 只解决一类问题,描述清晰,边界明确。需要组合时,通过工作流来串联,而不是把所有逻辑塞进一个 skill 里。这样每个 skill 都容易测试、容易维护、容易复用。
6.4 测试用例要覆盖“不该触发”的场景
大多数人写测试时只关注“该触发时是否触发”,忽略了“不该触发时是否误触发”。我吃过这个亏:一个部署 skill 在用户只是询问部署概念时被触发了,然后 Agent 开始执行检查流程,用户一脸懵。
后来我在测试用例里专门加了一组“负面用例”:询问概念、讨论方案、查看文档这些场景,验证 skill 不会被误触发。这组用例帮我发现了多个 description 过于宽泛的问题。现在我的测试清单里,负面用例和正面用例的数量基本是 1:1。
6.5 文档更新要及时,但不要频繁发版
Skill 的文档和实现不一致是常见问题。我遇到过 SKILL.md 里写的检查项和脚本实际执行的检查项对不上,导致 Agent 的输出和预期不符。解决办法是把文档更新纳入发版流程,每次改脚本必须同步改文档,否则不允许合并。
但发版频率要控制。我一开始每改一个错别字就发一个版本,结果版本号涨得飞快,使用者根本跟不上。后来改成按批次发版,攒够一批改进后统一更新版本号,并在变更记录里写清楚每个版本改了什么。这样使用者能清楚地知道每个版本的变化,升级时也有据可依。
6.6 国内环境下的特殊处理
国内网络环境对 skill 的影响主要体现在依赖下载和外部服务调用上。除了前面提到的 npx 镜像配置,Google Cloud 相关操作也可能遇到连接问题。我的做法是在 skill 里加入超时和重试逻辑,并给出明确的错误提示,而不是让 Agent 卡在那里。
另一个问题是时区和编码。涉及时间处理的 skill 要明确指定时区,避免因为时区差异导致逻辑错误。编码方面,所有脚本统一用 UTF-8,并在文件头声明编码格式。这些细节看起来小,但在跨环境使用时经常出问题。
7. 这个方向后续还能怎么扩展
Skills 这套机制目前还在快速演进中。我观察到几个值得关注的方向。一是skill 的市场化,已经有一些平台在尝试做 skill 的分享和交易,类似手机应用商店的模式。二是skill 的自动生成,通过分析用户的对话历史,自动提取重复性的操作模式,生成对应的 skill 草稿。三是skill 的跨平台标准化,不同 Agent 平台之间的 skill 格式如果能统一,开发者的迁移成本会大幅降低。
从个人实践角度,我接下来想尝试的是把 skill 和 CI/CD 流水线更深度地结合。目前 skill 主要是在对话中触发,如果能让它在代码提交、合并请求、定时任务这些场景自动执行,价值会更大。另一个方向是做 skill 的效果度量,记录每个 skill 的触发次数、执行成功率、用户反馈,用数据来驱动 skill 的优化。
如果你刚开始接触这个领域,我的建议是从一个小场景入手,写一个最简单的 skill,跑通完整流程。不要一上来就追求大而全,先把一个点做透,理解背后的机制,再逐步扩展。我最初就是从“检查 YAML 文件里的镜像标签”这一个检查项开始的,后来慢慢扩展成完整的部署检查 skill。这个过程踩的坑、积累的经验,比直接看文档要深刻得多。