ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenClaw Skill 实战:用 SKILL.md 把 wttr.in 天气查询封装成可复用技能

OpenClaw Skill 实战:用 SKILL.md 把 wttr.in 天气查询封装成可复用技能

1. 从零跑通 OpenClaw Skill:天气查询为什么是最好的第一个练手项目

如果你刚接触 OpenClaw,看到 skills 目录里一堆现成的技能,心里大概会冒出一个念头:我能不能自己写一个?答案是可以,而且门槛比你想的低。OpenClaw 的 Skill 机制本质上就是「一份 Markdown 说明书 + 一段可执行的命令」,模型读到这份说明书后,就知道在什么场景下该调用什么命令、参数怎么填、结果怎么解读。它不是什么需要编译打包的插件,也不需要你写复杂的注册代码,一个文件夹加一个 SKILL.md 就能跑起来。

天气查询之所以适合当第一个自定义 Skill,原因有三个。第一,它不需要 API Key,wttr.in 这个服务直接 curl 就能拿到结果,省去了申请密钥、配置环境变量的麻烦,让你能把注意力集中在 Skill 本身的结构上。第二,它的输入输出足够简单,输入是城市名,输出是一行天气文本,调试的时候一眼就能看出对错。第三,它足够实用,跑通之后你真的可以每天用它查天气,而不是做完就扔的玩具。

这篇文章会带你走完完整链路:先理解 SKILL.md 的字段结构,再写出一份可以直接复制的配置,然后配置 wttr.in 的请求参数,最后在本地触发验证。整个过程你只需要一个能跑 Node 的环境和 curl,不需要额外的账号。我试过把这套流程走了一遍,从建目录到看到天气输出,大概十分钟。下面按步骤拆开讲。

2. OpenClaw Skill 机制与 SKILL.md 字段结构详解

在动手写之前,得先搞清楚 OpenClaw 是怎么发现和加载 Skill 的。OpenClaw 启动时会扫描 skills 目录,每个子目录代表一个技能,目录里的 SKILL.md 就是这个技能的「身份证 + 使用手册」。模型在规划任务时,会读取所有 SKILL.md 的元信息,判断当前用户请求是否匹配某个技能。匹配上了,它就会按照 SKILL.md 里写的命令去执行,再把执行结果组织成自然语言回复给你。

SKILL.md 的结构分两部分:头部是 YAML front matter,用---包起来,描述技能的元信息;下面是 Markdown 正文,写给模型看的操作说明。头部字段里,name是技能标识,description是一句话说明这个技能干什么,模型主要靠它来判断要不要用这个技能。homepage指向文档地址,方便你后续查参数。metadata里可以放一些扩展信息,比如 emoji 图标、依赖的可执行文件。

这里有个容易踩的坑:description写得太模糊,模型就不知道什么时候该调用它。比如你写「查询信息」,模型根本判断不出是查天气还是查快递。所以要写清楚「Get current weather and forecasts」,把能力边界说明白。另一个坑是requires.bins,如果你声明了依赖 curl,但系统里没装 curl,技能就会加载失败。所以写之前先确认which curl有输出。

正文部分才是真正给模型看的「操作手册」。它需要包含:这个技能能做什么、用哪个命令、参数怎么传、输出长什么样、有什么注意事项。模型读完这些,就能自己拼出正确的命令。你可以把它理解成写给一个聪明但没背景知识的实习生的文档,越具体越好。下面这张表帮你快速对照各字段的作用。

字段作用是否必填
name技能唯一标识,目录名通常与之一致是
description一句话能力说明,模型据此判断是否调用是
homepage文档或服务地址否
metadata.openclaw.emoji技能图标否
metadata.openclaw.requires.bins依赖的命令行工具否

理解了这些,你就知道 SKILL.md 不是随便写写的说明文档,而是模型决策的依据。写得好,模型调用得准;写得含糊,模型要么不调用,要么调用错。接下来我们就按这个结构,把天气技能写出来。

3. 可复制配置:weather/SKILL.md 完整写法与 wttr.in 参数

