☰
OpenClaw技能系统:从能聊到能干活的关键进阶与实践排错
2026/9/28 5:18:16 网站建设 项目流程

OpenClaw 系列写到第四篇,技能系统是我一直想动笔的主题。前面聊完基础部署、通道接入和模型配置,OpenClaw 已经能跑起来,能接入飞书、Teams,能跟人正常聊天了。但不少朋友在这个阶段会陷入同一种困惑:OpenClaw 好像什么都会一点,又好像什么都没真正"交给我"——让它干活,它总是绕回到对话里跟我确认来确认去,离"自动完成任务"差着一大截。这个差距,基本都落在同一个点上:技能系统。

这篇我会把技能系统从原理到实现完整过一遍,包括一次最小技能是怎么写出来、如何注册和自检的,技能如何被会话机制驱动,以及为什么你会看到agent failed before reply: session file locked (timeout 60000ms)这类报错。最后会结合 Microsoft Teams、飞书和 Obsidian 的实际接入场景,把渠道输出时容易踩的坑一并处理掉。适合已经装好 OpenClaw、正在琢磨"接下来让它干什么"的读者。

1. 为什么技能系统是 OpenClaw 从"能聊天"到"能干活"的分水岭

先给一个我自己的定义:技能系统是 OpenClaw 给智能体挂载的"可插拔能力包"。它不是简单地把某个函数注册给模型,而是由清单(注册信息)、实现(代码或脚本)和上下文(触发规则、参数声明、依赖说明)组成的一个完整单元。这个单元一旦注册成功,OpenClaw 的 agent 就能在合适的时机调用它,完成一次具体的任务,然后带着结果回到对话里。

1.1 技能不是 Function Calling 的别名

很多人第一次听到"技能系统",第一反应是:"这不就是 Function Calling 换个名字吗?"我在刚开始接触时也这么想过,实际用下来发现两者完全是两个层面的东西。

Function Calling 是模型在一次对话里临时决定要调用某个工具的机制,重心在"调用"这一瞬间;技能系统则是一套可维护、可装卸、可复用的人员架构。你可以在技能里写清楚"什么时候该触发""需要哪些参数""没有参数时用什么默认值""依赖哪些外部文件",这些都独立于模型本身。模型只是技能的调度者之一,而不是技能的编写者。

拿我自己的经历举例。早期部署 OpenClaw 时,我试过在每个 prompt 里堆指令,让智能体记住 Obsidian 的路径、记住飞书怎么回复、记住本地数据库的查询方式。结果是维护成本直线上升——改一处逻辑,所有相关配置都得跟着动,而且不同渠道之间还会互相污染上下文。后来我把这些逻辑全部收拢成技能,每个技能只负责一件事,编译一次就能在多个渠道复用,改动时只需要动对应技能目录里的文件。从那以后我才觉得 OpenClaw 真正"稳了"。

1.2 三个真实场景,看懂技能系统的价值

  • 场景一:定时归档。每天早上让 OpenClaw 把 Obsidian 里没有被归档的日记,按周合并生成一份周报,并输出到指定目录。
  • 场景二:数据查询。飞书群里有人发了"查一下项目进度",agent 自动去本地数据库执行查询,返回结构化表格,而不是把 SQL 结果原样扔出来。
  • 场景三:跨渠道推送。在 Microsoft Teams 的某个频道里,周期性拉取外部任务列表的更新,把变更内容推给指定群组。

这三类任务,如果你不使用技能系统,要么靠手工输入一串复杂提示词然后一次次重复,要么把业务逻辑全部写死在主程序里——想换一个数据源、换一种输出格式,就得重新部署整个服务。技能系统把"任务定义""触发条件""执行逻辑"拆开了,任何一环都能独立改动,而且每加一个新技能,不需要修改 OpenClaw 主程序,只要在配置里多挂一个目录。

1.3 技能系统在 OpenClaw 里的两个支柱:声明式路由和会话驱动

技能系统真正跑起来依赖两个底层机制。

第一个是声明式路由。技能的注册信息里会声明它支持哪些触发方式:可以是关键词触发、正则匹配,也可以是模型根据意图自动选择。OpenClaw 在收到消息后先做路由解析,再决定调用哪个技能。这个设计的好处是技能之间互不感知对方的存在,你新增技能时,不需要在旧技能里做任何适配。

