☰
OpenClaw从玩具到工具:手把手教你编写自己的Skills技能体系
2026/10/14 4:38:08 网站建设 项目流程

先说说我自己的经历。某天我在准备一个AI编程专项的作业,要求把 OpenClaw 从“能跑通 Demo”变成“能解决我的实际问题”。装好 OpenClaw 的第一个下午,我兴致勃勃地让它试用内置的几个 Skills——写周报、搜信息、解释代码,它们确实演示得很顺。但到了第二天,我想让它把我电脑里乱七八糟的下载文件夹按我的规矩归类,它愣住了。它甚至告诉我,这个场景不在它已知的技能里。

那一刻我彻底同意标题里的判断:如果没有自己的 Skills,OpenClaw 只能是一个玩具。这篇复盘正是围绕这个判断展开的。我会先说清楚它为什么只是玩具,然后告诉你我是如何从零编写一个下载目录整理 Skills 的,最后总结出一套把单个技能扩展成技能体系的方法。内容不追求讲得多玄乎,只希望你读完能直接在自己的环境里动手,把 OpenClaw 变成真正替你干活的工具。

1. 为什么说“没有自己的Skills,OpenClaw只是玩具”

1.1 OpenClaw的本质是骨架,Skills才是肌肉

OpenClaw 这类智能体框架,核心本质是一个调度器:它调用大模型来理解你的意图,再调用外部工具来执行动作。也就是说,模型负责“思考”,而平台负责“连接”。如果你什么都不配置,它最多只能做三件事:跟你聊天、读一些通用文档、调用平台自带的几个示例技能。

我把这种状态叫作“骨架状态”。骨架没有肌肉,看起来有头有脚,但动弹不得。Skills 就是肌肉,是真实操作的载体。一个智能体的价值,不在于它拥有多大的模型参数,而在于它被允许调动多少种经过设计、适配场景、边界清晰的操作能力。

反过来说,为什么很多人玩了几天 OpenClaw 就觉得没意思?因为默认能力太薄。你问它“帮我写个周报”,它能做到;你问它“把上周所有项目文档汇总成一份带目录的清单”,它就蒙了。这个“蒙”不是模型不聪明,而是它不知道该调用什么技能、用什么规则去完成这件事。

1.2 内置Skills的通病:对谁都友好,就是对你不友好

几乎每个智能体框架都会带几个示例 Skills,比如网页搜索、文件读取、发送消息、跑一段 Python 代码。这些技能有个共同特点:设计者为了让所有人都能跑通,把触发方式、参数结构、输出格式全部标准化了。

标准化的另一面,就是无法适配个人规则。举个例子,我习惯把下载目录里的安装包单独扔到一个叫软件的子文件夹,但如果文件名里没有“setup”“install”等明显关键词,内置技能根本不会按我的习惯归类。我还会希望它整理完以后打印一个“今日归档统计”,而不是输出一堆原始路径。这些需求并不复杂,但内置技能永远无法预见到。

这就像一个公司只给你配了一把公用螺丝刀,能用,但拧不同形状的螺丝效率极低。你要解决的是自己的问题,就必须亲手打磨自己的螺丝刀,也就是自己的 Skills。

1.3 “玩具”与“工具”的分界线在哪里

我自己的判断标准有三条。第一,能否匹配你真实的重复性工作流。如果 OpenClaw 不能每天固定帮你完成一件你本来就要做的事,那它只适合演示。第二,能否处理你个人的私有规则。比如特定命名格式、特定分类逻辑、特定的权限边界,只有写进技能代码里,它才真正属于你。第三,能否被你自己调试和迭代。内置技能出了问题,你只能等官方更新;自建技能出了偏差,你可以立刻看日志、改规则、重新跑。

这三条合起来,就是“工具感”的来源。工具不是拿来展示的,是拿来干活并越用越顺手的。所以从今天开始,如果你想认真使用 OpenClaw,第一件事不是研究怎么把模型调得更好,而是坐下来想想:我最常做的一件事,能否把它变成一个属于自己的 Skills。

2. 从零搭建一个自己的Skills:先理解它的文件结构

2.1 Skills在OpenClaw里到底长什么样

在我使用的 OpenClaw 版本里,一个技能本质上是磁盘上的一个目录。目录里有三个关键部分:描述文件、说明文档、执行脚本。结构大致长这样:

skills/ download-sorter/ manifest.yaml SKILL.md scripts/ sorter.py

manifest.yaml负责告诉平台“这个技能叫什么、能做什么、需要哪些参数、用什么命令执行”。SKILL.md负责告诉大模型“你什么时候该调用它、怎么把用户的话翻译成参数”。scripts/里的脚本才是真正干活的程序。

