1. 先搞清楚 SKILL.md 为什么加载失败:Pi Agent Skills 技能系统排查入门
Pi Agent 的 Agent Skills 技能系统,本质上是给 AI 装一套「按需翻阅的专业手册」。你写一个SKILL.md,Pi Agent 启动时扫描技能目录,把每个技能的name和description抽出来,以 XML 形式塞进系统提示词;当你的任务描述和某个技能匹配上,AI 才会用read工具把完整的SKILL.md读进来执行。这套机制叫渐进式披露,好处是平时不占上下文,需要时才加载。
但正因为「描述常驻、正文按需」,出问题的地方也特别集中:要么技能压根没被扫描到,要么扫描到了但description写得太糊导致不触发,要么触发后去读文件时撞上 401 或local proxy failed。我见过最多的场景是——目录结构看着没问题,SKILL.md也写了,可/skill:xxx命令敲下去没反应,或者调用脚本时直接报鉴权失败。
这篇就按「先定位是加载问题还是鉴权问题」的思路走。适合正在给 Pi Agent 接 Agent Skills、或者从 Claude Code / Codex 迁移技能过来的开发者。核心检索词就三个:Pi Agent、Agent Skills、SKILL.md。下面每一步都给可复制的目录、配置和验证命令,你照着做能自己判断卡在哪一层。
先记住一个判断原则:如果/skill:名称命令根本不存在,那是加载/注册问题;如果命令存在但执行时报 401 或 local proxy failed,那是鉴权或网络出口问题。这两类问题的排查路径完全不同,别混着查。
2. TaoToken 前置准备:给 Pi Agent Skills 配好可用的模型出口
Pi Agent 本身是个 Agent 框架,它要调用大模型才能跑起来,而技能系统里的脚本又经常需要访问外部 API。所以在你排查 SKILL.md 之前,得先保证模型调用这条链路是通的。我这边习惯用 TaoToken 作为统一的模型接入层,它的 API 地址是https://taotoken.net/api,兼容 OpenAI 风格的接口,Pi Agent 里配置 Base URL 就能接上。
为什么先讲这个?因为很多「SKILL.md 加载失败」的假象,其实是模型请求本身就没通——Pi Agent 启动时如果连不上模型,技能扫描和系统提示词注入可能直接中断,你看到的现象就是技能列表空的。所以先把模型出口理顺,再谈技能。
你需要准备三样东西,我称之为「三件套」:Base URL、API Key、Model ID。Base URL 填https://taotoken.net/api;API Key 去控制台创建,地址是https://taotoken.net/console/api-keys;Model ID 按你实际要用的模型填,比如claude-sonnet-4-5这类。这三个值在 Pi Agent 的配置里必须成对出现,缺一个都会导致请求失败。
如果你用的是 Claude Code 那套配置习惯,Pi Agent 的 settings 里通常长这样,路径一般在~/.pi/agent/settings.json或项目级.pi/settings.json:
{ "model": "claude-sonnet-4-5", "providers": { "taotoken": { "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的key", "model": "claude-sonnet-4-5" } }, "skills": [ "~/.pi/agent/skills", ".pi/skills" ] }注意skills数组这里,它决定了 Pi Agent 去哪些目录找技能。如果你把技能放在别的地方却没写进这个数组,那 SKILL.md 永远不会被扫描到——这是加载失败最常见的原因之一,比 401 还高频。
配好之后先别急着测技能,先验证模型这条链路。用 curl 直接打一次接口,确认 Key 和 Base URL 没问题:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的key" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-5", "messages": [{"role": "user", "content": "ping"}] }'返回里有正常的choices字段,说明模型出口通了。这一步过了,再往下查技能系统才有意义。如果这里就报 401,那问题在 Key 或 Base URL,跟 SKILL.md 无关。
3. 可复制的 SKILL.md 目录结构与注册配置片段
现在进入正题。Pi Agent 的 Agent Skills 标准里,一个技能就是一个包含SKILL.md的目录。目录结构建议这样组织,我直接给一份能跑的:
my-skill/ ├── SKILL.md # 必需:Frontmatter + 指令正文 ├── scripts/ │ └── process.sh # 辅助脚本 ├── references/ │ └── api-reference.md # 按需加载的详细文档 └── assets/ └── template.jsonSKILL.md的格式是 YAML Frontmatter 加 Markdown 正文。Frontmatter 里name和description是必填的,name最多 64 字符,只能小写字母、数字、连字符;description最多 1024 字符,这是 AI 判断要不要加载你技能的唯一依据,必须写具体。给你一份可直接复制的:
--- name: brave-search description: 通过 Brave Search API 进行网页搜索和内容提取。适用于搜索文档、事实查询或任何网页内容检索场景。 license: MIT compatibility: 需要 Node.js 18+ 环境 metadata: author: your-name allowed-tools: - read - bash --- # Brave Search ## 安装 首次使用前安装依赖: ```bash cd /path/to/brave-search && npm install搜索
./search.js "查询关键词" # 基础搜索 ./search.js "查询关键词" --content # 包含页面内容参考
详见 参考指南
这里有个坑要提醒:`description` 千万别写成「一个搜索技能」这种。AI 匹配是靠语义的,太模糊会导致该触发时不触发、不该触发时乱触发。写清楚「做什么 + 什么时候用」,比如上面那样点明「搜索文档、事实查询、网页内容检索」。 技能放哪?Pi Agent 支持多个加载位置,作用范围不同,对照表如下: | 位置 | 作用范围 | 加载规则 | |------|----------|----------| | `~/.pi/agent/skills/` | 全局 | 根目录 .md 文件和含 SKILL.md 的目录都递归发现 | | `~/.agents/skills/` | 全局 | 仅含 SKILL.md 的目录被递归发现,根目录 .md 忽略 | | `.pi/skills/` | 项目 | 根目录 .md 文件和含 SKILL.md 的目录都递归发现 | | `.agents/skills/` | 项目 | 仅含 SKILL.md 的目录被递归发现 | | Pi Packages | 全局/项目 | `skills/` 目录或 package.json 的 `pi.skills` 条目 | 如果你是从 Claude Code 或 Codex 迁移过来的,可以直接在配置里挂载它们的技能目录,不用手动搬: ```json { "skills": [ "~/.claude/skills", "~/.codex/skills", "../.claude/skills" ] }注意最后那个../.claude/skills是项目级相对路径的写法。路径写错是加载失败的第二大原因,尤其是相对路径,基准目录搞错就全盘找不到。建议先用绝对路径跑通,再换成相对路径。
4. 验证技能是否生效:从命令注册到实际调用的完整检查动作
配置写完了,怎么确认技能真的被加载了?别靠感觉,按下面这套动作逐步验证。
第一步,确认命令注册。每个 Skill 会自动注册成/skill:名称命令。启动 Pi Agent 后,输入/skill:看有没有补全提示,或者直接敲/skill:brave-search。如果命令不存在,说明技能没被扫描到,回到第 3 节检查skills数组和目录结构。如果命令存在,说明加载成功,进入下一步。
第二步,手动调用验证。命令后的参数会以User: 参数的形式追加到技能内容里。比如:
/skill:brave-search extract https://example.com这一步能跑通,说明 SKILL.md 正文被正确读取了。如果这里报local proxy failed,那问题在脚本执行时的网络出口,不在技能加载。
第三步,验证自动触发。技能系统真正的价值是 AI 自动判断加载。你直接说一句「帮我搜一下 Pi Agent 的官方文档」,看 AI 会不会自动去读 brave-search 这个技能。如果不会,八成是description写得太糊,回去改描述。
第四步,验证脚本鉴权。技能里的脚本如果要访问外部 API,单独跑一次确认 Key 有效:
cd my-skill && ./scripts/process.sh "test input"如果这里报 401,那是脚本自己的鉴权配置问题,跟 Pi Agent 无关。检查脚本里的 API Key 环境变量有没有正确注入。
第五步,看系统提示词注入。如果 Pi Agent 支持导出当前系统提示词,检查里面有没有你的技能描述以 XML 形式出现。没有的话,说明扫描阶段就漏了。
这套动作走下来,基本能定位到具体是哪一层出问题。我实测下来,80% 的「加载失败」都卡在第一步和第二步之间——要么路径没配对,要么description太模糊。
5. 常见报错排查:401、local proxy failed、reading choices 逐个击破
现在把几个高频报错单独拎出来讲,每个都给判断依据和修法。
401 Unauthorized。这个最直接,就是鉴权失败。分两种情况:如果是模型请求报 401,检查settings.json里的apiKey和baseUrl是否配对,Key 有没有过期,去https://taotoken.net/console/api-keys重新生成一个。如果是技能脚本报 401,检查脚本读取 Key 的方式,常见错误是环境变量名写错,或者.env文件没被加载。用 curl 单独测一次脚本要调的接口,能快速区分。
local proxy failed。这个报错通常出现在脚本执行阶段,意思是本地代理或网络出口没配好。注意,这里说的不是让你去搞什么特殊网络工具,而是检查脚本里的请求地址、端口、超时设置。常见原因是脚本硬编码了一个本地端口,但那个服务没起来。排查方法:把脚本里的请求 URL 打印出来,手动 curl 一次,看是不是地址本身就不通。另外检查HTTP_PROXY/HTTPS_PROXY这类环境变量有没有被意外设置成无效值。
reading choices 相关报错。这类错误一般出现在解析模型返回时,说明请求发出去了但返回结构不对。可能是 Model ID 填错,导致返回的不是标准 chat completion 格式;也可能是 Base URL 少了/v1路径。检查你的baseUrl是不是https://taotoken.net/api,请求路径拼出来应该是https://taotoken.net/api/v1/chat/completions。Model ID 要和实际可用模型一致,别写个不存在的名字。
OAuth 相关报错。如果你用的是需要 OAuth 的模型服务,报错通常提示 token 刷新失败。检查 refresh token 有没有过期,或者授权范围对不对。这类问题建议直接换成 API Key 方式接入,省去 OAuth 的复杂度。
技能命令不出现。不是报错但更让人抓狂。检查三件事:skills数组路径对不对、目录里有没有SKILL.md(注意大小写,必须全大写)、Frontmatter 的name字段格式对不对(只能小写字母数字连字符)。还有一个隐藏坑:如果你设了disable-model-invocation: true,技能会从系统提示词里隐藏,只能手动/skill:name调用,别以为是加载失败。
从 Claude Code 迁移后技能失效。检查挂载路径的基准目录。~/.claude/skills是绝对路径没问题,但../.claude/skills这种相对路径,基准是你启动 Pi Agent 的目录,不是配置文件所在目录。建议统一用绝对路径。
排查时养成一个习惯:先分层,再定位。模型层、加载层、执行层分开测,别一上来就改 SKILL.md,很多时候问题根本不在那。
6. 把技能系统跑顺之后:接入文档与长期编码方案
技能系统调通之后,日常使用还有几个提效点。如果你经常需要验证某个模型在技能场景下的表现,可以直接用模型对话页面快速试,地址是https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite,不用每次都起完整的 Pi Agent。
接入细节和参数说明,官方文档写得比较全,遇到配置项不确定的时候查这里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite。API Key 管理在https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite,建议给不同项目建不同的 Key,方便排查问题时隔离。
如果你是要长期跑编码类 Agent 任务,或者技能系统里挂了很多自动化脚本,用 Coding Plan 会更省心,地址是https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite。它针对长时间、高频次的编码场景做了优化,比按次调用更适合技能系统这种反复触发的用法。
最后说个我踩过的坑:技能目录里的脚本,权限一定要给对。chmod +x scripts/process.sh这步很多人忘,结果就是技能加载成功、命令也注册了,一执行就报权限拒绝,还以为是 401。另外第三方技能在跑之前,务必先读一遍SKILL.md和脚本内容,技能里的指令可以要求 AI 执行任意操作,包括运行可执行文件,安全审查不能省。