
文章目录前言一、三份 http.ts 的荒诞剧二、每次新建 Skill都要重新思考人生三、SKILL.md 的玄学四、skill-kits一个被逼出来的工具链五、Runtime把重复劳动收进一个黑盒5.1 命令路由告别 if-else 摩天大楼5.2 输出协议stdout 和 stderr 分家5.3 HTTP一层薄的 fetch 封装5.4 长轮询心跳别让 Agent 以为你挂了5.5 错误体系能靠 code 说清楚就别靠猜 message六、业务公共模块跨 Skill 的共享仓库七、LintSKILL.md 也该体检八、Dev 模式告别快递小哥生涯写在最后P.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01前言半年前我以为写 Agent Skill 就跟写个脚本一样简单——一份 markdown 定规则一段代码跑逻辑完事儿。那时候的我天真得像个刚学会用 CtrlC 的孩子觉得自己就是代码界的造物主挥手之间就能让 Agent 为我打工。写到第三个 Skill 的时候我开始觉得不对劲了。写到第五个的时候我的右手食指已经因为复制粘贴形成了肌肉记忆。写到第十个的时候我终于崩溃了——我花了 80% 的时间在搞工程20% 的时间在搞业务。这合理吗这不合理。这就像一个厨子每天花八小时磨刀却只花两小时炒菜。于是我把自己逼成了工程化工具链的作者。今天我就来聊聊这 10 个 Skill 踩出来的坑以及我是怎么把它们填平的。一、三份 http.ts 的荒诞剧第一个 Skill我写了个 HTTP 封装自我感觉良好。第二个 Skill我又写了一份因为第一个的鉴权方式是 Cookie这个要用 Bearer。第三个 Skill我又写了一份因为前两个的错误处理逻辑不一样。三个 Skill三份 http.ts。它们长得就像三胞胎但一个用 Cookie一个用 Bearer一个我也不知道用了什么。最离谱的是有一天上游把鉴权方式从 Cookie 切到了 Bearer我需要把同一段逻辑改三次。那一刻我感觉自己不是在维护项目我是在玩大家来找茬而且这游戏没有奖励只有加班。更魔幻的是这三份代码里的错误处理也各说各话。有的抛 Error有的返回对象有的直接 console.error 然后 process.exit。Agent 调用的时候估计也在想“这个人类到底想让我怎么处理错误”顿悟时刻如果三个项目里有同样的痛苦那这个痛苦就不是业务问题而是工程问题。工程问题的解法永远是把它往上抽一层。二、每次新建 Skill都要重新思考人生写第一个 Skill 的时候目录结构我想了十分钟。写第二个的时候我又想了十分钟因为第一个的结构我已经忘了。写第三个的时候我直接复制了第一个的目录然后删删改改。写到第五个的时候我陷入了存在主义危机我是谁这个入口该放哪references 和 assets 到底有什么区别每次新建项目都像第一次装修房子。你不知道沙发该放哪不知道窗帘该选什么颜色最后只能把东西随便堆进去然后祈祷 Agent 不会迷路。更惨的是本地用 TS 写得爽交给 Agent 的时候它不一定有 TS 运行环境。你用 bunAgent 说我没装。你用 npx tscAgent 说每次执行都要等冷启动我很忙。这时候你就面临一个哲学问题用 JS 没类型补全写起来像蒙眼射箭用 TS 又怕环境复杂像背着降落伞跳伞。这就像在问你想被蚊子咬还是被蜜蜂蜇我选 C我两个都要然后自己造一个工具链解决。三、SKILL.md 的玄学SKILL.md 这东西写得对不等于真的好用。我一开始没当回事后来被现实教育得服服帖帖。有一次我把 description 写得特别抽象像个诗人一样朦胧美。结果 LLM 完全不知道啥时候该调用这个 Skill就像一个导航软件不知道你要去哪。还有一次AI 帮我生成了一个 SKILL.md内容特别全全到我想手动改的时候根本无从下手。就像你请了一个整理师把你的房间整理得完美无瑕但你找不到袜子在哪了。更离谱的是name 和目录名不一致、references 引错了路径、body 太长把上下文窗口塞爆——这些问题代码编译器不会报错但 Agent 会默默地翻车翻得你毫无察觉。血泪教训SKILL.md 不是散文是说明书。说明书的第一原则是让调用者一眼就知道什么时候用你什么时候不用你。第二原则是别写太长LLM 的上下文窗口比你想象的更抠门。四、skill-kits一个被逼出来的工具链踩了这么多坑之后我悟了Skill 开发缺的不是业务能力缺的是一套可复用的工程边界。就像你盖房子不是缺砖头和水泥是缺脚手架和施工规范。于是 skill-kits 诞生了——它不替你写脚本也不替你做业务抽象它只做一件事把入口、产物、运行时、定义校验这些横切问题收进一层护栏里。它的设计理念很简单源码侧当成正常 TS 项目写有 src、有 commands、有 references构建侧用 esbuild 统一打成单文件 main.mjs把 runtime 和业务公共模块内联进去产物零依赖交付侧 Agent 只认 node scripts/main.mjs 这一种形态。三句话总结你写你的 TS它帮你打包Agent 只管跑。常用命令也就三条pnpm new 创建 Skillpnpm dev 边写边同步pnpm build 编译加校验。简单到连我家猫看了都能学会——当然我家猫不会打字但它确实看了。五、Runtime把重复劳动收进一个黑盒Skill 拆开看就是两层一层是结构化的 Prompt即 SKILL.md负责定义规则一层是 Tool即脚本负责真正执行。前者天然灵活后者却有很多相似之处——命令路由、参数校验、输出协议、HTTP 样板、错误码、长轮询心跳。这些重复得太明显我把它们收成了一个 runtime。5.1 命令路由告别 if-else 摩天大楼以前写营销活动管理 Skill7 个子命令main.ts 里堆了 250 行的 parseArgs switch 参数校验。加一个命令要改三处参数解析、校验逻辑、switch case。漏一处就翻车翻得悄无声息。这代码最大的问题不是长而是逻辑分散像一盘散沙风一吹就糊一脸。后来我把这块收成了 createRouter声明式定义命令、参数和处理器。参数类型、必填校验、路由逻辑全收敛在一起。你不需要再盯着参数是怎么 parse 的只需要关心这个命令需要什么参数拿到参数后做什么事。思路清爽得像刚洗过的头发。5.2 输出协议stdout 和 stderr 分家以前打印信息除了错误用 console.error其他都用 console.log 一把梭。结果 stdout 里混着 JSON 结果和日志文案Agent 解析的时候一脸懵逼。后来我学会了stdout 输出 JSON 结果给 Agent 用stderr 输出进度文案给人类看。失败时通过非 0 退出码让 Agent 识别到 status: failed这比让 LLM 去解析 stderr 里的错误文本可靠得多。这就像你寄快递把文件和便利贴分开装。文件放信封里便利贴贴外面。收件人一看就知道哪个是正经内容哪个是备注。5.3 HTTP一层薄的 fetch 封装我一开始想做一个全功能 HttpClient内置鉴权、baseURL、重试、业务错误兜底。结果发现不同 Skill 处理 HTTP 的差异太大有的用 Cookie有的用 Bearer有的错误码完全自定义。硬做一个大而全的客户端就像给所有人发均码衣服——胖子穿不上瘦子像唱戏。最后我只保留了一层薄的 fetch 封装少写一点样板代码。剩下跟业务强相关的封装交给各个 Skill 自己包。这叫授人以渔而不是授人以鱼——虽然我更想直接给鱼但鱼的做法太多了。5.4 长轮询心跳别让 Agent 以为你挂了D2C 生码、SSO 登录回调这类场景最大的敌人不是超时而是看起来像超时。比如你直接睡 60 秒await new Promise(resolve setTimeout(resolve, 60000))。这 60 秒内进程没有任何输出Agent 会以为进程已经卡死然后果断把它终止。我只是在等接口返回Agent 却以为我在摸鱼。这误会大了。于是我加了 sleepWithHeartbeat每 5 秒往 stderr 输出一次心跳我还活着我在等数据别杀我。“这就像你给女朋友发微信每隔五分钟发个在忙”防止她以为你失踪了。5.5 错误体系能靠 code 说清楚就别靠猜 message以前错误处理全靠 throw new Error(“出错了”)。Agent 拿到这个错误只能从 message 里猜到底发生了什么。这就像医生给你写诊断书只写不舒服三个字——你倒是告诉我哪里不舒服啊后来我把错误收进了统一的 code 体系UserInputError 是参数问题AuthError 是鉴权问题HttpError 是上游问题BusinessApiError 是业务问题。每个错误带 code 和 detailsAgent 拿到后可以直接做分支处理不需要再从冗长的 message 里猜谜。Runtime 的核心价值runtime 解决的是基础设施层的重复。它让你写 Skill 的时候脑子里想的不再是参数怎么解析、“错误怎么输出”、“HTTP 怎么封装”而是这个业务逻辑怎么实现。六、业务公共模块跨 Skill 的共享仓库runtime 解决的是基础设施还有一层也很值得抽业务公共模块。比如内部 API 客户端、域名常量、签名工具这些在多个 Skill 之间反复出现。于是 skill-kits init 生成的 workspace 默认带一个 packages/shared跨 Skill 复用构建时 esbuild 会把用到的部分内联进产物最后还是单文件、零依赖。这就像你开了一家连锁店总部统一采购原料但每个门店只拿自己需要的。既保证了标准化又没有浪费。七、LintSKILL.md 也该体检SKILL.md 不可能像代码一样完全标准化但它也不是完全没法校验。至少这些问题应该在本地就拦住name 和目录名不一致、body 太长把上下文窗口塞爆、references 引错了路径、description 太短看不出触发场景。我补了一套 lint 规则pnpm build 默认先跑。name 必须等于父目录名body 超过 500 行直接报错超过 400 行给 warningdescription 太短给 warning还要检查有没有写清楚何时触发和不要触发。如果对阈值有自己的习惯可以配 .skillkitrc.json就像给 SKILL.md 做体检有问题早发现早治疗。以前这些问题都是 Agent 调用时才发现就像你到了机场才发现身份证没带。现在本地 build 就拦住就像出门前检查一遍钱包钥匙手机。八、Dev 模式告别快递小哥生涯开发 Skill 的时候改完代码需要同步到 Agent 的本地 Skill 目录。以前这一步基本都是手动复制cp -r dist/xxx ~/.agent/skills。次数多了我感觉自己像个快递小哥每天往返于两个目录之间运送的不是包裹是代码。于是我加了 dev 模式pnpm dev daily-report --out ~/.agent/skills。它同时做两件事用 esbuild watch srcTS 文件变化触发重编监听 SKILL.md 和 references 和 assets资源变化直接同步到指定目录。本地改完Agent 下次调用拿到的就是最新版本。我终于不用当快递小哥了我可以安心写代码了。这感觉就像你以前每次做饭都要把菜从厨房端到客厅现在装了传送带菜做好自动送到餐桌上。虽然传送带是我手搓的但至少不用端盘子了。写在最后skill-kits 不替你写脚本也不替你做业务抽象。它做的事情很明确把入口、产物、运行时、定义校验这些横切问题收进一层护栏里让你在新建第 5 个、第 10 个 Skill 时脑子里想的依然是业务逻辑怎么写而不是这个目录该放哪、“这份 HTTP 封装要不要复制”、“改完代码怎么同步”。从手搓 10 个 Skill 到造一套工具链我最大的收获不是技术能力而是对重复劳动的敏感度。当你发现自己在做第三次同样的事情时就应该停下来想想这件事能不能被收敛能不能被固化能不能被自动化如果你也在写 Agent Skill欢迎试试。毕竟人生苦短何必手搓。快速开始npx skill-kits init my-skillscd my-skills pnpm installpnpm new daily-reportP.S. 无意间发现了一个巨牛的人工智能教程非常通俗易懂对AI感兴趣的朋友强烈推荐去看看传送门https://blog.csdn.net/HHX_01