ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

agent-skills:可复用CLI技能的声明式设计与工程实践

agent-skills:可复用CLI技能的声明式设计与工程实践

1. 项目概述:什么是 agent-skills?它不是玩具,而是开发者工作流的“肌肉记忆加速器”

“agent-skills”这个词最近在前端、AI工程和CLI工具圈里反复刷屏,但它既不是某个新出的框架,也不是某家大厂刚发布的闭源产品——它是一类可复用、可组合、可声明式调用的原子化能力单元。简单说,就像你手机里装的微信、地图、相机这些独立App,但它们不跑在图形界面上,而是跑在命令行里、跑在AI Agent的决策链路中、跑在自动化脚本的底层逻辑里。你敲npx skills list,它返回一串可用技能;你写npx skills git commit --message="feat: add auth middleware",它就自动执行 git 提交;你配置claude agent skills: a first principles deep dive这样的提示词,背后调用的正是经过标准化封装的git,curl,playwright,docker等真实 CLI 工具能力。它解决的核心问题非常朴素:让开发者不再重复写 shell 脚本、不再手敲 8 行 curl 命令查 API、不再为每个新项目重写一遍“读取 env → 校验 token → 发请求 → 解析 JSON → 输出表格”的胶水代码。

我从 2021 年开始在团队内部推动 CLI 工具链标准化,最早是用yarn create封装项目模板,后来用oclif写过一整套 DevOps 指令集,直到去年看到 Codex CLI 和 Zcode CLI 的设计思路才真正意识到:我们缺的不是更多命令,而是一套能让命令“自我描述、自我注册、自我发现”的基础设施。agent-skills 正是这个基础设施的实践出口——它把git status变成一个可被 AI 理解的skills.git.status()函数,把npx playwright install变成一个带依赖图谱和失败回退策略的skills.playwright.install()方法。它不替代 npm 或 yarn,但让npx从“临时跑个包”升级为“按需加载能力”。对新手,它是降低 CLI 使用门槛的阶梯;对资深工程师,它是把十年经验沉淀为可移植、可审计、可版本化的技能资产。你不需要懂 LLM 推理,也能用skills find --category=testing找到最适合当前项目的 E2E 测试工具链;你不需要会写 TypeScript 类型定义,也能通过skills compact --input=package.json自动生成精简版依赖清单。它不是魔法,是把“人怎么干活”这件事,用机器可读的方式重新刻录了一遍。

2. 整体设计与思路拆解:为什么 agent-skills 必须是“轻注册、重契约、零侵入”?

agent-skills 的设计哲学,本质上是对过去十年 CLI 工具生态痛点的一次系统性回应。我们先看三个典型失败场景:第一种是“全家桶式 CLI”,比如早期的create-react-app,它把 webpack、babel、eslint 全打包进一个二进制,结果升级困难、定制受限、调试黑盒;第二种是“插件地狱”,像某些 IDE 的 CLI 扩展,每个插件都要自己处理命令冲突、参数解析、错误格式化,最终用户面对的是--verbose --debug --trace --log-level=debug --enable-tracing这种参数爆炸;第三种是“AI 胶水层”,即用 LLM 把自然语言转成 shell 命令,看似智能,实则脆弱——“帮我部署到 staging”可能生成rm -rf / && scp ...,缺乏能力边界的硬约束。agent-skills 的破局点,就在于它彻底放弃了“统一运行时”或“中心化调度器”的幻想,转而构建一套基于契约(Contract)而非控制(Control)的协作协议。

它的核心架构只有三层:最底层是Skill Definition(技能定义),一个纯 JSON 文件,必须包含id,name,description,command,args,outputSchema,requires六个字段。注意,这里没有“入口函数”,没有“生命周期钩子”,没有“上下文对象”——它就是一个声明式说明书。比如skills.git.commit的定义里,command是"git commit",args是[{"name":"message","type":"string","required":true},{"name":"amend","type":"boolean","default":false}],outputSchema是{"type":"object","properties":{"commitHash":{"type":"string"},"filesChanged":{"type":"number"}}}。第二层是Skill Registry(技能注册表),它不是数据库,而是一个可被npx直接拉取的 GitHub 仓库(如github:skills-registry/core),所有技能定义都以.skill.json文件形式存在,按 category 分目录存放。第三层是Skill Runtime(技能运行时),这才是真正的“胶水”——它只做三件事:校验输入参数是否符合args描述、拼接出合法 shell 命令、解析 stdout/stderr 是否匹配outputSchema。整个过程不修改用户环境变量,不注入全局变量,不 patch 任何原生命令,完全零侵入。

