1. 为什么你写的 Skill 总像一段“许愿文案”
AI Skill 是什么?一句话说清:它是 AI Agent 在特定场景下可被调用的能力入口,通常由一段声明式描述加若干工具脚本组成。它能做什么?让 Agent 知道“什么时候该用我、用我时该按什么规则办事”。适合谁?正在用 Trae、Claude Code、Coding Plan 这类工具搭 Agent 工作流的开发者。
但很多人第一次写 Skill 就踩坑:写完之后发现 Agent 根本不按你写的来,或者时灵时不灵。我试过把一个“代码审查 Skill”写成 200 行 Markdown 指令,结果 Agent 每次输出的报告结构都不一样,评分标准也飘。问题不在模型,而在于没搞清一件事——大部分 Skill 的本质是“指令集”,不是“实现代码”。
指令驱动架构和代码实现架构的区别,不是“谁更高级”,而是“谁负责哪一段”。指令负责描述意图、边界、输出契约;代码负责确定性执行、性能敏感路径、外部系统调用。把两者混为一谈,就会写出既不可测又不可维护的“许愿文案”。这篇就按可跟做的路径,把 Skill 配置骨架、验证动作、排障清单一次讲透。
2. TaoToken 前置:把 Skill 跑起来需要的能力底座
Skill 本身是描述文件,真正执行时还是要落到模型调用上。无论你走指令驱动还是代码实现,最终都要有一个稳定的模型入口。我这边习惯用 TaoToken 做统一接入,原因是它同时提供对话、编码、Agent 三类场景的调用方式,省得在多个平台之间来回切 Key。
官网入口在这里:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册后在控制台创建 API Key 即可。API 基址是 https://taotoken.net/api ,注意这个地址不带 UTM 参数,直接填进配置里就行。
如果你只是验证 Skill 的指令是否被正确理解,用模型对话页面最快:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 。如果你要长期跑编码类 Agent,比如让 Skill 自动改代码、跑测试,那更适合用 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。Key 的管理在控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
注意:Skill 的指令文件本身不包含密钥,密钥统一放在环境变量或 settings.json 里,避免把 Key 写进 Markdown 被 Agent 读出来。
3. 可复制配置:指令驱动 vs 代码实现的 Skill 骨架
3.1 指令驱动骨架:SKILL.md + settings.json
指令驱动的核心是把“做什么”写清楚,把“怎么做”留给模型推理。下面是一个可复制的代码审查 Skill 骨架,放在项目.agent/skills/code_reviewer/SKILL.md:
--- name: code_reviewer description: "分析代码中的 bug、性能问题和最佳实践。当用户请求代码审查时调用。" version: 1.2.0 --- ## Instructions 1. 解析代码,识别语言与框架特征 2. 检查常见 bug 与反模式(空指针、越界、未处理异常) 3. 评估性能问题(N+1 查询、低效算法、重复计算) 4. 核对语言级最佳实践 5. 生成结构化报告,按严重程度排序 ## Constraints - 只报告 critical / high / medium 三级问题 - 每条问题必须给出 line_number 和可执行建议 - 不得编造代码中不存在的问题 ## Output Format { "issues": [ { "severity": "critical|high|medium", "category": "bug|performance|best_practice", "line_number": 42, "description": "string", "suggestion": "string" } ], "overall_score": 0.0 }配套的settings.json放在项目根目录,负责把模型入口和 Skill 目录挂上:
{ "agent": { "skills_dir": ".agent/skills", "model": { "base_url": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "model_name": "claude-3.5-sonnet" }, "execution": { "max_steps": 8, "timeout_seconds": 60, "enable_tool_calls": true } } }这里的关键点是api_key_env指向环境变量,而不是把 Key 明文写进去。启动前执行:
export TAOTOKEN_API_KEY="你的Key"3.2 代码实现骨架:config.toml + 工具脚本
当 Skill 需要确定性执行时,比如“抓取新闻并去重”,就不能只靠指令。下面用config.toml声明工具入口,把确定性逻辑交给 Python 脚本:
[skill] name = "news_aggregator" description = "抓取、过滤、分析多源实时新闻" version = "1.1.0" [skill.instructions] file = "SKILL.md" [skill.tools.fetch_news] command = "python3 scripts/fetch_news.py" args = ["--source", "{source}", "--limit", "{limit}", "--keyword", "{keyword}"] timeout = 30 [skill.tools.dedup] command = "python3 scripts/dedup.py" args = ["--input", "{raw_json}", "--output", "{dedup_json}"] timeout = 10 [model] base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model_name = "claude-3.5-sonnet"对应的scripts/fetch_news.py只做确定性的事——发请求、解析 JSON、落盘,不做“判断哪条新闻重要”这种推理活:
import argparse import json import urllib.request def fetch(source: str, limit: int, keyword: str) -> list: url = f"https://news.example.com/api?source={source}&limit={limit}&q={keyword}" with urllib.request.urlopen(url, timeout=10) as resp: data = json.loads(resp.read().decode("utf-8")) return data.get("items", []) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--source", required=True) parser.add_argument("--limit", type=int, default=20) parser.add_argument("--keyword", default="") args = parser.parse_args() items = fetch(args.source, args.limit, args.keyword) print(json.dumps({"items": items}, ensure_ascii=False))这样拆完之后,Agent 负责“选哪个源、怎么过滤、怎么组织报告”,脚本负责“把数据拿回来”。指令驱动和代码实现各管一段,边界清晰。
3.3 两种架构的对照表
| 维度 | 指令驱动架构 | 代码实现架构 |
|---|---|---|
| 核心载体 | SKILL.md 文字描述 | config.toml + 脚本 |
| 确定性 | 低,依赖模型推理 | 高,逻辑固定 |
| 可测试性 | 需契约测试 | 可写单元测试 |
| 修改成本 | 改一行文字即可 | 改代码、重测、重部署 |
| 适合场景 | 意图理解、多步推理、动态决策 | 数据抓取、格式转换、外部调用 |
| 性能可控性 | 弱 | 强 |
4. 验证请求:确认 Skill 真的被调用
配置写完不算完,必须验证。第一步,用模型对话页面发一条会触发 Skill 的请求,观察返回结构是否符合Output Format。如果返回里没有issues字段,说明指令没被正确解析。
第二步,用命令行直接打 API,确认模型入口通:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-3.5-sonnet", "messages": [ {"role": "system", "content": "你是一个代码审查 Skill,严格按 SKILL.md 的 Output Format 输出 JSON。"}, {"role": "user", "content": "审查这段代码:def f(x): return x[10]"} ] }' | python3 -m json.tool成功的结果是返回体里choices[0].message.content是一段合法 JSON,且包含severity、line_number、suggestion三个字段。如果返回的是自然语言段落,说明指令里的 Output Format 约束不够强,需要把“必须输出 JSON”提到 Instructions 第一条。
第三步,验证工具脚本能被正确调用。在 config.toml 里配好fetch_news后,让 Agent 执行一次抓取,检查scripts/目录下是否生成了中间 JSON 文件。这一步能区分“指令没生效”和“脚本没跑起来”两类问题。
5. 本篇常见错排查
5.1 Skill 不触发
最常见的原因是description写得太泛。比如只写“处理代码”,Agent 无法判断何时调用。改成“分析代码中的 bug、性能问题和最佳实践,当用户请求代码审查时调用”,触发率明显提升。description 里要包含“什么时候用”,而不只是“能做什么”。
5.2 输出结构不稳定
指令驱动下模型每次输出格式飘,是因为约束不够硬。解决办法是在 SKILL.md 里加一段## Output Format,并明确写“必须输出合法 JSON,不得包含解释性文字”。如果还是飘,就在系统提示里再强调一次,形成双重约束。
5.3 脚本调用报路径错误
config.toml 里的command是相对路径时,工作目录不同就会找不到脚本。统一改成绝对路径,或者在启动 Agent 前cd到项目根目录。另外args里的占位符{source}必须和 Agent 传入的参数名完全一致,大小写敏感。
5.4 密钥泄露风险
把 Key 写进 SKILL.md 或 config.toml 是高频错误。Agent 读取指令文件时可能把 Key 带进上下文,造成泄露。正确做法是统一用api_key_env指向环境变量,配置文件里只留变量名。
5.5 指令和代码职责重叠
有人在 SKILL.md 里写“用 Python 实现去重”,又在脚本里写去重逻辑,结果 Agent 以为要自己写代码去重,和脚本冲突。记住原则:指令只描述“做什么”和“输出什么”,具体“怎么做”交给脚本。
6. 该用文字还是该写代码:判断清单与下一步
判断标准其实很简单。如果这个 Skill 的输出需要“每次都不一样但都合理”,比如新闻摘要、根因分析、策略建议,用指令驱动。如果输出必须“每次完全一致”,比如金额计算、格式转换、数据校验,用代码实现。混合架构是最常见的落地形态:指令负责编排和推理,代码负责确定性执行。
下一步建议你从最小闭环开始:先写一个只有 Instructions 和 Output Format 的 SKILL.md,用模型对话页面验证它能被触发、能按格式输出。确认没问题后,再把其中确定性最强的部分抽成脚本,配到 config.toml 里。这样每一步都可验证,不会一上来就搭一个跑不起来的复杂架构。
接入文档里有完整的 Skill 配置字段说明和示例,遇到字段不生效时对照排查:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。Key 的创建和管理在控制台完成:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 。如果你要跑的是长期编码类 Agent,直接用 Coding Plan 的额度更划算:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。