
1. 从 AGENTS.md 越写越乱说起AI 代理技能骨架到底解决什么问题如果你正在用 Claude Code、Cline 或者任何支持 AGENTS.md 的编码代理大概率遇到过这个场景一开始 AGENTS.md 只有十几行写着「用 pnpm 不用 npm」「提交前跑 lint」。三个月后它变成了八百行里面塞满了数据库迁移步骤、发版检查清单、某个内部 SDK 的调用模板。每次开新会话代理都要把这八百行全部读一遍token 烧得飞快而其中 90% 的内容这次任务根本用不上。这就是 authoring-skills 这套规范要解决的核心矛盾常驻上下文和按需上下文必须分层。AGENTS.md 是每次会话都加载的「护栏层」只放一句话就能说清的规则而 SKILL.md 是「技能层」只有当任务真正匹配时才被加载里面可以放多步骤工作流、完整代码模板、诊断命令。你可以把它理解成公司手册和操作手册的区别——员工入职第一天要背的是行为准则AGENTS.md而修打印机的时候才去翻那本《打印机故障排查手册》SKILL.md。SKILL.md 能做什么它通过 Frontmatter 里的name和description告诉代理「我是谁、什么时候该用我」代理在启动时只扫描所有技能的元数据很便宜命中触发条件后才把正文读进来按需付费。适合谁适合任何维护超过 200 行 AGENTS.md 的团队或者任何想让代理在特定任务上表现更稳定的个人开发者。我试过把一套前端项目的发版流程从 AGENTS.md 拆成独立技能会话首轮 token 消耗直接降了六成而代理执行发版步骤的准确率反而上升了——因为技能正文里可以写清楚每一步的验证命令不用再和别的规则抢注意力。下面从目录结构开始一步步搭出可运行的最小技能。2. TaoToken 前置准备把模型通道和技能目录先对齐在写 SKILL.md 之前得先确认两件事代理能正常调用模型以及技能目录放在代理会扫描的位置。这两件事没搞定后面写再多 Frontmatter 都是白搭。模型通道这块我用的是 TaoToken 的 API 接入方式。它的 Base URL 是https://taotoken.net/api兼容 OpenAI 风格的请求格式所以 Claude Code、Cline、Codex 这类工具都能直接配。你需要先去控制台拿一个 API Key地址是 https://taotoken.net/api-keys 拿到之后先别急着写进配置文件用 curl 验一下通道是否通curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: reply with ok}], max_tokens: 16 }返回里能看到choices[0].message.content就说明通道没问题。这一步很关键因为后面技能加载验证时代理需要真实调用模型来判断是否触发技能通道不通会误判成技能配置错误。技能目录的位置取决于你用的工具。Claude Code 默认扫描项目根目录下的.agents/skills/Cline 走 MCP 配置时也支持同样的约定。所以第一步是在项目根目录建目录mkdir -p .agents/skills/authoring-skills cd .agents/skills/authoring-skills touch SKILL.md如果你用的是 Codex它的认证信息在~/.codex/auth.json里面需要填 Base URL 和 KeyClaude Code 则在~/.claude/settings.json里配env字段。这两个文件的写法我在第 3 节给完整片段。这里先记住一个原则Base URL 填https://taotoken.net/api不要带任何路径后缀很多 401 报错都是因为多写了/v1或者少了/api。目录建好之后先别写内容跑一个空技能测试代理能不能识别到目录。有些工具需要重启会话才会重新扫描.agents/skills/有些支持热加载。判断方法很简单在会话里输入/authoring-skills如果代理回复「未找到该技能」说明目录没被扫描到检查一下是不是建在了子目录里而不是项目根目录。3. 可复制配置SKILL.md 的 Frontmatter 骨架与 AGENTS.md 协作约定这一节是全文的核心给你可以直接抄的配置。先看 SKILL.md 的完整骨架Frontmatter 字段只从官方支持列表里选未知字段会被静默忽略这点很容易踩坑——你写了个trigger字段以为能生效实际上代理根本没读。--- name: authoring-skills description: How to create and maintain agent skills in .agents/skills/. Use when creating a new SKILL.md, writing skill descriptions, choosing frontmatter fields, or deciding what content belongs in a skill vs AGENTS.md. Covers supported spec fields, description writing, naming conventions, and the relationship between always-loaded AGENTS.md and on-demand skills. argument-hint: skill-name user-invocable: true disable-model-invocation: false allowed-tools: [Read, Write, Bash] model: opus context: fork agent: Explore --- # Authoring Skills Use this skill when creating or modifying agent skills in .agents/skills/. ## When to Create a Skill Create a skill when content is: - Too detailed for AGENTS.md (code templates, multi-step workflows, diagnostic procedures) - Only relevant for specific tasks (not needed every session) - Self-contained enough to load independently Keep in AGENTS.md instead when: - Its a one-liner rule or guardrail every session needs - Its a general-purpose gotcha any agent could hit ## File Structure .agents/skills/ └── my-skill/ ├── SKILL.md # Required: frontmatter content ├── workflow.md # Optional: supplementary detail └── examples.md # Optional: referenced from SKILL.md ## Verification After creating a skill, run: bash ls -la .agents/skills/my-skill/SKILL.mdThen in the agent session, type/my-skillto confirm it loads.Frontmatter 里几个字段值得单独说。description 是自动触发的唯一匹配面写得太泛比如「Helps with flags」代理永远匹配不上必须带上具体文件名和关键词像上面那样写 config-shared.ts、feature flag 这种词用户一提代理就能命中。user-invocable: false 会把技能从 / 菜单里藏起来适合那种只该被自动触发、不该手动调用的技能。context: fork 配合 agent: Explore 能让技能在隔离子代理里执行适合那种会改一堆文件、不想污染主会话上下文的重活。 然后是 AGENTS.md 的协作约定。技能建好之后必须在 AGENTS.md 里加一行指针否则代理不知道有这个技能存在 markdown ## Skills - $authoring-skills — 创建和维护 .agents/skills/ 下的技能文件 - $pr-status-triage — PR 状态分类与优先级排序这个$skill-name引用是硬约定代理读到这行就知道「有个叫 authoring-skills 的技能可以按需加载」。AGENTS.md 里只放这一行摘要详细内容全部留在 SKILL.md 里这就是职责分离。如果你用 Claude Code~/.claude/settings.json里这样配{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-your-key-here, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }如果你用 Codex~/.codex/auth.json里这样写{ base_url: https://taotoken.net/api, api_key: sk-your-key-here, model: claude-sonnet-4-20250514 }三件套 Base URL、Key、Model ID 一个都不能少缺任何一个都会在加载技能时报认证错误。Cline 走 MCP 的话在 MCP 配置里把这三项填进环境变量即可。4. 验证请求跑一次技能加载确认骨架真的活了配置写完不算完得验证代理真的能加载这个技能。验证分两步先验文件结构再验运行时触发。文件结构验证用一条命令搞定find .agents/skills -name SKILL.md -exec sh -c echo $1 ; head -20 $1 _ {} \;这条命令会列出所有技能的 SKILL.md 前 20 行你能一眼看出 Frontmatter 有没有写对、name和目录名是否一致。目录名和name字段不一致是个隐蔽的坑有些工具按目录名索引有些按name字段索引不一致会导致/skill-name命令找不到。运行时验证更直接。在代理会话里输入/authoring-skills如果技能配置正确代理会加载 SKILL.md 正文并回复技能内容摘要。如果报「unknown skill」按这个顺序排查目录是不是在项目根目录、Frontmatter 的---是不是成对、name字段有没有拼错。自动触发验证稍微麻烦一点需要构造一个能命中description的请求。比如你问代理我要新建一个 SKILL.md帮我看看 Frontmatter 该怎么写因为 description 里包含了creating a new SKILL.md这个短语代理应该自动加载 authoring-skills 技能。如果没触发说明 description 写得不够具体回去补上用户可能提到的关键词。验证成功后你会看到代理的回复里引用了技能正文的步骤而不是泛泛而谈。这一步的「成功结果」很明确代理能说出「根据 authoring-skills 技能Frontmatter 只支持这些字段」并列出具体字段名而不是编造字段。再补一个端到端的验证确认模型通道和技能加载是打通的curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: claude-sonnet-4-20250514, messages: [ {role: system, content: You have a skill named authoring-skills. Reply with its name only.}, {role: user, content: which skill applies?} ], max_tokens: 32 }返回里出现authoring-skills就说明从通道到技能元数据的链路是通的。这个测试的好处是不依赖具体工具的 UI纯 API 层面就能确认。5. 常见报错排查401、local proxy failed、reading choices 逐个拆技能加载失败时报错信息往往指向模型通道而不是技能本身很容易误判。下面按真实遇到的报错逐个拆。401 Unauthorized。这个最常见九成是 Key 或 Base URL 的问题。先确认 Key 有没有过期去 https://taotoken.net/api-keys 重新生成一个。然后确认 Base URL 写的是https://taotoken.net/api不要写成https://taotoken.net/api/v1或者漏掉/api。Claude Code 的ANTHROPIC_BASE_URL和 Codex 的base_url对路径的处理略有差异前者通常不带/v1后者有些版本需要带。如果 401 反复出现用第 2 节的 curl 命令单独测通道通道通了再回头查工具配置。local proxy failed。这个报错通常出现在工具试图走本地代理转发请求时。检查你的环境变量里有没有残留的HTTP_PROXY、HTTPS_PROXY有的话先 unset 掉再重启会话。另外确认工具配置里没有填localhost或127.0.0.1作为 Base URL应该直接填https://taotoken.net/api。reading choices of undefined。这个报错说明请求发出去了但返回体里没有choices字段通常是返回了一个错误对象。打印完整返回体看看curl -s https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d {model:claude-sonnet-4-20250514,messages:[{role:user,content:hi}],max_tokens:8} | jq .如果返回里有error字段按 error message 处理如果返回是空的检查model字段拼写模型 ID 写错也会导致返回体异常。OAuth 相关报错。有些工具默认走 OAuth 登录流程如果你用的是 API Key 模式需要在配置里显式关掉 OAuth。Claude Code 里检查有没有CLAUDE_CODE_USE_OAUTH之类的环境变量Codex 里检查auth.json是不是同时存在 OAuth token 和 api_key 导致冲突。清理掉 OAuth 相关字段只保留 Base URL、Key、Model ID 三件套。技能不触发。如果通道没问题但技能就是不自动加载八成是 description 写得太泛。把 description 改成包含具体文件名、具体动作短语的写法比如把「Helps with config」改成「How to modify config-shared.ts feature flags end-to-end」。代理的匹配是基于语义相似度的越具体的描述命中率越高。排查顺序建议固定成先 curl 测通道再查工具配置文件最后查技能 Frontmatter。这个顺序能避免在技能层面瞎改半天结果发现是 Key 过期了。6. 把技能骨架用起来从最小技能到技能体系最小技能跑通之后下一步是把它扩展成体系。我的做法是先建一个authoring-skills作为元技能专门管技能怎么写然后按业务域拆出具体技能比如pr-status-triage、dce-edge、react-vendoring。每个技能都遵循同样的骨架Frontmatter 写清楚触发条件正文用「Use this skill when...」开头步骤化末尾附验证命令。复杂技能用 hub detail 模式主 SKILL.md 只放概览和快速命令细节拆到workflow.md和local-repro.md里主文件里用相对路径引用。这样代理加载主文件时不会一次性读入所有细节需要深入时再读子文件。命名上保持短、描述性、主题域内不要加仓库前缀.agents/skills/已经限定了范围多词用连字符。flags、dce-edge这种名字比my-project-feature-flag-helper好得多因为代理匹配时短名字更容易和用户输入对齐。最后提醒一个容易忽略的点每次新增技能记得回 AGENTS.md 加一行$skill-name指针。技能文件和 AGENTS.md 是配套的只建技能不加指针代理永远不知道它存在。这套分层设计跑顺之后你的 AGENTS.md 会稳定在几十行而技能库可以无限扩展每个技能只在需要时消耗 token。如果你还没配好模型通道先去 https://taotoken.net/api-keys 拿 Key接入文档在 https://taotoken.net/doc 想先试试模型对话效果可以走 https://taotoken.net/console 。长期跑编码代理的话Coding Plan 在 https://taotoken.net/coding-plan 有更划算的额度方案。