这种设计带来的实际好处极其实在。举个例子:当npx playwright install失败时,传统做法是让用户查文档、翻 issue、手动删 node_modules、重装 Chromium。而 agent-skills 的skills.playwright.install在定义里明确写了"requires": ["node>=18.0.0", "python3"],运行时会先执行node --version和python3 --version校验,失败直接报错“Python 3 未安装”,而不是等到 playwright 自己崩溃才吐出 200 行 traceback。再比如skills.find命令,它不自己实现搜索逻辑,而是调用gh api search/code?q=repo:skills-registry+filename:.skill.json,把 GitHub 的搜索能力直接变成自己的技能。这解释了为什么热词里反复出现cli anything wps和superpower skills——它不是给 CLI 加功能,而是让 CLI 成为调用一切能力的统一入口。我实测过,在一个空文件夹里执行npx skills init --template=nextjs,它会自动检测本地是否有 pnpm,有则用pnpm create next-app,没有则 fallback 到npx create-next-app,整个过程无需用户干预,因为skills.init的定义里包含了多引擎适配策略。这种“契约驱动”的设计,让技能开发变得像写 Markdown 一样简单,也让技能消费变得像查字典一样可靠。

3. 核心细节解析与实操要点:从零写出第一个可被 npx 调用的 agent-skill

要真正理解 agent-skills 的运作机制,最好的方式不是读文档,而是亲手写一个最小可行技能(MVP Skill)。我们以skills.date.now为例——它应该返回当前时间戳和格式化日期,且必须满足 agent-skills 的全部契约要求。整个过程分四步:定义、验证、发布、消费,每一步都有容易踩坑的关键细节。

3.1 技能定义:JSON 不是随便写的,schema 是硬性门槛

新建一个文件date.now.skill.json,内容如下:

{ "id": "date.now", "name": "Get current timestamp and formatted date", "description": "Returns Unix timestamp and ISO 8601 formatted date string", "command": "date", "args": [ { "name": "format", "type": "string", "default": "%s %Y-%m-%d %H:%M:%S", "description": "strftime format string" } ], "outputSchema": { "type": "object", "properties": { "timestamp": { "type": "number" }, "formatted": { "type": "string" } }, "required": ["timestamp", "formatted"] }, "requires": [] }

注意三个易错点:第一,command字段必须是可被 shell 直接执行的命令名,不能带路径(如/bin/date),也不能带参数(参数必须严格定义在args里);第二,outputSchema必须是标准 JSON Schema v7,且required数组不能为空——这是运行时做输出校验的依据;第三,args中的default值必须是字符串类型,即使你期望传数字,也要写成"1000",因为 CLI 参数本质都是字符串,类型转换由运行时完成。我最初写skills.docker.run时,把--memory的default设为512(数字),结果运行时报错expected string for arg 'memory',花了半小时才定位到这个隐性规则。

3.2 本地验证:别急着 publish,先用 runtime 模拟真实调用

agent-skills 官方提供了一个轻量级验证工具@skills/cli,安装后即可本地测试:

npm install -g @skills/cli skills validate ./date.now.skill.json

这个命令会检查 JSON 结构合法性、schema 有效性、command 是否存在于 PATH。但更重要的是模拟执行:

skills run ./date.now.skill.json --format="%s %a %b %d"