很多人第一次写技能,只重视最后那个脚本,前面两个文件胡乱写。结果就是技能执行逻辑写得再完美,大模型根本识别不到它,等于白写。OpenClaw 的调度原理是:大模型先看manifest.yaml里的描述和参数说明,再读SKILL.md里的使用样例,确定要用这个技能后,才会按execute字段去启动脚本。

2.2 manifest和SKILL.md里的字段,哪些是真正要命的

manifest.yaml里最重要的不是名称,而是description和parameters_schema。description 写得越具体,模型就越容易在“用户说了一堆话”时判断出这个技能能不能用。parameters_schema 则决定用户输入怎么落到脚本参数上,格式不匹配,脚本就会收到一堆莫名其妙的字符串。

下面是我常用的一个配置骨架,你可以照抄后按自己需要改:

name: download_sorter description: 整理指定目录中的文件,按类型移动到对应子目录并规范命名。适合用户要求整理下载文件夹、桌面、临时目录时使用。 version: 1.0.0 trigger_examples: - "帮我把下载目录整理一下" - "把桌面的压缩包归类" - "整理一下我的临时文件目录" parameters_schema: directory: type: string description: 要整理的目录绝对路径,默认取当前用户的下载目录 default: "" dry_run: type: boolean description: 是否只预览整理结果而不真正移动文件,默认 true default: true execute: command: python3 args: - "scripts/sorter.py" - "--directory" - "{directory}" - "--dry-run" - "{dry_run}" allowed_actions: - file:read - file:list - file:move

dry_run这个参数我强烈建议保留。它不是给人看的,是给模型兜底的。模型在不确定操作影响时,可以先跑一次只读预览,把整理计划返回给用户确认,然后再执行真正移动。这个设计能避免大量误伤。

SKILL.md则是给大模型看的“说明书”,我更愿意把它理解成一个小手册。里面要写清楚:这个技能的边界是什么,比如“不会处理隐藏文件”“不会覆盖同名文件”;参数应该如何设置,比如用户说“桌面”时对应哪个绝对路径;如果遇到无法归类的情况,应该返回什么提示而不是直接报错。

2.3 为什么说脚本只是技能的一半,另一半是“说明书”

我最初犯过一个典型错误:只写脚本,不写说明书。脚本写的是“怎么执行”,说明书写的是“什么时候执行”。大模型不像人,它不会自己去看你的源码,更不会理解你隐藏的意图。它只能通过SKILL.md的文字描述来判断。

所以好的SKILL.md应该像你在给一个实习生布置任务:说清楚触发条件、操作边界、常见坑、失败时怎么办。比如这样写:

# download_sorter 当用户想整理下载目录、桌面或临时文件夹时使用本技能。 输入目录必须是绝对路径。如果用户只说了“下载目录”或“桌面”, 请获取系统默认路径后填入参数。 如果目录不存在,直接告诉用户目录不存在,不要尝试创建。 dry_run 参数默认为 true,在执行真实移动前必须先以预览模式运行一次。 输出格式:先输出分类统计,再输出每个文件将被移到的目标位置。

脚本负责“做到了”,说明书负责“做对事”。两者缺一不可。

3. 实战:给OpenClaw写一个“下载目录整理器”Skills

3.1 需求拆解:从“看不过去”到“可执行的规则”

我写这个技能的真实动机很简单:我的下载目录常年堆着几十个文件,各种命名混乱的文件、安装包、图片、压缩包混在一起。手动整理太累,而 OpenClaw 恰恰可以自动完成。

开始之前我先把需求拆成了四条规则。第一,根据扩展名分类:文档、图片、压缩包、安装包、其他。第二,文件名要规范:去掉首尾空格、把连续空格替换成下划线、保留原始扩展名。第三,同名文件不能覆盖:目标文件已经存在时,自动加时间戳后缀。第四,必须支持先预览再执行:避免模型一上来就把文件移动错地方。

拆完需求你就能发现,这其实不是程序设计,而是“规则建模”。所有让 OpenClaw 变得好用的技能,都来源于你把模糊的生活需求,翻译成确定性的判断逻辑。

3.2 我写的manifest配置(可以直接抄)

这个技能我命名为download_sorter,实际配置就是上一节那段 YAML。其中parameters_schema我特意只留了两个参数,一个是directory,一个是dry_run。参数越少,模型越容易理解。太多参数会增加模型填错的风险。

