OpenClaw 之SKILL开发踩坑
年前开发另一个OpenClaw SKILL,安装到OpenClaw 测试的时候,发现了很多Agent 的非预期行为。虽然OpenClaw不能称之为一个完美的产品,或许也很快会成为替代。但在get your hands dirty的过程中也还是积累的一些经验的。SKILL 本身并不重要,所以此篇会进行业务脱敏。
年前开发另一个OpenClaw SKILL,安装到OpenClaw 测试的时候,发现了很多Agent 的非预期行为。虽然OpenClaw不能称之为一个完美的产品,或许也很快会成为替代。但在get your hands dirty的过程中也还是积累的一些经验的。
SKILL 本身并不重要,所以此篇会进行业务脱敏
问题踩坑
-
权限问题
很多人都知道OpenClaw没有很好的权限和隐私控制,对于OpenClaw来说,它默认和它对话的是相同的用户。而这个用户有所有的权限。那么如果你的OpenClaw是一个群聊天bot,如果想限制某些文档只能被某些用户读/写/改,需要把权限显示地加入它本地的MEMORY.md文件作为长期记忆。 -
会话管理
虽然它有runtime session management,也就是说它会有一个sessionKey来区分对话,例如:agent:main:msteams:direct:78ca643a-1a52-4b0d-a541-d8010761b56a但是会发现它会聊错人。比如一个bot 安装在不同的群里,它会把群A的消息回复到群B里。这里可能是Agent 本身对会话的管理是不严谨的。对于这种不严谨我并没有处理。
如果我需要OpenClaw向某个channel发消息,它应该是map 到当前runtime里那个人对应的sessionKey, 然后做一个internal routing找到对应的integration session,比如我用的MS Teams,那么它会map到对应的teams channel id去发送,但是很显然,这种mapping它并不会做的很稳定。
另外,我问了OpenClaw如果我在会话中开了一个新的session,它的runtime SessionKey会不会改变?以下是它的回答:不会。
The sessionKey stays the same!
/new just clears the conversation history within your existing session — it doesn't create a new session container. The sessionKey is tied to this Teams DM thread itself, not to the conversation history.
To get a completely new sessionKey, you'd need a different channel/conversation entirely (like a new DM thread, different group chat, etc.).
-
时区问题
OpenClaw 默认使用服务器时间,即UTC时区。我本以为它可以读到我的本地时间,但是似乎并不会。如果在此前的会话中多次强调了自己的时区,OpenClaw会选择把它写入长期记忆。但是如果是完全新的session,或者新的agent instance,它默认还是使用UTC时间的。建议直接告诉它它的工作时区是什么。而对于群聊bot,我的建议是为每一个用户在工作区创建profile记录各自的时区。 -
定时任务
遇到时区问题其实是为了更好的处理定时任务。另外,OpenClaw的cron job是非常不稳定的,我测试下来发现它的定时任务流程是:用户用自然语言说要一个定时任务,例如每天早上10点给我发今天的天气。OpenClaw会创建一个JSON 来定义这个定时任务。然后按时执行。但是在实际情况里,它创建的这个JSON可能缺胳膊少腿,比如缺少delivery_to 字段,导致要么触发失败,要么投递失败。
不要用它的announce mode,让agent直接用message/cron tool。message tool负责消息投递,cron tool负责任务定时。不要用这种delivery: {mode: “announce”}
经验积累
-
JSON vs Markdown
大模型是基于自然语言的,虽然现在都是程序员用的比较深,但是我在这个过程中意识到模型和代码是完全不同的软件架构。我曾认为JSON 是比Markdown更好被模型理解的,但这其实是误解。对于LLM来说,它的训练语料大部分都是MD文档,所以对于模型来说,MD形式比JSON更加对模型友好。虽然可能目前的模型能力,和token消耗差不太多,但我的习惯还是“在意细节”。在结构性不是很强的情况下,prompt用MD 形式要优于JSON。 -
Generate Now -> Deliver Later
这种任务是为了,如果生成失败,用户可以提前知晓,不至于错过按时的delivery。那么也就是说需要逻辑去监控生成状态。可以另起用一个HEARTBEAT cron job,每隔一段时间检查一下生成状态。如果报错,则直接回复给用户。如果正常生成,则可以停止monitoring,只保留deliver的定时任务。 -
先预览再修改
由于OpenClaw的定位是助手,如果在开发测试SKILL的过程中出现问题,当然可以和它本身的LLM一起分析解决,但是由于它比较自负,经常在我问问题的时候,它自己边分析边就把KILL的文档修改了。这非常影响效率,最好让它提出修改方案,并进行预览,只有你同意的时候,才执行修改,不要给它开发太自由的修改权限,会非常难管理SKILL的版本。 -
Workflow不按预期SKILL定义执行
这是一个大问题。我本以为SKILL里的每一步写的清清楚楚就可以了,即使我自认为我的SKILL逻辑并没有特别复杂。但是实际上agent并不会完全按照SKILL操作。有以下几种情况:
- 全新的session,首次触发SKILL的时候,SKILL作为完整的context传给LLM的时候,LLM在推理时会进行“偏台”,它会自动聚焦到比较复杂的逻辑上,以解决问题为优先,把SKILL作为指导方案,而不是严格的照章办事。就像人拿了说明书,也会根据自己的理解操作一通一样。
- SKILL里有分支结构,情况A和情况B,且情况A是情况B的shortcut。而在用户请求中,包含了两个子任务,希望分别触发情况A和情况B分支。结果是agent在执行时用相同的B分支执行了,而没有执行A分支。模型会分析两个请求的相似性,如果它判断这两个任务差不多,则会自作主张地用同一条分支解决问题,而不会再费心分别进行处理,去走不同的分支。我在测验过程中,有一种强烈的感觉,就是模型会采取节能和省token的方案,也就是“偷懒”
总的来说,虽然这可能是每个模型的处理问题,但是一个SKILL 本质上不应该挑模型的,用户使用什么样的模型不应该成为SKILL的限制,它应该是普适的。
对于解决方案,应该没有绝对稳定的方案,毕竟它是LLM,不是机器指令,不过想到的有:
a) 多次纠正agent,它认错态度良好。但是这对于不了解SKILL的用户来说,会认为SKILL本身有问题,很难意识到是LLM没有根据SKILL定义走
b) 安装时即写入长期记忆,强制SKILL 必须按顺序执行
c) 优化SKILL的写法,比如把Agent 定义为状态机state-machine,定义好状态转换的条件,强制模型不会跳跃状态执行。而不是用简单的自然语言定义顺序。
和朋友聊最近的OpenClaw的种种缺陷的时候,朋友讲它的问题是太像人类了,哈哈。比如聊天发错群,不按规定办事,等等。假期我话了点碎片化时间去学习LLM的一些基础概念,有空也整理出来。作为一个软件开发工程师,模型的不严谨带来了一种很强的不可控性,这是与我之前的代码逻辑不同的。但是了解了模型的训练过程,就会知道它的本质是一个统计学猜测,这和机器指令是完全不同的。虽然AI很强大,在开发Agent 的工程中,我倾向于给模型较小的工作范围,严谨的逻辑还是用机器指令也就是代码来实现。模型虽然有自修复的能力,但是反复调用的token浪费造成的等待时间长、不稳定性是我难以接受的。
更多推荐


所有评论(0)