1. 为什么你的 OpenClaw 在嵌入式 Linux 上只会“动嘴”如果你已经在 OK1126B-S 这类开发板上跑通了 OpenClaw也接上了本地模型或者飞书入口大概率会遇到一个很尴尬的场景你问它“板子上有哪些 LED”它能答得头头是道你让它“把 work 灯点亮”它回你一段看起来正确、但根本没执行的命令。问题不在模型而在于它没有“手”。OpenClaw 本身是一个对话与任务编排框架模型负责理解意图但真正去读写/sys/class/leds/、操作 GPIO、跑一段 shell 的是 Skills 机制。没有 SkillOpenClaw 就只是一个装在开发板上的聊天窗口有了 Skill它才会在识别到“点灯”“闪烁”“读 GPIO”这类意图时主动去调用本地脚本并返回真实执行结果。这篇就围绕嵌入式 Linux 场景把 Skills 和 SKILL.md 讲清楚Skill 目录放哪、SKILL.md 怎么写、scripts 里的 GPIO 脚本怎么组织最后给一条可以直接复制运行的 GPIO 读写验证动作让你确认 OpenClaw 是真的在“干活”而不是在“背课文”。适合已经在开发板上部署过 OpenClaw、想让它接管硬件外设的嵌入式开发者。2. 前置准备TaoToken 与 OpenClaw 的接入位置在写 Skill 之前先把模型调用这条链路理顺。OpenClaw 的“大脑”需要稳定的模型接口我这边习惯用 TaoToken 来做统一接入它的 API 地址是https://taotoken.net/api兼容常见的 OpenAI 风格调用方式配置到 OpenClaw 的模型后端里就行。具体操作上先在 TaoToken 控制台创建一个 API Key然后把它填到 OpenClaw 的模型配置中。控制台入口在这里控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建 Key 的页面API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite如果你还没决定用哪个模型可以先去模型对话页面试一下确认模型对“GPIO”“LED”“shell 脚本”这类嵌入式语义的理解是否到位模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite接入文档里有 OpenClaw 这类客户端的具体配置字段说明建议对照着填接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite这一步的意义在于Skill 负责“做什么”模型负责“判断该不该做、用哪个参数做”。两者缺一不可。模型接口不稳定Skill 触发就会时灵时不灵Skill 写得不清楚模型再强也不知道该调哪个脚本。3. 可复制配置SKILL.md 骨架与 Skills 目录3.1 Skill 目录结构与命名规范OpenClaw 默认从下面这个路径加载 Skill~/.openclaw/workspace/skills/${SKILL_NAME}一个完整的 Skill 目录长这样gpio-led-control/ ├── SKILL.md # 核心元数据 操作手册 ├── scripts/ # 可直接运行的脚本 │ ├── led_on.sh │ ├── led_off.sh │ └── led_blink.sh ├── references/ # 按需加载的参考资料 │ └── ok1126b-led-map.md └── assets/ # 输出用资源不参与推理 └── led-report-template.md目录名有硬性规范只能用小写字母、数字和连字符比如gpio-led-control。我踩过的坑就是一开始用了下划线gpio_led_control结果 OpenClaw 死活不加载排查半天才发现是命名问题。这一点在嵌入式场景里尤其要注意因为很多工程师习惯用下划线命名脚本。3.2 SKILL.md 的元数据部分SKILL.md 分两段前置元数据和正文。元数据用---包裹负责让 OpenClaw 识别和语义匹配--- name: gpio-led-control description: 控制嵌入式 Linux 开发板上的 GPIO LED支持点亮、熄灭、按节奏闪烁适用于 OK1126B-S 等板卡。 user-invocable: true ---name和description是必填。description写得越贴近用户真实说法触发越准。比如用户会说“让灯闪起来”“work 灯亮一下”那 description 里就该出现“点亮”“熄灭”“闪烁”这些词而不是只写“LED 控制”。3.3 SKILL.md 正文操作手册怎么写正文是给模型看的“行动指南”要写清楚什么时候执行、执行哪个脚本、参数怎么传。下面是一份可以直接改的骨架# GPIO LED Control - 开发板 LED 灯控制 控制 OK1126B-S 等开发板上的系统 LEDwork / net 等。 ## 快速开始 ### 查看可用 LED 执行ls /sys/class/leds/ ### 点亮指定 LED 执行bash scripts/led_on.sh led_name 示例bash scripts/led_on.sh work ### 熄灭指定 LED 执行bash scripts/led_off.sh led_name ### 按节奏闪烁 执行bash scripts/led_blink.sh led_name interval_ms count 示例bash scripts/led_blink.sh work 500 6 ## 使用场景示例 - 用户说“把 work 灯点亮” → 调用 led_on.sh work - 用户说“让 net 灯闪 6 次每次 500 毫秒” → 调用 led_blink.sh net 500 6 - 用户说“现在有哪些灯” → 执行 ls /sys/class/leds/ ## 权限说明 操作 /sys/class/leds/ 通常需要 root 权限脚本内已包含 sudo 判断。 ## 注意事项 - 执行前先确认 LED 名称存在不存在则返回错误提示。 - 闪烁间隔不要低于 100ms避免占用过多 CPU。正文里把“用户可能怎么说”和“对应执行什么”一一列出来模型匹配起来就稳。很多人 Skill 不触发不是模型笨是正文里只写了命令没写触发语。3.4 scripts 里的 GPIO 脚本scripts/放固定逻辑的脚本避免模型每次现生成代码。以led_blink.sh为例#!/bin/bash # led_blink.sh - 按节奏闪烁指定 LED LED_NAME$1 INTERVAL_MS${2:-500} COUNT${3:-6} LED_PATH/sys/class/leds/${LED_NAME} if [ ! -d $LED_PATH ]; then echo ERROR: LED ${LED_NAME} 不存在可用 LED ls /sys/class/leds/ exit 1 fi for i in $(seq 1 $COUNT); do echo 1 ${LED_PATH}/brightness sleep $(echo scale3; ${INTERVAL_MS}/1000 | bc) echo 0 ${LED_PATH}/brightness sleep $(echo scale3; ${INTERVAL_MS}/1000 | bc) done echo OK: ${LED_NAME} 已闪烁 ${COUNT} 次间隔 ${INTERVAL_MS}ms脚本最后一定要输出明确的结果字符串OpenClaw 会把这段回显给用户用户才知道是真执行了。4. 验证请求确认 OpenClaw 真的在主动执行配置完成后重启 OpenClaw 让它重新加载 Skill 目录openclaw restart # 或者 systemctl --user restart openclaw然后通过飞书或本地对话入口发一条自然语言指令让 work 灯闪 6 次每次间隔 500 毫秒预期行为是OpenClaw 识别意图 → 匹配gpio-led-control→ 读取 SKILL.md → 调用scripts/led_blink.sh work 500 6→ 返回类似下面的结果OK: work 已闪烁 6 次间隔 500ms同时你盯着开发板work 灯应该真的在闪。如果灯闪了、回显也对说明 OpenClaw 已经从“只会答”变成“会做”了。再补一条 GPIO 读写的直接验证确认底层通路没问题# 读一个 GPIO 的当前方向 cat /sys/class/gpio/gpio12/direction # 导出并设置为输出点亮 echo 12 /sys/class/gpio/export echo out /sys/class/gpio/gpio12/direction echo 1 /sys/class/gpio/gpio12/value # 读取当前值 cat /sys/class/gpio/gpio12/value把这段逻辑也封装成scripts/gpio_rw.sh在 SKILL.md 里加一条“读写任意 GPIO”的说明OpenClaw 就能接管更通用的引脚操作而不只是板载 LED。5. 本篇常见错排查Skill 不加载九成是目录名不规范。检查是否用了下划线、大写字母或中文。必须是小写字母数字连字符。Skill 加载了但不触发看 SKILL.md 的description和正文触发语。用户说“闪一下”你只写了“闪烁控制”匹配度就低。把口语化说法补进去。脚本执行报权限错误/sys/class/leds/和/sys/class/gpio/多数需要 root。要么脚本里加 sudo要么给 OpenClaw 运行用户配置对应的 udev 规则。回显是模型编的灯没动说明模型没真正调用脚本而是自己“脑补”了结果。检查 SKILL.md 里是否明确写了“必须执行 scripts 下的脚本不得自行编造输出”。闪烁间隔异常sleep不支持小数时用bc或改成毫秒级usleep。上面脚本用了bc如果板子上没装换成整数秒或sleep 0.5的写法。GPIO 导出失败部分内核已经废弃 sysfs GPIO改用libgpiod。这时把脚本里的echo /sys/class/gpio/换成gpioset/gpioget命令即可SKILL.md 里同步更新调用方式。6. 让 OpenClaw 长期接管嵌入式任务单次点灯只是验证。真正让 OpenClaw 在嵌入式 Linux 上长期干活建议把常用外设都做成独立 SkillUART 收发、I2C 读传感器、SPI 驱动屏幕、PWM 调电机。每个 Skill 一个目录SKILL.md 写清触发语和脚本入口scripts 里放稳定脚本references 里放寄存器手册和引脚映射。如果你打算让它承担更连续的编码和 Agent 任务比如自动写驱动、批量改设备树、跑回归脚本可以了解下 Coding Plan把长期编码场景的额度规划好Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewriteClaude Code 这类编码 Agent 的接入方式在文档里也有说明ClaudeCodeAnthropichttps://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-code-anthropicutm_campaignrewrite回到最实际的一点先把gpio-led-control这个 Skill 跑通看着灯真的闪起来再去扩展下一个外设。嵌入式场景里能动手的 OpenClaw价值远大于能聊天的 OpenClaw。