还有一个细节:allowed_actions我只给了file:read、file:list、file:move三个权限。没有给file:write或file:delete。为什么?因为整理目录本身只需要这三个权限,删除操作由用户自己决定。把权限列表收窄,可以避免某个意外情况导致文件被大范围改写。

3.3 处理脚本的几个关键片段

scripts/sorter.py我用了 Python 写,原因很简单:文件操作逻辑清楚,跨平台能力过得去,写起来也不费劲。核心函数大概是这个思路:

import argparse import os import re from pathlib import Path def classify(name: str) -> str: ext = Path(name).suffix.lower() if ext in {".pdf", ".docx", ".txt", ".md"}: return "文档" if ext in {".png", ".jpg", ".jpeg", ".gif", ".svg"}: return "图片" if ext in {".zip", ".tar", ".gz", ".7z", ".rar"}: return "压缩包" if re.search(r"(setup|installer|\.exe$|\.msi$|\.dmg$)", name.lower()): return "安装包" return "其他" def normalize_name(name: str) -> str: stem, ext = os.path.splitext(name) stem = stem.strip() stem = re.sub(r"\s+", "_", stem) return stem + ext.lower() if ext else stem

移动文件那一段我加了个保护逻辑:先判断目标目录是否存在,如果不存在则makedirs;再判断目标文件是否已存在,如果存在,就在文件主名后追加-YYYYMMDDHHMMSS后缀。用户看起来名字长一点,但不会出现丢失文件的情况。

整个脚本不是几十行就完事,但真正关键的就是这两块:分类和去重。分类规则定了,所有文件才有一个确定去向;去重逻辑定了,才敢让模型放手执行。

3.4 测试时才发现的问题:参数透传、相对路径、安全防护

写完脚本不代表完事,我至少调了四轮才让它稳定跑通。第一轮发现的问题是参数透传:manifest.yaml里{directory}如果模型没传,Python 脚本收到的是空字符串,直接导致Path("")指向当前目录,差点把整个 skill 目录当成下载目录整理。解决办法是在脚本里再次校验参数,如果不合法就返回提示,而不是硬着头皮执行。

第二轮是相对路径问题。OpenClaw 执行脚本时,工作目录可能是技能目录,也可能是用户项目目录,不确定。所以我在脚本里把所有路径都做了expanduser().resolve(),确保相对路径和波浪号都能转成绝对路径。从那以后,我再也没遇到过“文件跑到莫名其妙位置”的情况。

第三轮是安全防护问题。我先干跑一次--dry-run,然后让模型把整理计划汇报给用户,用户确认后才执行真实移动。实测下来,这个步骤虽然多了交互,但非常值得。因为模型理解“桌面”和“下载目录”时偶尔会填错路径,干跑一次能提前暴露问题。

第四轮是日志留痕。我在脚本里用了最简单的logging模块,每次整理都在技能目录下写一个sorter.log。日志里包含调用时间、参数、处理文件数量和异常信息。这个习惯让我后面排查问题省了大量时间。

4. 把Skills做“专”的五个决策点

4.1 输入设计:一句话说清楚“让技能做什么”

很多人设计技能时会把参数设计得很“技术化”,比如传一个 JSON 对象进去、传一个mode=fast之类的枚举值。我踩过这个坑之后明白了一个原则:参数要设计成让大模型一看就懂、一填就对。

比如我这个整理技能,只保留了directory和dry_run。用户说“整理一下桌面”,模型只需要把“桌面”转成路径;用户说“先看看会怎么样”,模型就知道把dry_run设为true。参数越接近自然语言,模型的填充准确率越高。反过来,如果参数是operation_mode=1这种,模型只能靠猜,猜错就出错。

4.2 权限设计:给技能最小触碰范围

给技能授权时,我遵循一个原则:能碰目录,就不碰全盘;能读取,就不给写入;能移动,就不给删除。很多人觉得授权越多越好,但智能体最怕的就是不可控。一个文件移动脚本如果同时拥有删除权限,一次路径写错,后果可能是灾难性的。

所以我会刻意在manifest.yaml里把allowed_actions写得尽量少。在后续技能设计里,我也建议你把“最小权限”写成一条硬性检查项。每次新增一个动作前,先问自己:这个动作真的是这个技能必须的吗?

4.3 粒度设计:一个技能只解决一个场景

刚开始写技能时,我总想做一个“万能文件管理技能”,把所有文件操作全部塞进去。结果发现,模型要在几十个参数里做选择,光解释清楚就很费劲,效果也很差。

现在我更倾向于“一个技能只做一件事”。下载目录整理是一个技能,日志快速检索是另一个技能,项目文件打包又是一个技能。每个技能边界清晰、描述简短,模型自然更容易在合适的时机调用。更重要的是,这些技能可以被组合:先整理文件,再生成归档清单,最后调用消息通知技能把结果发给自己。