第二个是会话驱动。OpenClaw 每个会话对应一份 session 文件,里面保存了上下文的积累。技能执行过程中产生的中间状态、向用户输出、抛出的异常,全部会被记录到当前会话里。这就是为什么群里聊同一个话题时,智能体能记得前几轮的内容。但会话文件也带来一个隐患——如果两个请求同时对同一个 session 文件做读写,就可能触发锁冲突,也就是网上很多人搜过的那条session file locked报错。后面我会专门讲排查方法,这里先记住一个原则:技能执行要尽量设计成"短平快",不要长时间持有会话。

2. 开发环境准备:从 Windows 到 Ubuntu 再到云服务器,把底座铺平

说完了技能系统的设计逻辑,先把运行环境准备好。OpenClaw 本身跨平台支持,社区里 Windows、Linux、云服务器的安装教程都不少,这里我只挑容易出问题的地方讲。

2.1 三种部署场景的安装要点

  • Windows 场景。很多朋友用的是 windowshub 这类辅助工具一键安装,体验上类似应用商店。安装后建议重点检查两件事:一是 OpenClaw 的可执行文件目录有没有加入 PATH,否则后面加载技能时会找不到命令;二是注意权限问题,尽量不要把 OpenClaw 装在系统盘的高权限保护目录下,否则技能脚本写文件时容易被拦。
  • Ubuntu / Linux 场景。网上 openclaw ubuntu 安装教程和 openclaw 安装教程 linux 的内容大同小异,核心三步:下载二进制、初始化配置目录、启动服务。我个人的建议是用 systemd 把 OpenClaw 托管起来,这样不会因为 SSH 断开导致 agent 退出。很多人忽略的是 systemd 服务里的WorkingDirectory要指向 OpenClaw 的配置目录,否则技能脚本里的相对路径会集体失效。
  • 云服务器场景(以阿里云免费试用为例)。如果用的是阿里云服务器免费试用实例,一般 2 核 2G 就能跑基础技能,但建议给系统加一个小 swap 分区。原因很简单:技能加载时如果涉及模型调用和脚本编译,内存瞬时占用会出现一个峰值,没有 swap 的话 OOM 直接把进程杀掉,日志里还看不出任何异常。

2.2 把千问配置成 OpenClaw 的模型后端

技能系统本身不提供智能决策能力,它依赖一个模型后端来理解用户意图、决定是否触发技能。我在免费试用服务器上最常配的是千问,因为它提供 OpenAI 兼容接口,配置起来非常直接。

在 OpenClaw 的主配置里,模型相关的部分大致长这样:

model: provider: qwen model_name: qwen-plus base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 api_key_env: QWEN_API_KEY

注意几个细节:

  • base_url用的是 DashScope 的 OpenAI 兼容终点,字段名和 OpenAI 保持一致,OpenClaw 内部不需要做额外适配。
  • api_key_env意思是密钥从环境变量读取,而不是直接写在配置文件里。这样做的好处是技能代码、配置文件可以放进版本管理,不用担心密钥泄出去。
  • 如果内存紧张,可以把model_name换成一个更小的模型版本,技能触发场景对推理能力要求不高,够用就行。

2.3 选对 channel:同一个 OpenClaw 怎么决定把回复送到哪

OpenClaw 里的 channel 是"消息通道"的概念,常见的 channel 有飞书、Teams、Obsidian、终端等。你完全可以同时启用多个 channel,同一个技能在不同渠道里被触发后,回复会回到各自发消息的那个渠道。

channel 的路由配置大致如下:

channels: feishu: enabled: true webhook: your-feishu-webhook app_id: cli_xxx teams: enabled: true bot_id: your-teams-bot-id bot_password_env: TEAMS_BOT_PASSWORD obsidian: enabled: true vault_path: /home/user/notes

很多新手在这里会踩一个坑:多个 channel 同时开启后,agent 在 A 渠道聊到一半的消息,可能会被 B 渠道的问题打断,上下文互相串。如果你的 use case 是每个渠道独立工作,建议先只开终端 channel 调试,把所有技能都调通后,再逐步打开其他 channel。否则排查问题的时候,你很难分清是技能的问题还是 channel 路由规则的问题。

我在后面的实战里会再提到 channel 选择这件事,尤其是"agent 怎么选择 channel"这个问题在社区讨论里特别高频。先建立一个认知:OpenClaw 的 agent 默认遵循路由表,而不是自己随便挑一个 channel 回复。想让它"在飞书群里只回复飞书、在 Teams 里只回复 Teams",本质是把每个 channel 的上下文隔离开。

3. 技能运行的内部机制:一条消息从进来到技能执行前发生了什么