先建目录。OpenClaw 的 skills 路径取决于你的安装方式,用 nvm 装的 Node,全局包一般在~/.nvm/versions/node/<版本>/lib/node_modules/openclaw/skills/下面。你可以先找到这个路径:

npm root -g

输出类似/Users/you/.nvm/versions/node/v22.22.0/lib/node_modules,那么 skills 目录就是它下面的openclaw/skills。进去建一个 weather 文件夹:

cd $(npm root -g)/openclaw/skills mkdir weather && cd weather

然后创建 SKILL.md,把下面这份配置完整复制进去。注意 front matter 的缩进和冒号后的空格,YAML 对格式敏感,少一个空格都可能解析失败。

--- name: weather description: Get current weather and forecasts for a city (no API key required). homepage: https://wttr.in/:help metadata: openclaw: emoji: 🌤 requires: bins: - curl --- # Weather Two free services, no API keys needed. wttr.in is the primary one. ## Quick one-liner ```bash curl -s "wttr.in/London?format=3" # Output: London: ⛅ +8°C

Compact format

curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w" # Output: London: ⛅ +8°C 71% ↙5km/h

Full forecast

curl -s "wttr.in/London?T"

Format codes

%c condition · %t temp · %h humidity · %w wind · %l location · %m moon

Tips

  • URL-encode spaces: wttr.in/New+York
  • Airport codes: wttr.in/JFK
  • Units: ?m (metric) ?u (USCS)
  • Today only: ?1 · Current only: ?0
  • PNG: curl -s "wttr.in/Berlin.png" -o /tmp/weather.png

Open-Meteo (fallback, JSON)

Free, no key, good for programmatic use:

curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.12&current_weather=true"

Find coordinates for a city, then query. Returns JSON with temp, windspeed, weathercode. Docs: https://open-meteo.com/en/docs