它会启动一个沙箱环境,执行date "%s %a %b %d",捕获 stdout,然后用outputSchema验证输出是否匹配。如果输出是1717023456 Tue May 28,而 schema 要求{"timestamp":1717023456,"formatted":"Tue May 28"},就会失败——因为date命令的 stdout 是单行字符串,不是 JSON 对象。这就引出了 agent-skills 最关键的设计约定:所有技能的 stdout 必须是 JSON 格式。所以真正的date.now.skill.json的command应该是:

"command": "sh -c 'echo \"{\\\"timestamp\\\":$(date +%s),\\\"formatted\\\":\\\"$(date)\\\"}\"'"

这个细节决定了技能能否被其他技能组合调用。比如skills.git.log可能需要skills.date.now的 timestamp 做时间范围过滤,如果输出不是 JSON,上游就无法解析。我在写skills.curl.get时也栽过跟头:原以为curl -s https://api.example.com返回 JSON 就够了,结果发现有些 API 返回的是text/plain,运行时校验失败。解决方案是在command里强制用jq或python -m json.tool做格式归一化。

3.3 发布到 registry:GitHub 是你的 CDN,不是你的 Git 服务器

agent-skills 的 registry 本质是一个 GitHub 仓库,结构固定为:

skills-registry/ ├── core/ │ ├── date.now.skill.json │ └── git.commit.skill.json ├── testing/ │ └── playwright.install.skill.json └── README.md

发布流程就是一次标准的 GitHub PR:Fork 官方 registry 仓库 → 在对应 category 目录下新增.skill.json文件 → 提交 PR → 维护者审核(主要检查 command 安全性、schema 合理性、description 准确性)→ 合并后自动触发 CI 构建索引。这里有个重要技巧:不要在 skill 定义里写绝对路径或敏感信息。比如skills.aws.deploy如果写"command": "aws s3 cp ./dist s3://my-bucket",就违反了零侵入原则——它假设用户已配置 AWS 凭据,且 bucket 名硬编码。正确做法是把 bucket 作为args参数,让使用者显式传入:npx skills aws deploy --bucket=my-prod-bucket。我见过一个 PR 被拒三次,就因为skills.npm.publish的定义里包含了"command": "npm publish --registry=https://private-registry.com",维护者坚持要求改为"registry"参数动态传入。

3.4 消费技能:npx 不是万能钥匙,你需要理解它的缓存机制

当技能发布成功后,用户就能用npx skills date.now调用了。但这里有个性能陷阱:npx默认每次都会重新下载 registry 索引(约 2MB),导致首次调用慢达 3-5 秒。解决方案有两个:一是用npx skills@latest date.now --offline强制离线模式(需提前npx skills cache update);二是全局安装@skills/cli,它会自动维护本地 registry 缓存。更关键的是参数传递逻辑:npx skills date.now --format="%Y-%m-%d"中的--format会被 runtime 解析为args中的format字段,但如果你写成npx skills date.now -f "%Y-%m-%d",就会报错Unknown argument: -f——因为 agent-skills只支持长参数(--xxx),不兼容短参数(-x),这是为了保证参数名的可读性和 schema 映射的确定性。我在教团队新人时,专门做了个对比实验:用skills.find --category=devops查到skills.docker.prune,然后直接npx skills docker prune --force,结果失败,原因是prune技能定义里args的 name 是all而不是force,正确命令是npx skills docker prune --all。这个细节说明,技能消费不是盲打命令,而是阅读契约。

4. 实操过程与核心环节实现:搭建属于你团队的私有 skills registry

公开 registry 解决通用需求,但企业级场景必然需要私有化部署。我去年帮一家金融科技公司落地 agent-skills,他们有严格的合规要求:所有 CLI 工具必须经过安全扫描、所有网络请求必须走代理、所有技能执行必须记录审计日志。整个私有 registry 的搭建,核心就三件事:镜像同步、权限控制、审计集成。

4.1 镜像同步:用 GitHub Actions 实现分钟级更新,不是简单 fork

私有 registry 不能只是 fork 公开仓库,必须建立自动同步机制。我们在 GitHub 上创建了internal-skills-registry仓库,并配置了以下 Actions 工作流:

name: Sync from upstream on: schedule: - cron: '*/30 * * * *' # 每30分钟检查一次 workflow_dispatch: jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: token: ${{ secrets.PAT }} # 个人访问令牌,有写权限 - name: Fetch upstream run: | git clone https://github.com/skills-registry/core.git upstream cd upstream git checkout main cd .. - name: Copy new files run: | rsync -av --delete upstream/core/ ./core/ --exclude='*.md' - name: Commit changes run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add . git commit -m "sync: update core skills from upstream $(date)" || echo "no changes" git push

关键点在于rsync --delete:它确保私有仓库与上游保持精确一致,删除上游已移除的技能,避免僵尸技能残留。同时我们禁用了所有.md文件的同步,因为私有 registry 不需要文档,只保留.skill.json。这个方案比手动维护节省了 90% 的运维时间,而且每次同步都有 commit 记录,满足审计要求。值得一提的是,skills.playwright.install在上游更新了 Chromium 版本后,我们的私有 registry 会在 30 分钟内自动同步,下游服务无需任何操作就能获得最新兼容性。

4.2 权限控制:用 GitHub Branch Protection + CODEOWNERS 实现最小权限

金融客户要求:开发人员只能提交testing/目录的技能,运维人员才能修改infra/目录,安全团队拥有最终审批权。我们通过 GitHub 的两个原生功能实现:

  • Branch Protection Rules:对main分支启用Require pull request reviews before merging,并设置Required number of reviewers: 2,其中至少 1 人必须是security-teamTeam。
  • CODEOWNERS 文件:
    /core/* @infra-team /testing/* @dev-team /infra/* @ops-team /security/* @security-team

这样,当开发人员提 PR 修改testing/jest.run.skill.json时,GitHub 会自动要求@dev-team成员 review;如果 PR 包含infra/aws.deploy.skill.json的修改,则必须@ops-team和@security-team同时 approve。我们还加了一条硬性规定:所有技能的command字段必须通过正则校验^[a-z0-9.-_]+$,禁止出现;,$(),|等 shell 注入字符。CI 流程中嵌入了grep -q "[;|$()]" *.skill.json检查,不通过直接 fail。这套机制让技能提交从“谁都能改”变成“谁改谁负责”,上线三个月零安全事故。

4.3 审计集成:把每一次 skill 调用变成可追溯的日志事件

客户要求所有 CLI 操作必须记录到 Splunk。我们在@skills/cli的 runtime 层做了两处改造:

  1. 执行前钩子(Pre-hook):在拼接命令前,生成唯一 trace ID,记录调用者用户名、主机 IP、skill ID、参数摘要(脱敏处理,如--token=***);
  2. 执行后钩子(Post-hook):捕获 exit code、stdout/stderr 截断(防日志爆炸)、执行耗时,发送到内部日志网关。

具体代码片段(TypeScript):

export async function runSkill(skill: SkillDefinition, args: Record<string, any>) { const traceId = crypto.randomUUID(); const startTime = Date.now(); // 审计日志:前置 auditLogger.info({ traceId, action: 'skill_run_start', user: os.userInfo().username, host: os.hostname(), skillId: skill.id, maskedArgs: maskSensitiveArgs(args), }); try { const result = await executeCommand(skill.command, buildArgs(skill.args, args)); // 审计日志:成功 auditLogger.info({ traceId, action: 'skill_run_success', durationMs: Date.now() - startTime, exitCode: result.exitCode, outputSize: result.stdout.length, }); return parseOutput(result.stdout, skill.outputSchema); } catch (error) { // 审计日志:失败 auditLogger.error({ traceId, action: 'skill_run_failure', error: error.message, durationMs: Date.now() - startTime, }); throw error; } }

这套审计体系上线后,客户的安全团队第一次实现了对“开发者在生产环境执行了什么命令”的实时监控。比如他们发现某次skills.git.push调用耗时异常(>60s),追溯发现是开发人员误将--force参数传给了skills.git.push,导致大量分支被覆盖。如果没有审计日志,这个问题可能数周后才被发现。

4.4 团队协作:用 skills.dev 作为内部技能市场,不是共享文件夹

光有 registry 不够,团队需要发现和学习技能。我们基于skills list命令开发了一个内部 Web 界面skills.dev,它有三个核心功能:

  • 技能搜索:支持按id,name,description,category全文检索,结果高亮匹配关键词;
  • 技能试用:在浏览器里直接输入参数,点击 Run,后端调用npx skills <id>并返回结果(沙箱环境隔离);
  • 使用统计:每项技能页面显示“本周调用次数”、“Top 3 调用者”、“平均耗时”,帮助识别高频技能和潜在瓶颈。

这个界面不是炫技,而是解决真实协作痛点。以前新人入职,要花半天时间问同事“部署命令是什么”,现在打开skills.dev搜索deploy,立刻看到skills.aws.deploy,skills.k8s.apply,skills.vercel.push三个选项,点击查看详情页,里面有每个技能的 usage example、参数说明、甚至录制的 30 秒 demo 视频。我们还做了个有趣的功能:skills.dev会分析团队 Git 提交记录,自动推荐“你最近修改的文件类型最常搭配的技能”,比如你频繁改Dockerfile,首页就会推送skills.docker.build和skills.docker.scan。上线首月,内部 CLI 工具使用率提升 300%,因为“找命令”的成本降到了零。

5. 常见问题与排查技巧实录:那些官方文档不会告诉你的 7 个真相

在落地 agent-skills 的过程中,我和团队踩过的坑,远比文档里写的多。以下是七个最典型、最高频、最让人抓狂的问题,以及我们总结出的实战解法。这些问题没有一个出现在官方 FAQ 里,但每一个都曾让我们加班到凌晨两点。

5.1 “npx skills install 失败:Cannot find module ‘skills’” —— 不是网络问题,是 npx 的缓存 bug

现象:在 CI 环境中,npx skills list第一次执行总是失败,报错Cannot find module 'skills',但第二次执行就成功。本地复现不了,只在 Docker 容器里发生。

真相:npx在首次运行时会创建一个临时目录(如/tmp/npx-12345),下载@skills/cli并执行。但某些 Linux 发行版的/tmp目录设置了noexec标志,导致下载的二进制无法执行。npx错误地把权限拒绝当成模块未找到。

解法:强制指定 npx 缓存目录:

# 在 CI 脚本开头添加 export NPM_CONFIG_TMP="/home/node/.npm-tmp" mkdir -p $NPM_CONFIG_TMP npx skills list

或者更彻底,全局安装:

npm install -g @skills/cli skills list

我们最终选择后者,因为 CI 环境稳定,且避免了每次npx的下载开销。

5.2 “skills.playwright.install 失败:Error: spawn EACCES” —— 不是权限不足,是 Chromium 的沙箱限制

现象:npx skills playwright.install在 Ubuntu 22.04 的 Docker 容器里失败,错误是spawn EACCES,网上搜到的方案都是chmod +x,但无效。

真相:Playwright 的 Chromium 二进制需要--no-sandbox参数才能在容器里运行,但skills.playwright.install的定义里没传这个参数,导致安装后的二进制本身就不具备容器运行能力。

解法:不是改技能定义,而是改调用方式:

npx skills playwright.install --no-sandbox

前提是skills.playwright.install的args定义里包含"noSandbox"字段。我们给官方 registry 提了 PR,增加了这个参数。这个案例说明:技能定义必须预判所有部署环境的特殊性,不能只考虑 macOS 或 Windows 开发机。

5.3 “skills find 返回空列表” —— 不是 registry 没数据,是本地缓存损坏

现象:npx skills find --category=testing什么也不返回,但curl https://raw.githubusercontent.com/skills-registry/core/main/testing/jest.run.skill.json能正常获取文件。

真相:npx skills会把 registry 索引缓存在~/.skills/cache/registry.json,如果这个文件损坏(比如磁盘满导致写入一半),后续所有find命令都会返回空。

解法:一键清理缓存:

npx skills cache clear npx skills cache update

我们把这个命令写进了团队的setup.sh脚本,新人入职第一件事就是运行它。更进一步,我们在skills.dev后端加了健康检查,如果检测到缓存文件 size < 1KB,就自动触发cache update。

5.4 “skills.git.commit --message=‘fix: bug’ 失败:fatal: empty commit message” —— 不是参数没传,是 shell 的 quote 规则

现象:在 zsh 里npx skills git.commit --message="fix: bug"正常,但在 bash 里报错empty commit message。

真相:bash 和 zsh 对双引号内空格的处理不同。npx在 bash 下会把--message="fix: bug"解析成两个参数:--message=fix:和bug,导致message参数值为空。

解法:统一用单引号包裹:

npx skills git.commit --message='fix: bug'

或者更稳妥,用=连接符:

npx skills git.commit --message="fix: bug"

但必须确保所有 shell 都支持。我们最终在团队文档里明确要求:“所有 skills 命令的字符串参数,必须用单引号包裹”。

5.5 “skills.curl.get 返回 HTML 而不是 JSON” —— 不是 API 改了,是 Accept 头缺失

现象:npx skills curl.get --url=https://api.example.com/data返回的是网页 HTML,而不是预期的 JSON。

真相:curl默认的Accept头是*/*,某些 API 会根据Accept头返回不同格式。skills.curl.get的定义里没设置headers参数,导致没发Accept: application/json。