写第一个技能之前,得先把机制讲清楚。很多人的技能写得没问题,但死活触发不了,就是对中间链路不够了解。

3.1 技能触发的完整流程

一次完整的技能调用通常经过这么几个阶段:

  1. 用户在某个 channel 发出一条消息。
  2. channel 接入层把消息标准化,转成内部事件。
  3. 会话管理模块查找到当前 session,加载上下文文件。
  4. 意图解析模块根据当前模型判断用户想做什么。
  5. 技能清单匹配:如果命中了某条触发规则,就进入技能执行。
  6. 技能运行结束后,把结果以文本或结构化数据的形式返回。
  7. channel 输出层将结果格式化后发回原渠道。

这个过程里最容易出问题的是第 4 步和第 5 步之间的衔接。模型可能理解了意图,但技能清单里没有合适的技能;也可能技能清单匹配了,但模型的 prompt 上下文里没有足够的触发信息,导致 agent 选择直接对话而不是调用技能。

我的调试经验是:在技能清单里把description写得尽量"有画面感"。不要写"归档日记",而要写"当用户要求整理日记、生成周报、汇总每日记录时,调用此技能归档指定目录下的 md 文件"。因为模型是根据 description 来做匹配的,你描述得越具体,匹配准确率越高。

3.2 深入理解 session 文件锁和 60000ms 超时

网上有个高频搜索词:agent failed before reply: session file locked (timeout 60000ms)。第一次看到这行报错的人都会慌,因为它看起来像是 agent 崩了。实际上它说的是:当前会话的文件锁无法在 60 秒内获取。

在 OpenClaw 里,每个 session 对应一个文件,文件的读写需要一个锁机制来避免并发冲突。如果你同一个 agent 同时收到多个 channel 的消息,或者一个技能执行得太慢还没结束,另一个请求又来了,后一个请求就可能等待锁释放。等待时间超过 60000ms,就抛出这条错误。

引发这个问题的常见原因有三个:

  • 同一份会话文件被多个进程同时打开。最常见的是你手动启动了第二个 OpenClaw 实例,却没有关闭旧的。
  • 某个技能脚本卡死,导致会话上下文一直处于"执行中"状态,锁迟迟不释放。
  • 会话目录里有残留的.lock文件,进程异常退出后没有清理掉。

排查路径我放在后面第 6 节详细介绍,这里先给一个应急方案:确认没有重复进程后,去会话目录把.lock后缀的文件备份后删除,再重启 OpenClaw 进程,一般能恢复正常。但要记住,这不是根治办法,根治要靠技能尽量无状态化、执行超时可控。

3.3 agent 怎么选择 channel:路由规则和典型误区

"openclaw agent 怎么选择 channel"这个热搜词背后,其实藏着两种需求:一是问配置层面怎么决定消息走哪个渠道,二是问运行时 agent 为什么有时不按预期选择渠道。

运行时选择的逻辑很简单:agent 只有在收到该 channel 的消息或事件时,才会把该 channel 视为可回复的候选。它不会自己去别的 channel 找活干,更不会主动跨渠道回复。如果你的 agent 突然在 A 渠道回复了 B 渠道的问题,那多半不是 agent 自己做主,而是两个渠道的配置里关联到了同一个 session,上下文被共享了。

所以想让 agent "选对" channel,核心工作是做好 session 隔离。你可以按 channel 维度分配不同的 session 前缀,比如飞书的消息都进session_feishu_*,Teams 的消息都进session_teams_*。这样即使两个渠道同时来消息,互不排队,也不会出现"锁等待"。

4. 从零写一个能用的技能:以 Obsidian 笔记整理为例

理论讲完,直接上手。我选一个非常典型且容易验证的场景:让 OpenClaw 把 Obsidian 里的日记按周归档成周报。这个技能麻雀虽小,但覆盖了清单、触发规则、参数声明、Python 实现和注册自检的完整链路。

4.1 技能目录结构和清单文件

在 OpenClaw 的技能目录下,每个技能是一个独立文件夹。以obsidian-archiver为例:

skills/ obsidian-archiver/ skill.json run.py requirements.txt

skill.json是技能的身份证,我写下这样一个最小版本:

{ "name": "obsidian-archiver", "description": "用户要求整理日记、生成周报、汇总每日记录时,将指定目录下的日记文件按周归档", "version": "0.1.0", "agent": { "triggers": ["归档", "整理日记", "周报"], "auto_trigger": true }, "parameters": [ { "name": "vault_path", "type": "string", "description": "Obsidian 仓库根目录", "required": false } ] }