4.4 错误设计:把异常返回给“大脑”而不是自己崩溃

脚本报错时,很多人的第一反应是让脚本崩溃,然后看日志找原因。但在智能体场景里,最好的做法是让异常信息按可读方式返回给大模型,让模型自己调整方案。

我在sorter.py里专门写了一个try-except大块,捕获目录不存在、权限不足、文件正在被占用等常见异常,然后返回类似“目录不存在,请检查路径是否正确”的中文提示。这样大模型拿到提示后,会主动猜测用户是否说了另一个路径,或者让用户重新给出一个有效目录。用户友好度提升很大。

4.5 可观测设计:每次调用留痕

最后一个决策点,也是所有进阶技能都要做的:每次调用必须留痕。日志、结构化输出、调用记录,属于智能体时代的“工程素养”。没有日志,你永远不知道模型到底怎么使用你的技能,也无法判断是描述文件写得不够好,还是脚本逻辑有问题。

我的做法是,每个技能至少输出一份结构化摘要。比如整理完目录后,脚本除了移动文件,还会打印一份聚合统计:一共找到多少文件、分成几类、移动到哪、跳过多少同名文件。这份摘要既给用户看,也作为日志的一部分留存。下次你发现自己设计的技能变得不好用时,翻一翻日志,问题往往一目了然。

5. 从“单个技能”到“技能体系”:给OpenClaw装上自己的工具箱

5.1 为工作流建技能库,而不是为功能建技能

做完下载目录整理技能后,我又陆续写了几个技能:会议纪要转结构化待办、图片批量压缩、项目文件备份、网络文章转本地 Markdown。它们表面上是不同功能,实际上都围绕我真实的工作流。专门给某个功能做一个技能,往往做完了就吃灰;围绕工作流做的技能,才会天天被调用。

所以我的建议是,建技能库之前,先记录自己一周内的高频重复动作。把那些“每周都要做、又不难做、只是麻烦”的事情挑出来,这才是技能库的第一批成员。技能数量不必多,只要每个都能稳定解决一个问题,价值就非常大。

5.2 技能间的调用与协作:让OpenClaw自己串联多个技能

单个技能只能解决一个小步骤,真正让人省心的是多个技能的串联。比如我现在可以告诉 OpenClaw:“整理我的下载目录,然后生成一份归档报告,最后把报告路径发给我。”它会依次调用download_sorter、generate_report和send_notice三个技能。

要让这种串联更稳定,我通常会把上一个技能的输出设计成下一个技能需要的输入格式。比如download_sorter输出的统计摘要,我会让它额外保存为一个 JSON 文件;generate_report技能只需要读取这个 JSON 即可。这样技能之间通过文件解耦,谁也不依赖谁,模型也可以更灵活地组装调用顺序。

5.3 技能的版本维护:一次好的更新来自真实使用记录

技能写出来不是终点,它会随你的使用习惯慢慢演化。我每周都会翻一下各技能的调用日志,重点关注两个指标:触发频率和失败率。如果某个技能两周都没被触发过,那不是模型不聪明,而是描述文件没写清楚,或者这个技能根本不在用户场景里。此时我会改写SKILL.md里的触发示例。

曾经有一个技能总是把用户的话理解成另一个相近技能,排查发现是我的两个技能 description 用了一大堆重叠词。把它们改成互相区隔的边界描述后,调用准确率立刻上来了。这就是版本维护的价值:不是改代码,而是持续校准大模型对技能的理解。

5.4 我的真实体验:从玩具到工具,也许只是一个网关的距离

整个 Skills 专项做完之后,我最大的感受不是“多了一堆自动化脚本”,而是 OpenClaw 终于成了我知道它下一步会怎么做的工具。它知道我的下载目录规则,知道我的归档命名习惯,知道哪些文件可以自动处理、哪些必须问过我之后才能动。这种确定感,是任何内置技能都给不了的。

如果你也想摆脱“玩具”状态,我的建议很简单:先挑一个你自己最头疼的重复性小任务,照着上面的结构写一个最简单的 Skills,跑通它。不用追求复杂,先把“整理下载目录”或“自动改文件名”这类小事做扎实。一旦你经历了从写规则到配置参数、再到模型自主调用并完成任务的全过程,你就会真正理解题目里那句话的分量——没有自己的 Skills,OpenClaw 只是一个玩具;而当你为它亲手装上第一个技能,它就迈出了变成工具的第一步。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询