ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

OpenClaw自定义Skill开发实战:用Python为智能体打造工具技能

OpenClaw自定义Skill开发实战:用Python为智能体打造工具技能 最近群里聊 OpenClaw 的人越来越多了大家都管它叫“龙虾”而这套东西最让人上头的点就是 Skill 机制。简单说OpenClaw 是一个偏执行侧的智能体框架模型负责“想”Skill 负责“做”。框架本身会带一些默认技能可真到自己的业务场景里你会发现大部分时候都得自己动手写 Skill。用 Python 给 OpenClaw 写自定义 Skill是当前门槛最低、生态最顺手的一条路——Python 社区里轮子多你只要把一个业务功能封装成 Skill 的标准格式Agent 就能在对话里自动调用它。这篇文章不是给你念官方文档而是按照我自己从零摸一遍的经验走先拆 Skill 的运行逻辑再完整写一个能落地的系统信息采集技能最后聊注册、调试和踩坑。如果你正准备给 OpenClaw 加技能或者只是好奇这种“模型 工具插件”的模式怎么玩这篇文章应该能帮你少走不少弯路。1. Skill机制拆解龙虾的“技能插件”到底是怎么跑的1.1 Skill的本质一个目录、一份元信息和一段执行逻辑很多人第一次看到 OpenClaw 的 Skill 目录会懵一个文件夹里放一个.py文件、一个.yaml文件这算什么“技能”其实它的设计思路跟 IDE 插件、浏览器扩展很像。每个 Skill 就是一个自包含的模块向 Agent 暴露两样东西元信息告诉 Agent“我会什么、需要什么参数”执行函数告诉 Agent“你调我之后我能具体做什么”。我在实际使用中习惯把 Skill 看作“给大模型配的一把专用工具”。模型本身的强项是语义理解和生成弱项是执行确定性的计算、读本机状态、调领域接口。Skill 正好补上这块。比如你问模型“看看这台机器内存剩多少”模型如果只靠训练知识它根本不知道你这个环境里真实的内存占用但如果你挂了一个system_info技能模型就会决定调用它把工具返回的真实数据整理成回答。所以理解 Skill 不能只看代码要把它放进 Agent 的工作链路里看用户请求进来模型判断需要外部能力通过元信息匹配到合适的 Skill再按参数约定触发执行函数拿到返回值后继续组织语言。这里面的核心设计点就是元信息能不能让模型“一眼看懂”。很多新手写 Skill 只顾着写实现结果模型根本不知道什么时候该调问题就出在元信息写得太抽象。1.2 开发前的环境准备动手写 Skill 之前先把环境捋清楚。我的建议是不要直接往系统 Python 里装东西而是为 OpenClaw 单独准备一个虚拟环境。原因很简单OpenClaw 本身依赖不少库你写 Skill 时还会加一些自己的依赖如果全堆在系统环境里没过多久就会出现“装了这个包那个包被降级”的连锁反应。基础环境有这么几样Python 3.8 或更高版本。OpenClaw 生态目前对 3.10/3.11 的支持最稳如果你还没装 Python直接装 3.11 就行。OpenClaw 本体。安装方式去官方仓库看就好不同版本的安装命令会变我不建议死记硬背命令重点是把它的skills目录找到。一个你顺手的编辑器。VSCode 或者任意文本编辑器都行Skill 本质上就是一个目录里的几个文件不需要重型 IDE。代码版本管理工具。哪怕只有你自己开发也建议建一个 git 仓库Skill 的迭代速度比你想象中快。装完以后先别急着写代码在命令行里跑一下 OpenClaw 自带的示例 Skill确认“框架主流程”是通的。这一步特别重要因为它把“框架问题”和“你的代码问题”隔离开如果示例 Skill 都跑不通那就是环境问题如果示例能跑通而你的 Skill 不行那问题多半出在自己写的代码里。1.3 命名与设计原则在我看过的二三十个 Skill 插件里最影响使用体验的不是代码写得好不好而是命令命名。OpenClaw 里模型的调用决策依赖元信息里的name和description如果你的技能叫data_processor描述写“一个数据处理模块”模型面对用户问题“帮我把这段文字里的电话号码都提取出来”很难确定是不是该调你这个技能。我自己定了几条命名规范供你参考技能名用动词开头比如fetch_weather、send_email、check_system让模型一眼看出动作。描述里写清楚“什么场景用、输入什么、输出什么”不要写空话。比如描述写“当用户想查看本机CPU/内存/磁盘使用情况时使用此技能获取系统信息并返回结构化数据”模型命中率会高很多。一个 Skill 只做一件事。有些朋友喜欢写一个大而全的 Skill里面有十几个函数看似方便但模型在调用时会很犹豫参数也容易传错。宁可多做几个小 Skill也别憋一个大怪物。2. 手把手写第一个Python Skill2.1 场景选择先做一个系统信息采集技能我在给新手建议时从来不让他们上来就写“调用外部 API”或者“操作数据库”这种带网络和服务依赖的技能而推荐先写一个能“自我感知”的技能。这里我就用系统信息采集做例子它有几个好处只用标准库就能跑通最小版本方便确认 Skill 机制本身没问题返回结果是真实数据调试时有明确预期后续想加 psutil 增强版也顺理成章。我们这个技能要实现的能力是当用户问“这台电脑什么系统”“内存够不够”“磁盘还剩多少”时Agent 能调用一个 Python Skill返回 JSON 格式的系统信息。为了让过程可感我会先实现一个“标准库版”再升级成“psutil 增强版”这样你能看出来一个技能是怎么从零到一演进的。2.2 目录与元信息文件怎么写先看看 Skill 的标准目录结构。在 OpenClaw 的skills目录下建一个文件夹名字就是技能名里面放代码和元信息skills/ └── system_info/ ├── skill.py └── skill.yamlskill.yaml是模型感知 Skill 的第一入口相当于“技能说明书”。我一般会这样写name: system_info version: 1.0.0 description: 获取本机操作系统、CPU、内存、磁盘等基础信息。当用户询问系统版本、内存占用、磁盘剩余空间时使用。 python: 3.8 parameters: - name: detail type: boolean required: false default: false description: 是否输出详细的CPU占用率和内存/磁盘使用情况这里有几个细节容易踩坑。第一个是description别写太短写清楚触发条件模型才能正确决策第二个是parameters里的type一定要和代码里的逻辑对应否则模型会传错类型第三个是version字段我要求自己每改一次就升一个小版本这样出问题时能排查是不是缓存了旧版本。2.3 Skill代码标准库版本与psutil增强版skill.py部分我一般会定义一个Skill类然后实现run方法。OpenClaw 各个小版本的调用约定可能略有差异但“定义类、实现run()”这个模式在多数 Agent 框架里是通用的你只需要把函数名对牢自己用的版本就行。先看最简单的版本import platform import json import socket class Skill: name system_info version 1.0.0 description 获取本机操作系统、CPU、内存、磁盘等基础信息 def run(self, **kwargs): detail kwargs.get(detail, False) info { os: platform.system(), os_version: platform.version(), machine: platform.machine(), hostname: socket.gethostname(), python_version: platform.python_version(), } if detail: try: import psutil info[cpu_usage_percent] psutil.cpu_percent(interval1) memory psutil.virtual_memory() info[memory] { total_gb: round(memory.total / 1024 ** 3, 2), available_gb: round(memory.available / 1024 ** 3, 2), usage_percent: memory.percent, } disk psutil.disk_usage(/) info[disk] { total_gb: round(disk.total / 1024 ** 3, 2), free_gb: round(disk.free / 1024 ** 3, 2), usage_percent: disk.percent, } except ImportError: info[warning] psutil not installed, only basic information returned return json.dumps(info, ensure_asciiFalse)我解释几个设计决策。第一detail参数默认是False但psutil是懒加载的也就是说只有用户明确要求详细信息时这个库才会被导入。这么做是为了让基础调用不依赖第三方库降低失败率。第二返回值我用json.dumps(..., ensure_asciiFalse)确保中文不会被转成\u开头的一串转义符否则在 Agent 端看起来非常不直觉。第三interval1是cpu_percent的参数表示采样一秒能拿到一个相对真实的瞬时 CPU 使用率而不是 0.0 这种无意义值。2.4 参数传递与返回值约定写 Skill 的时候最怕框架约定的输入输出接口和你自己写的函数对不上。我强烈的建议是统一用**kwargs接收参数统一返回 JSON 字符串。拿**kwargs的原因在于 Skill 可能被框架用多种方式调用有的版本会传入模型填好的命名参数有的会传一组字典你用kwargs.get(detail)取值无论哪种都能应对。返回值那里也容易迷糊。有些框架希望run返回字符串因为字符串可以直接塞回 Agent 上下文有些框架希望返回 dict框架自己帮你序列化。你没法保证所有版本一致时就按项目文档来。我的默认选择是返回字符串因为它的兼容面最广而且可以在返回前手动控制序列化过程。还要注意一个设计细节返回内容不要让 Agent“看不懂”。比如返回一个套娃式的嵌套 JSON模型解析起来费劲回答自然容易出错。我习惯把数据打平到两级以内像上面memory、disk这种对象里包含基础字段就是够用的深度。3. 把Skill装进OpenClaw并完成本地联调3.1 安装路径与自动发现写完了代码和元信息接下来就是把 Skill 放进 OpenClaw 能扫到的地方。不同版本的 OpenClaw 对 Skill 目录的扫描路径不完全相同但大体逻辑没变有一个根目录叫skills下一级每个子目录代表一个 Skill框架启动时遍历这些目录读取skill.yaml并把skill.py里的类实例化注册到技能库里。我用过一个笨但有效的办法来确认路径对不对先在skills目录下建一个空目录再在里面放一个只返回ping的最小 Skill启动 OpenClaw 看日志里有没有出现这个技能名。如果日志里都找不到先查目录层级很常见的问题是有人把system_info.py直接扔在skills下面而不是放到skills/system_info/skill.py。另外如果你用了配置文件来管理技能白名单记得在配置里把system_info加进启用列表。这一步在不同框架版本里差异挺大有的默认全量加载有的默认只加载显式声明的技能。看日志最直接加载失败时通常会有 “failed to load skill” 之类的报错跟着提示改就好。3.2 用Ollama跑本地模型做端到端验证OpenClaw 比较大的亮点之一就是可以接本地模型玩常见方案是 Ollama 部署一个开源模型比如 qwen 或者 llama 系列然后让 OpenClaw 通过本地模型做推理。这样整个链路不依赖外部服务适合在离线环境或本地开发机里反复验证 Skill。我的端到端测试流程是这样的先确保 Ollama 服务启动然后在 OpenClaw 的模型配置里把地址指向本地 Ollama重启框架。接着在对话里输入一句自然语言比如“查一下这台电脑的磁盘使用情况”。如果配置正常模型会自己判断需要调用system_info技能然后你应该能在日志里看到技能命中、参数填充、执行结果返回这几个阶段的记录。这里有个常见现象本地小模型在参数填充上不如大模型准确它可能会漏掉detail参数或者把布尔值传成字符串“True”。所以在设计 Skill 时参数尽量给默认值并且代码里要有容错。比如把kwargs.get(detail, False)改成能兼容字符串真值的写法可以写成detail str(kwargs.get(detail, False)).lower() in (true, 1, yes)这样模型再怎么传错你的代码也不会崩。3.3 调试三板斧单测入口、日志隔离、JSON输出检查在把 Skill 交给 OpenClaw 之前我建议你把它当作普通 Python 模块先单独测试一遍。我以前直接往 Agent 里调试一报错就挣扎半天分不清是我代码的问题还是框架调用的问题。后来养成了习惯每个skill.py底部都留一个if __name__ __main__:入口里边调用Skill().run()先当作脚本跑。调试时的三条经验单测入口的模拟要贴近框架传参。比如框架传参数可能是字典你就在入口里构造一个字典传进去不要直接用函数默认参数测试。日志要能区分“技能执行日志”和“模型思考日志”。我的做法是在 Skill 代码里只往 stdout 输出最终结果任何中间日志一律写到文件或 stderr避免污染返回内容。JSON 输出要做一次合法性检查。写完json.dumps之后再用json.loads读回来确认没有因为变量类型问题导致序列化失败。这一步可以作为“金标准”在命令行能正确输出 JSON再接 OpenClaw 联调。我见过太多人跳过了这个步骤直接在 Agent 里报错最后排查一圈发现就是 Python 序列化时遇到set对象这种锅不该让 Agent 背。4. 常见问题与排查实录4.1 高频报错速查表把我在实际使用中遇到过的、以及在开发群里看别人踩过的坑整理一下做成一个速查表可以收藏备用。现象可能原因处理办法框架日志里没有 Skill 加载记录目录层级不对、技能未启用、元信息格式错误检查skills/技能名/skill.py结构确认配置里已启用Agent 一直不选择调用技能元信息描述不具体模型无法判断触发场景重写description增加触发条件和示例场景调用后返回内容为空执行发生异常但异常信息被吞掉在run里给执行逻辑包try/except打印堆栈到日志ModuleNotFoundErrorSkill 代码引用了未安装的依赖在 OpenClaw 的 Python 环境里安装依赖或用懒加载逻辑中文输出乱码Windows 下控制台编码与 Python 默认编码不一致设置PYTHONIOENCODINGutf-8返回 JSON 时指定ensure_asciiFalse技能返回了但 Agent 说没结果返回内容里混了日志输出结构不符合模型预期检查 stdout 是否只有 JSON格式确保能被json.loads解析这个表看起来简单却是我屡次“怀璧其罪”的总结。尤其是第一行新手十有八九会折在目录结构上不是你代码写错是文件放错位置。4.2 三个容易被忽略的坑第一个坑是Skill 执行环境的 Python 和 OpenClaw 的 Python 不是同一个。如果你用系统自带的 Python 跑了pip install psutil但 OpenClaw 跑在虚拟环境里那 Skill 照样找不到模块。排查方法是启动前在配置里打印sys.executable确认到底走的哪个解释器。第二个坑是缓存。有一些版本会缓存 Skill 信息你改了skill.py但它加载的还是旧代码。我改代码后必做的动作是清楚缓存目录并重启框架别省钱。第三个坑是权限问题。不是所有环境都允许你读取完整系统信息尤其在 Linux 容器里磁盘统计可能只有挂载点的一部分。这种问题在 Python 层没有解只能在 Skill 输出里加一个warning字段保证 Agent 不会拿到 false 数据。4.3 Windows和Linux部署差异开发环境如果是 Windows到了 Linux 服务器上跑有两点要提前处理。第一是路径分隔符skills目录扫描在 Windows 下用反斜杠Linux 下用正斜杠代码里不要硬编码任何路径尽量用pathlib去拼。第二是权限模型Linux 下读取磁盘信息和进程信息有时需要 sudo所以如果你的 Skill 里有这些操作要提前想好运行 OpenClaw 的服务账号权限。Windows 上还有一种常见坑就是 PowerShell 的默认编码和 Python 输出的 UTF-8 不兼容。我自己碰到过脚本单独运行没问题接入 OpenClaw 后中文信息全变成乱码。后来在启动脚本里加了环境变量才解决。这个问题不算复杂但一旦碰上会浪费一下午在这里提个醒。5. 我的建议与扩展方向5.1 新手的入场顺序如果让我给新手排一个开发路线我的建议是这样的先写一个不带参数、只返回“hello world”的最小 Skill跑通注册和调用链路然后给这个最小 Skill 加一个参数体验一下参数传递如何影响输出再把它替换成有实际价值的系统信息采集技能体验完整业务闭环最后再去尝试 API 类、数据库类、文件操作类的复杂技能。这条路径看起来慢其实最快。因为你每一步都只增加一个变量出了问题能立刻定位。反观一上来就想写个大而全的电商助手、GIS 分析助手结局往往是卡在环境问题上连“我的代码到底有没有被执行”都不知道。5.2 值得扩展的方向Skill 这个机制本身是中性的任何领域能力都可以封装成技能。我目前看到社区里有人在写 GIS 空间分析技能把常用空间操作包装成 Skill 给 Agent 调用也有做电商场景的把商品查询、价格计算做成技能ROS2 方向也有人在做尝试想通过 Skill 让 Agent 间接控制机器人仿真环境。这些尝试的共同点就是把原本需要手动写脚本的领域逻辑变成模型可以按需调用的“工具”。往深了做还有两个方向值得关注。一个是多技能协作比如先调用系统信息技能拿到本机状态再根据状态决定要不要调用另一个清理技能这种“技能编排”会极大丰富 Agent 的行为能力。另一个是技能参数复杂化让 Skill 支持结构化参数对象而不是一层的键值对这能让技能适应更复杂的业务输入。最后分享一个小技巧调试 Skill 时一定要让 Agent 肉眼可见地拿到结果。我的做法是先在单独测试入口里把返回的 JSON 字符串写到一个临时文件确认文件内容完全正确再接 OpenClaw 联调。等这一步稳了再去做参数变形和异常分支。按这个顺序走我基本没再遇到过“卡在两套环境之间”的难题希望你也能一次跑通。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表