几个字段我觉得值得多解释一句:

  • triggers是关键词触发列表,命中任意一个就会优先让技能处理。但注意,触发关键词不等于技能就一定会被调用,最终决定权还在模型解析那一步。
  • auto_trigger设为 true 时,agent 会自行判断是否调用技能,不一定要用户说出明确关键词。
  • parameters用于声明技能需要的外部参数,模型在调用技能前会尝试从对话上下文里提取这些值。提取不到时,技能内部要处理参数缺失的默认值。

4.2 核心逻辑实现

run.py是技能的执行入口。我习惯让它从标准输入接收一个 JSON 参数对象,处理完把结果以 JSON 字符串输出到标准输出。OpenClaw 会捕获这个输出,并作为技能的执行结果返回给会话。

#!/usr/bin/env python3 import json import re import datetime from pathlib import Path from collections import defaultdict def run(config): vault = Path(config.get("vault_path", "~/notes")).expanduser() diary_dir = vault / "Diary" weekly_dir = vault / "Weekly" weekly_dir.mkdir(exist_ok=True) files = list(diary_dir.glob("*.md")) if not files: return json.dumps({"ok": True, "archived": 0, "message": "no diary files"}) groups = defaultdict(list) for f in files: m = re.match(r"(\d{4}-\d{2}-\d{2})", f.stem) if m: date = datetime.date.fromisoformat(m.group(1)) iso = date.isocalendar() key = f"{iso[0]}-W{iso[1]:02d}" groups[key].append(f) for week, items in groups.items(): dest = weekly_dir / f"{week}.md" lines = [f"# Week {week}\n"] for item in sorted(items, key=lambda x: x.name): content = item.read_text(encoding="utf-8") lines.append(f"## {item.stem}\n\n{content}") dest.write_text("\n".join(lines), encoding="utf-8") return json.dumps({"ok": True, "archived": len(files), "weeks": len(groups)}) if __name__ == "__main__": payload = json.loads(input()) print(run(payload))

这个实现非常简单,但已经具备了一个技能该有的健壮性:传参缺失时有默认值;目录不存在时会自动创建;没有日记文件时会明确给出提示,而不是报错退出。脚本短小的原因是它把大量逻辑交给模型去理解触发条件,脚本本身只做稳定的文件操作。

4.3 注册与自检

技能放进目录后,OpenClaw 通常会在启动时自动扫描目录并加载。如果你正在运行 OpenClaw,需要重启一次进程或者触发技能热加载命令。重启之后,先用终端 channel 做自检。

终端输入"帮我整理一下日记",正常情况下 agent 应该命中技能,执行完成后返回类似这样的结果:

{"ok": true, "archived": 15, "weeks": 2}

如果返回的不是 JSON 而是一段对话文本,说明技能没被真正调用,agent 只是在纯聊天。这时优先检查skill.json的description是否清晰,其次看run.py的入口逻辑是否符合 OpenClaw 约定。千万不要去怪模型笨,绝大多数情况是技能注册信息写得不够准确。

4.4 新手最容易犯的四个错误

  • 路径权限不对。技能脚本的目标目录如果是系统目录,OpenClaw 运行时没有写权限,脚本会静默失败。建议技能的操作路径统一指向配置目录或用户目录下。
  • 依赖环境不一致。requirements.txt里写了第三方库,但没有在 OpenClaw 所在环境里安装。技能加载时可以 import 失败,log 里不一定有显眼报错。
  • 触发词和业务强绑定。如果你把触发词写得过于口语化,换个说法它就认不出来了。触发词只做初筛,真正的匹配还是要靠 description。
  • 技能没有独立目录。把多个技能的代码堆在一个目录下,会导致 OpenClaw 的清单解析混乱,技能时好时坏。一个目录只放一个技能,目录名就是技能名。

5. 渠道接入实战:Teams、飞书和输出截断问题

技能写好了,接下来最重要的是把它接到真实工作流里。我选两个最常见的渠道展开讲:Microsoft Teams 和飞书。

5.1 从零接入 Microsoft Teams:机器人注册与路由校验

OpenClaw 接入 Microsoft Teams,本质上是在 Teams 里创建一个机器人应用,再把机器人的身份凭据交给 OpenClaw 去连接。

步骤大致是:先在 Azure 门户或 Teams 开发者平台注册一个机器人,拿到 Bot ID 和 Bot Password;然后在 Teams 应用管理里给机器人添加适当的权限范围;最后把凭据填进 OpenClaw 配置中,像我在 2.3 节里给出的那段channels.teams配置。