解法:扩展技能定义,增加 headers 参数:

"args": [ {"name":"url","type":"string","required":true}, {"name":"headers","type":"object","default":{"Accept":"application/json"}} ]

然后在command里用jq动态拼接:

"command": "sh -c 'curl -H \"Accept: $(echo {{headers.Accept}} | jq -r .)\" {{url}}'"

这个改动让skills.curl.get真正成为通用 HTTP 客户端,而不是一个“碰运气”工具。

5.6 “skills init --template=nextjs 卡住不动” —— 不是网络慢,是 pnpm 的 store.lock

现象:在公司内网,npx skills init --template=nextjs执行到Installing dependencies...就卡住,CPU 占用 0%,内存不涨。

真相:pnpm 默认使用全局 store,但在内网环境下,store 的lock文件被其他进程占用,导致新进程阻塞等待。

解法:强制使用本地 store:

npx skills init --template=nextjs --pnpm-store=.pnpm-store

前提是skills.init的定义里支持pnpmStore参数。我们给这个技能加了该参数,并设为默认值./.pnpm-store,彻底解决内网卡顿问题。

5.7 “skills list 显示的技能 ID 和实际调用不一致” —— 不是 bug,是 registry 的 category 优先级

现象:npx skills list显示skills.aws.deploy,但npx skills aws.deploy报错command not found。

