Skill 测试与调试 - OpenClaw | JR Academy
Skill 测试与调试
写完 SKILL.md 不测就发布?那是给自己挖坑呢。但说实话 Markdown 格式的 Skill 调试跟传统代码调试不太一样——你没法像写 TypeScript 那样跑单元测试,因为 Skill 本身就是给 Agent 的指令文本嘛。调试的核心其实是:跟 Agent 对话,看它有没有按你 SKILL.md 里写的指令来做。
去年十一月第一次写 Skill 的时候,我发现 Agent 完全没理我写的流程步骤,后来才发现是指令写得太模糊了——就写了个"帮用户查天气",Agent 理解得一塌糊涂。摸索了一阵之后才找到比较顺手的工作流。
Workspace Skill 开发模式
开发调试的最佳方式是用 workspace skill——直接在项目目录的 ./skills/ 里写:
# 创建 workspace skill 目录
mkdir -p ./skills/my-skill
# 写你的 SKILL.md(改了保存就生效,不需要重新安装)
workspace skill 的好处是改了 SKILL.md 重新激活就能测,不用走 clawhub publish → clawhub install 的发布流程。开发阶段全程用这种方式,确认没问题了再发到 ClawHub。
Skill 文件存放位置分两种:
- 全局 managed skills:
~/.openclaw/skills/(通过clawhub install安装的) - 项目 workspace skills:
./skills/(当前项目独有的,只在这个项目目录下生效)
测试方式
对话测试(核心方法)
因为 Skill 是 Markdown 指令,最直接的测试方式就是跟 Agent 对话,看它执行得对不对:
# 启动 Gateway 的 WebChat UI
openclaw gateway --verbose
# 打开 http://127.0.0.1:18789/
在 WebChat 里可以像真实用户一样对话来测。重点关注几个方面:
- Agent 有没有理解你的 Skill 指令 — 你让它做的事,它做了没?
- 执行步骤对不对 — 如果你在 SKILL.md 里写了多个步骤,它是不是按顺序来的?
- 输出格式对不对 — 你指定了格式,它有没有遵守?
- 边界情况怎么处理 — 用户输入不完整或者错误信息,Agent 怎么反应?
这跟写单元测试的思路不一样——你是在"面试" Agent,看它有没有把你的指令理解透。说实话这个过程更像调 prompt 而不是调代码,需要反复修改 SKILL.md 的措辞直到 Agent 行为符合预期。
CLI 快速验证
不想开 WebChat 的话,命令行也能做基本检查:
# 验证 SKILL.md 格式和 frontmatter
openclaw skills validate ./my-skill
# 查看 Skill 加载状态
openclaw skills list
openclaw skills info my-skill
validate 会检查 SKILL.md 的 frontmatter 格式对不对、必填字段有没有缺、requirements 声明合不合理。这步特别容易忘对吧?但真能帮你抓不少低级错误。比如 YAML frontmatter 里缩进用了 Tab 而不是空格——这种错误不 validate 的话你得在运行时慢慢排查,问我怎么知道的?别问。
脚本测试
如果你的 Skill 包含 scripts/ 目录里的可执行脚本,这些脚本本身可以独立测试——它们就是普通代码嘛:
# 直接跑脚本看输出对不对
python ./skills/my-skill/scripts/fetch-data.py --city Sydney
# 或者 shell 脚本
bash ./skills/my-skill/scripts/check-status.sh
脚本是普通代码,该写单元测试写单元测试,该 mock 就 mock。这部分跟传统开发没区别。
日志与调试
查看日志
# 实时查看所有日志
openclaw logs -f
# 只看 Skill 相关日志
openclaw logs -f --filter skill
# 看特定 Skill 的日志
openclaw logs -f --filter "my-skill"
调整日志级别
# 在聊天中切换详细模式
/verbose
# 或在配置中设置
openclaw config set logLevel debug
开了 --verbose 或者 debug 级别之后,你能看到 Agent 的决策过程——它考虑了哪些 Skill、为什么选择或跳过某个 Skill、执行了什么操作。这步很关键,能看到 Agent 是压根没加载你的 Skill 还是加载了但没按指令执行。
openclaw doctor
这个命令特别有用但很多人不知道——
openclaw doctor
它会帮你做一系列检查:
- 配置文件
~/.openclaw/openclaw.json格式对不对(注意是 JSON5 格式) - Gateway Control Plane(
ws://127.0.0.1:18789)能不能连上 - 已安装的 Skill 有没有已知安全问题(ClawHavoc 之后加的检查)
- MCP Server 连接状态
- 权限和目录结构是否正确
碰到奇怪问题的时候先跑一下 openclaw doctor,能省掉很多排查时间。我现在养成了习惯,每次调试前先跑一下这个,就像看病先量个体温一样。
常见问题排查
Skill 没被加载
症状:你写了 Skill 但 Agent 对话中完全不理。
先检查基本的吧:
openclaw skills list # Skill 在列表里没
openclaw skills info my-skill # 状态是 active 还是 inactive
openclaw logs --filter "skill" --filter "error" # 有没有报错
最常见的几个原因:
- SKILL.md 位置不对 — workspace skill 必须放在
./skills/your-skill-name/SKILL.md这个路径下,不是随便放哪儿都行 - frontmatter 格式错误 — YAML 格式很严格,缩进错了、冒号后面没空格、用了 Tab 缩进,都会导致解析失败。
openclaw skills validate能查出来 - Skill 名冲突 — 如果 workspace skill 和 managed skill 同名,可能会有加载冲突
- 文件名写错了 — 必须是
SKILL.md,大小写敏感,写成skill.md或Skill.md就不认了
Agent 不按指令执行
这个问题比较隐蔽也比较气人。你明明在 SKILL.md 里写得清清楚楚,Agent 偏偏按自己的方式来。这合理吗?
原因几乎都是指令写得不够明确。几个改进方向:
- 用编号列表代替大段文字 — Agent 对结构化步骤的理解比散文好得多
- 加"必须"和"不要"这样的强约束 — 比如"必须先确认城市名称,不要直接猜测"
- 给具体的 input/output 示例 — Agent 会模仿你给的例子
## 正确的查询流程
1. **必须**先从用户消息中提取城市名称
2. 如果无法确定城市,**必须**主动询问,**不要**猜测
3. 调用 weather 工具获取数据
4. 按指定格式返回结果
### 示例
用户:明天出门要带伞吗
助手:你在哪个城市呢?我帮你查下天气。
群里老王总结过一条经验挺好用的:把 SKILL.md 当成给新员工写的操作手册——你觉得显而易见的东西,对 Agent 来说可能并不明显,得写清楚。说白了就是把 SKILL.md 的指令当 prompt engineering 来做...
references 目录里的文件没被读取
如果你在 references/ 里放了参考资料但 Agent 不用,大概率是你在 SKILL.md 的指令里没提到这些文件。Agent 不会自动去翻 references 目录的,你得在指令里明确写"参考 references/api-docs.md 中的 API 格式"。
数据没有持久化
看看数据目录的权限和路径:
ls -la ~/.openclaw/data/
目录不存在或者没写权限的话数据就存不进去。
调试工作流
我自己的习惯啊——
先在 ./skills/my-skill/ 里写好 SKILL.md,用 openclaw skills validate 确认格式没问题。
然后开 WebChat(openclaw gateway --verbose)跟 Agent 对话测试。反复修改 SKILL.md 的指令措辞直到 Agent 行为符合预期——这步最花时间,本质上是在调 prompt。
Agent 行为不对的话用 /verbose 打开详细日志看它的决策过程——这步很关键,能看到 Agent 是压根没考虑你的 Skill 还是考虑了但没按指令执行。
如果 Skill 里有 scripts,单独跑脚本确认逻辑正确。
最后发布前跑下 openclaw skills validate 和 openclaw doctor。别让配置问题到了用户手里才发现,那就很尴尬了...
几条建议
SKILL.md 要写得像操作手册。步骤清晰、约束明确、有示例。越具体越好,别指望 Agent 能"领会意思"。
先从简单 Skill 开始迭代。别一上来就写特别复杂的指令,先写最基本的流程跑通了,再逐步加复杂逻辑。每加一个步骤都测一下。
善用 references 目录。如果你的 Skill 需要大量背景知识(比如 API 文档、数据格式说明),别全塞进 SKILL.md 正文,放 references 里然后在指令中引用。这样 SKILL.md 保持简洁可读。
错误处理指令别偷懒。在 SKILL.md 里写清楚各种异常情况怎么处理——API 挂了告诉用户什么、参数不对怎么回复、数据找不到怎么办。这些不写的话 Agent 会自由发挥,结果往往不太好看。
想想看啊:如果你写了个代码审查 Skill,用户提交了一个空文件,Agent 应该说什么?"没有代码可审查"还是直接报错?在 SKILL.md 里把这种情况写清楚,用户体验会好很多。