这里最容易翻车的点有两个:

  • 密码不是拿来就能用。Teams 的 Bot Password 经常带有特殊字符,直接写进 YAML 容易被转义解析错误。我建议一律通过环境变量注入,配置里只写变量名。
  • 消息回复方向搞反。在 Teams 里,机器人收到的消息和它发出的消息是两个概念。技能执行完后,OpenClaw 会以机器人的身份向同一频道回复。如果你的技能修改了文档、生成了文件,尽量把摘要发到频道就行,没必要把整个文件都推上去。

Teams 对单条消息大小有限制。如果一个技能返回 8000 字的报告,Teams 会自动截断,用户看到一半内容没了,还以为技能出 bug 了。这不是技能的问题,是输出层的限制。后面 5.2 节会讲通用解法。

5.2 飞书输出被截断:为什么总在技能场景里发生

"openclaw在飞书输出容易被截断"这个热搜词,我太有共鸣了。我之前跑一个数据统计技能,一次返回 8000 字,结果飞书群里的消息只显示前两千字,后半部分直接消失。

飞书截断的根因在于消息卡片/文本长度有限制,当技能返回的内容超过上限时,飞书要么截断显示,要么直接报错拒收。以前纯聊天场景很少遇到,因为聊天回复普遍在几百字以内,但技能系统一旦跑起来,你会经常遇到动辄几千字的输出。

解决思路有三个,我按推荐程度排个序:

  1. 技能端做摘要。返回给渠道的内容只保留结论、关键数字和建议,完整数据写入附件或本地文件。这是最健康的做法,对用户也友好。
  2. 输出分段。在技能内部把超长内容拆成多段,每段单独通过渠道接口发送。这个方案不用改模型,适合快速解决燃眉之急,但发送多段消息体验略碎。
  3. 启用长文本模式。部分渠道有专门的长文本发送接口,可以把完整内容作为附件发送。Obsidian 和飞书都支持类似能力,但需要你在 channel 配置里显式开启。

我个人建议第一个方案为主,第二个方案保底。永远不要指望一个渠道能承载无限长的输出,技能设计本身就应该遵循"返回摘要、存储细节"的原则。

5.3 让一套技能服务多个渠道的实践

如果你的 OpenClaw 同时接入了 Teams、飞书、Obsidian,同样的技能可以共享,但要注意输出格式的适配。我的做法是在每个技能里接收一个channel参数,根据渠道名称选择输出格式。

比如同一个查询技能,在飞书群里输出 Markdown 表格,在 Teams 里输出 Adaptive Card 的 JSON 结构,在 Obsidian 里则直接追加到笔记文件底部。这样一套逻辑复用,输出层单独适配,比每个渠道各写一套技能要轻松得多。这也是我强力推荐"声明式路由"的原因——技能本身只关心执行,不需要理会消息从哪来、要到哪去。

6. 线上部署后的调试与排错:从 60000ms 超时到日常运维

技能上线之后,真正的考验才开始。这一节把最常遇到的线上问题按"症状-根因-处理"的方式梳理一遍。

6.1 “session file locked” 的完整排查链路

先还原一个典型场景。某天早上,飞书群里有人 @agent 让它跑一下日报统计,OpenClaw 半天没反应,日志里出现:

agent failed before reply: session file locked (timeout 60000ms)

我的完整排查步骤是这样:

  1. 先确认进程数。执行ps -ef | grep openclaw查看是否有多个实例在跑。如果之前用nohup启动过,后来又用 systemd 启动了一遍,就会有双进程同时监听同一份配置。双进程必然抢会话文件锁,这种是最好排查的。杀掉旧实例,保留 systemd 托管的那个。
  2. 查看会话目录里的锁文件。OpenClaw 会话目录一般在配置目录下的 sessions 里。用ls -la找.lock后缀的文件。正常运行时这些锁文件应该会随会话结束自动释放,如果发现有残留且时间戳停在很久以前,说明之前某个进程是被强杀的,锁没来得及清理。
  3. 检查技能日志。如果锁文件没有残留、进程也只有一份,那问题大概率出在技能执行时间过长。日志里如果能看到技能业务逻辑开始打印,却没有结束标记,就说明技能脚本卡住了。我之前遇到过一次是技能里做了网络请求,第三方接口迟迟不响应,导致整个会话文件一直被锁住。
  4. 修复并验证。删除残留锁文件(先备份),重启 OpenClaw,然后用终端 channel 向同一个 agent 连发两条消息,确认不会再次报错。如果复现,就进入了代码层修复环节。