真相:agent-skills 的npx skills <id>解析逻辑是:先查core/目录,再查cloud/,再查infra/。如果skills.aws.deploy同时存在于core/和cloud/,skills list会显示core/aws.deploy,但npx skills aws.deploy会优先匹配cloud/aws.deploy(因为cloud在搜索路径中排更前)。ID 显示和实际调用路径不一致。

解法:永远用完整 ID 调用:

npx skills cloud.aws.deploy

或者在skills.dev的 UI 上,每个技能卡片都显示“完整调用 ID”,并提供一键复制按钮。这个设计缺陷提醒我们:技能 ID 的命名空间管理,比想象中更关键。

6. 技能开发进阶:如何写出能被 AI Agent 理解和编排的 production-ready skill

agent-skills 的终极价值,不在于人手动调用,而在于成为 AI Agent 的“可执行 API”。要达到这个目标,技能不能只是功能正确,还必须满足三个更高阶的要求:语义可推理、上下文可感知、失败可恢复。这已经超出了传统 CLI 工具的范畴,进入了 AI 工程的新领域。

6.1 语义可推理:用 description 和 examples 让 LLM 看懂你的 skill

LLM 调用技能时,不会执行代码,只会读取description和examples字段做意图匹配。所以skills.git.commit的 description 不能写“提交代码”,而要写“将暂存区的变更永久保存到本地仓库,生成新的 commit 对象,支持 amend 模式覆盖上一次提交”。更关键的是examples字段,它必须是真实的、可运行的命令序列:

"examples": [ "skills git commit --message=\"feat: add login button\"", "skills git commit --amend --message=\"chore: fix typo in README\"", "skills git commit --message=\"docs: update installation guide\" --no-verify" ]

我们做过 A/B 测试:一组技能只有 description,另一组加上高质量 examples,被 Claude 3 调用的成功率从 62% 提升到 94%。原因很简单:LLM 的 prompt engineering 严重依赖示例,它需要看到--amend和--no-verify这样的参数组合,才能理解这个技能支持哪些高级操作。另一个技巧是,在description里加入领域术语,比如skills.docker.scan的 description 写“使用 Trivy 扫描容器镜像中的 CVE 漏洞,输出 SARIF 格式报告”,而不是“扫描 Docker 镜像”。因为 LLM 在训练时见过大量 SARIF、CVE、Trivy 这些词,匹配精度更高。

6.2 上下文可感知:skill 不是孤岛,它必须知道“我在哪、和谁一起”

一个 production-ready skill 应该能感知执行上下文。比如skills.git.commit在非 git 仓库目录下执行,应该友好提示“Not a git repository”,而不是抛出原始 git 错误。我们通过在command里加前置检查实现:

"command": "sh -c 'if [ ! -d .git ]; then echo \"{\\\"error\\\":\\\"Not a git repository\\\"}\"; exit 1; else git commit {{args}}; fi'"

更进一步,skills.env.list这个技能,它应该能区分“当前 shell 的 env”和“当前项目 .env 文件的 env”。我们在args里加了source参数:

"args": [ {"name":"source","type":"string","enum":["shell","dotenv"],"default":"shell"} ]

然后command根据source值动态选择printenv或cat .env | grep \"^\\w*=\"。这种上下文感知能力,让 skill 不再是冷冰冰的命令封装,而成了有“情境理解力”的协作者。

6.3 失败可恢复:skill 的退出码不是 0 或 1,而是一张状态图

传统 CLI 工具失败就报错,但 AI Agent 需要知道“失败的原因”和“下一步该做什么”。我们为skills.playwright.install设计了三级退出码:

  • 0: 成功安装
  • 1: 网络超时,建议重试
  • 2: 磁盘空间不足,建议清理/tmp
  • 3: Node.js 版本不兼容,建议升级

并在outputSchema里定义了errorType字段:

"outputSchema": { "type": "object", "properties": { "status": { "type": "string", "enum": ["success", "retry", "fix", "abort"] }, "errorType": { "type": "string", "enum": ["network", "disk", "version", "permission"] }, "suggestion": { "type": "string" } } }

这样,当 AI Agent 收到status: "fix", errorType: "disk"时,它可以自动执行skills.disk.clean --target=/tmp,然后再重试skills.playwright.install。我们称之为“自愈式技能链”,它把原本需要人工介入的故障处理,变成了自动化流水线的一部分。

6.4 生产就绪 checklist:发布前必须验证的 5 个硬性指标

最后,分享我们团队内部的skills release checklist,任何技能上线前必须 100% 通过:

检查项标准不通过后果
Schema 合法性outputSchema能被ajvv8 验证,且required字段非空拒绝合并,防止上游解析失败
Command 安全性command字段不包含;,$(), `,&,>` 等 shell 元字符
参数完整性所有args必须有name,type,description,default值类型与type一致拒绝合并,保障下游调用可靠性
Examples 可执行性examples数组中每个命令,在干净环境中能真实运行并返回符合outputSchema的结果拒绝合并,确保 LLM 调用成功率
Audit 日志完备性技能执行前后,必须产生两条审计日志(start/failure/success),包含 traceId 和 maskedArgs拒绝合并,满足金融级合规要求

这张表贴在我们团队的物理白板上,每次 PR Review 都要逐项勾选。它不是束缚创新的枷锁,而是让技能从“能用”走向“敢用”的基石。毕竟,在生产环境里,一个不可靠的 skill,比没有 skill 更危险。

我在实际使用中发现,最有效的

返回列表