这份配置里,`format=3` 是最简输出,适合快速看一眼;`format=%l:+%c+%t+%h+%w` 是自定义格式,把位置、天气状况、温度、湿度、风速拼在一起,信息密度高。`?T` 会输出带颜色的完整预报,适合终端里看。`?0` 只看当前,`?1` 只看今天。这些参数你可以在 SKILL.md 里都写上,模型会根据用户问法自己选。 如果你想让模型在 wttr.in 不可用时自动降级到 Open-Meteo,就把 fallback 那段也写进去。Open-Meteo 返回的是 JSON,字段是 `temperature`、`windspeed`、`weathercode`,模型能直接解析。注意 Open-Meteo 需要经纬度,所以你得先知道城市坐标,或者让模型先查坐标再查天气。这一步稍微复杂点,但作为 fallback 足够用。 写完保存,目录结构应该是 `skills/weather/SKILL.md`。你可以用 `cat` 确认一下内容没写乱: ```bash cat SKILL.md | head -20

看到 front matter 正常显示就说明文件没问题。接下来就是触发验证。

4. 本地触发验证:从 curl 到 OpenClaw 调用链路

验证分两步走。先单独测 curl 命令能不能通,再让 OpenClaw 去调用。这样出问题的时候你能快速定位是网络问题还是 Skill 配置问题。

第一步,直接跑命令:

curl -s "wttr.in/Beijing?format=3"

正常输出类似Beijing: ☀ +12°C。如果卡住不动,可能是网络到 wttr.in 不通,加个超时curl -s --max-time 10 "wttr.in/Beijing?format=3"。如果返回乱码,检查终端编码,或者加?T看彩色输出是否正常。这一步通了,说明命令本身没问题。

第二步,启动 OpenClaw,问它天气。具体启动方式取决于你的安装,通常是openclaw或npx openclaw。启动后输入类似「北京今天天气怎么样」或者「查一下 London 的天气」。模型应该会识别到 weather 技能,拼出 curl 命令并执行,然后把结果返回给你。

这里有个关键点:模型怎么知道该用哪个技能?它读的是所有 SKILL.md 的description。你的 description 写的是「Get current weather and forecasts for a city」,用户问天气时语义匹配,模型就会选中它。如果没选中,先检查 description 是不是太泛或者有拼写错误。

调用链路是这样的:用户输入 → 模型读技能列表 → 匹配 weather → 读 SKILL.md 正文 → 拼命令 → 执行 curl → 拿到输出 → 组织成回复。你可以在 OpenClaw 的日志里看到这个过程,如果它没调用技能,日志里会有「no matching skill」之类的提示。

验证成功后,你可以试试更复杂的问法,比如「北京和上海哪个更热」,模型可能会调用两次 curl 然后对比。或者「伦敦未来三天天气」,它会用?T或者?1参数。这些都能跑通,说明你的 Skill 已经真正可用了。

5. 常见报错排查:401、local proxy failed、reading choices 与 OAuth

跑 Skill 的过程中,报错基本集中在几类。下面按真实遇到的错误对照排查。

401 Unauthorized:这个通常不是 wttr.in 报的,wttr.in 不需要认证。如果你在 OpenClaw 里配了某个需要 Key 的模型服务,401 说明 Key 无效或过期。检查你的模型配置,确认 Base URL、Key、Model ID 三件套填对了。如果你用的是 TaoToken 这类服务,去 console 里重新生成一个 Key,然后更新配置。注意 Key 不要有多余空格。

local proxy failed:这个报错说明 OpenClaw 尝试走本地代理但失败了。常见原因是环境变量里配了HTTP_PROXY或HTTPS_PROXY,但代理服务没启动。检查env | grep -i proxy,如果有输出但代理不可用,先 unset 掉再试。另一个可能是端口被占用,换个端口或者关掉冲突进程。

reading choices 报错:这个一般出现在模型返回格式不符合预期的时候。比如你用的模型服务返回的 JSON 里没有choices字段,OpenClaw 解析就失败了。检查你的模型服务是否兼容 OpenAI 格式,Base URL 是不是指向了正确的 endpoint。如果是自建服务,确认返回结构里有choices[0].message.content。

OAuth 相关报错:如果你用的是需要 OAuth 的模型服务,报错可能是 token 过期或 scope 不对。重新走一遍授权流程,确认回调地址和配置里的一致。有些服务需要你在 console 里手动开启对应权限。

排查顺序建议:先确认 curl 命令本身能通,再确认模型服务配置正确,最后看 OpenClaw 日志里的具体错误行。大部分问题出在配置层,而不是 Skill 本身。Skill 写错了顶多是模型不调用或者调用参数不对,不会导致 401 这种认证错误。

另外提醒一句,SKILL.md 里的requires.bins如果写了 curl 但系统没有,技能加载会直接失败,日志里会有「missing binary」提示。用which curl确认一下,没有就装一个。

6. 把天气 Skill 用起来:从验证到日常调用的实用建议

跑通之后,你可以把这个 Skill 真正用起来。最直接的用法是每天早上问一句「今天天气」,模型调用 wttr.in 返回当前状况。如果你想要更结构化的输出,可以在 SKILL.md 里加一段说明,让模型把结果整理成「温度、湿度、风速、建议」的格式。比如加一句「Present the result as a short bullet list with temperature, humidity, wind, and a one-line suggestion.」模型就会按这个格式回复。

如果你经常查固定城市,可以在 SKILL.md 里写一个默认城市,比如「If no city is specified, default to Beijing.」这样你只说「查天气」它就知道查哪。但要注意,默认值写死了灵活性会降低,看你的使用习惯。

对于需要程序化处理的场景,Open-Meteo 的 JSON 输出更合适。你可以在 SKILL.md 里写清楚字段含义,让模型解析后返回结构化数据。比如问「北京现在温度多少」,模型可以只提取temperature字段返回一个数字,方便你后续做判断。

最后说一个实用技巧:把常用的几个城市做成快捷方式。在 SKILL.md 里加一段「Common cities: Beijing, Shanghai, London, New York」,模型看到用户说「查上海」时能更快匹配。这不是必须的,但能减少模型拼错城市名的概率。

整个流程走下来,你会发现 OpenClaw 的 Skill 机制核心就是「用 Markdown 描述能力,用命令实现能力」。天气查询是最小可跑案例,你可以照着这个结构封装更多技能,比如查汇率、查快递、查服务器状态。只要有一个能返回结果的命令,就能包装成一个 Skill。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进