重点说一下预防方案。技能设计上要把 IO 操作全部加上超时控制。Python 里用requests时设置timeout,文件读写时控制并发。技能本身是无状态的,任何一次调用都不应该阻塞整个会话。

6.2 技能卡死的高发原因归类

根据我观察到的经验,线上技能卡死的主要原因有以下几类:

  • 外部服务无响应。技能里调用了一个 API,上游服务 hang 住,技能一直等。处理方式是为所有外部请求统一加timeout,并设置重试上限。
  • 死循环未加退出条件。技能处理一批文件时,如果代码里有个while循环,条件永远为真,就会一直跑。建议在技能脚本里加最大执行次数或最大处理文件数。
  • 模型解析步骤和技能执行步骤相互等待。个别情况下 agent 先请求模型判断意图,技能执行结束后又把结果送回模型做二次总结,模型响应慢,整体执行时间拉长,流量高峰期就容易触发 60s 锁等待。

6.3 OpenClaw 和 WorkBuddy 的选型经验

很多人在搜索"openclaw和workbuddy哪个好",说明大家在做智能体框架选型。我个人的看法是,这两个工具定位并不完全一样。

OpenClaw 的优势在于灵活性:技能目录是独立模块,你可以随时写脚本、挂服务、改触发规则,甚至把一套技能迁移到另一台服务器上复用。适合喜欢自己掌控逻辑、需要频繁自定义能力的人。

WorkBuddy 更偏向开箱即用,配置更简单,但个性化能力相对受限。如果你的核心诉求只是聊天和几个预设功能,WorkBuddy 上手更快;如果你要长期维护一套业务技能,比如 Obsidian 归档、数据库查询、跨渠道推送,OpenClaw 的技能系统会给你更大的操作空间。

我的建议是:不要被框架名带着跑,先想清楚你要做多少个技能、哪些渠道、哪些逻辑需要和你现有系统打通,再做选择。框架只是载体,技能才是资产。

6.4 日常运维的两个习惯

  • 日志分类输出。OpenClaw 自身的日志和技能日志分开维护。技能脚本里可以用独立的日志文件,记录每次调用的参数、执行时长和输出摘要。出现问题的时候,先看技能日志,能过滤掉大量信息。
  • 定期备份配置目录。技能是资产,配置是基建。把整个配置目录纳入版本管理,技能改动前先提交一个 base。线上改技能时,就算改坏了也能快速回滚,不需要从零排查。

7. 让技能系统真正运行的四个习惯

最后的篇幅没有新知识,分享几个我在实际部署中固化下来的习惯,也算是一个阶段性的总结。

第一个习惯:一个技能只做一件事。技能最忌讳变成大杂烩。一个技能里面又归档笔记又查询数据库又发送消息,看起来高效,实际上是把自己活活困死。任何一处改动都可能影响其他环节,调试成本会指数级上升。

第二个习惯:所有可配置项都暴露成参数。我在 4.1 节里给vault_path提供了默认值,其实这就是一个最小化的参数化设计。不要把路径、密钥、目标频道直接硬编码在技能里,让它们作为参数从配置里读取,这样同一个技能才能在不同环境间迁移复用。

第三个习惯:输出结构化数据。技能返回给 agent 的结果,尽量使用 JSON 等机器可读格式,让 agent 能根据结果决定下一轮动作。纯文本输出虽然人看着舒服,但对模型后续处理不友好。比如归档技能返回{"archived": 15, "weeks": 2},agent 就能直接告诉用户"已归档 15 篇,生成 2 份周报",而不是把整个文件内容念一遍。

第四个习惯:每个技能都写下可用的触发示例。我会在技能的description末尾附上一两个典型句式,比如"触发示例:整理一下本周日记"。这不仅能提高触发准确率,也是在帮未来的自己回忆这个技能当初是为什么写的。

一次技能系统的开发周期通常不需要太长,但把它做得好用、可维护、不轻易卡死,靠的是上面这些细碎的设定。我的建议是不要追求一开始就写一个复杂的超级技能,先有一个能跑通的最小闭环,让 OpenClaw 真正完成一次"自动干活",然后再在这个基础上迭代。技能系统的价值不是单次执行得多么惊艳,而是当你积累了几十个技能之后,OpenClaw 会变成一个真正懂你的工作伙伴——你只需要告诉它你想做什么,剩下的事情,交给技能去完成。

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

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

立即咨询